]> www.infradead.org Git - users/rw/ppcboot.git/commitdiff
Patch by James Dougherty, 12 Aug 2002:
authorwdenk <wdenk>
Tue, 13 Aug 2002 12:11:51 +0000 (12:11 +0000)
committerwdenk <wdenk>
Tue, 13 Aug 2002 12:11:51 +0000 (12:11 +0000)
Support for Broadcom BCM56xx PPC BMW Board
Added Broadcom BCM570x Gigabit Ethernet for MPC824x systems

40 files changed:
CHANGELOG
MAKEALL
Makefile
README
board/bmw/Makefile [new file with mode: 0644]
board/bmw/README [new file with mode: 0644]
board/bmw/bmw.c [new file with mode: 0644]
board/bmw/bmw.h [new file with mode: 0644]
board/bmw/config.mk [new file with mode: 0644]
board/bmw/early_init.S [new file with mode: 0644]
board/bmw/flash.c [new file with mode: 0644]
board/bmw/m48t59y.c [new file with mode: 0644]
board/bmw/m48t59y.h [new file with mode: 0644]
board/bmw/ns16550.c [new file with mode: 0644]
board/bmw/ns16550.h [new file with mode: 0644]
board/bmw/ppcboot.lds [new file with mode: 0644]
board/bmw/serial.c [new file with mode: 0644]
common/board.c
common/cmd_nvedit.c
cpu/mpc824x/cpu_init.c
cpu/mpc824x/start.S
drivers/5701rls.c [new file with mode: 0644]
drivers/5701rls.h [new file with mode: 0644]
drivers/Makefile
drivers/bcm570x.c [new file with mode: 0644]
drivers/bcm570x_autoneg.c [new file with mode: 0644]
drivers/bcm570x_autoneg.h [new file with mode: 0644]
drivers/bcm570x_bits.h [new file with mode: 0644]
drivers/bcm570x_debug.h [new file with mode: 0644]
drivers/bcm570x_lm.h [new file with mode: 0644]
drivers/bcm570x_mm.h [new file with mode: 0644]
drivers/bcm570x_queue.h [new file with mode: 0644]
drivers/nicext.h [new file with mode: 0644]
drivers/pci.c
drivers/pci_auto.c
drivers/tigon3.c [new file with mode: 0644]
drivers/tigon3.h [new file with mode: 0644]
include/configs/BMW.h [new file with mode: 0644]
include/mpc824x.h
include/ppcboot.h

index 49e2ff8af51790574d800fbf8c65fded7a5f60b6..2f25528a0b6a84b564ae9243576d8079766491d2 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,10 @@
 Modifications for 1.2.0:
 ======================================================================
 
+* Patch by James Dougherty, 12 Aug 2002
+  Support for Broadcom BCM56xx PPC BMW Board
+  Added Broadcom BCM570x Gigabit Ethernet for MPC824x systems
+
 * Patch by Josef Wagner, 9 Aug 2002:
   added Configure command to set PHY bit (MII) in drivers/eepro100.c
 
@@ -11,7 +15,6 @@ Modifications for 1.2.0:
   MII-MDC function, because the existing FEC code only checks Utopia
   mode and configures PCMCIA port A for MII.
 
-
 * Patch by Greg Allen, 6 Aug 2002:
   Make the mpc824x correctly report the cpurevision according to
   Motorola's docs.
diff --git a/MAKEALL b/MAKEALL
index 2c650a56bedc8b902278843af406c92255d1f270..e17d7cffe71129233272d81893fb67cca60fc272 100755 (executable)
--- a/MAKEALL
+++ b/MAKEALL
@@ -46,9 +46,8 @@ LIST_4xx="    \
 #########################################################################
 
 LIST_824x="    \
-       CU824           MOUSSE          MUSENKI         OXC             \
-       Sandpoint8240   Sandpoint8245   \
-       utx8245 \
+       BMW             CU824           MOUSSE          MUSENKI         \
+       OXC             Sandpoint8240   Sandpoint8245   utx8245         \
 "
 
 #########################################################################
index b58c96cc791001fc6412692e01fbc25823445ae1..9e4bdbe9b5de9cc834fe9459aab665d2fc889ac8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -421,6 +421,8 @@ WALNUT405_config:unconfig
 #########################################################################
 ## MPC824x Systems
 #########################################################################
+BMW_config: unconfig
+       @./mkconfig $(@:_config=) ppc mpc824x bmw
 
 CU824_config: unconfig
        @./mkconfig $(@:_config=) ppc mpc824x cu824
diff --git a/README b/README
index 7cfeb163453d897fa288eefae4694f494d7f88df..f072820f9824a82ca56960b13e10de0e5a8c3410 100644 (file)
--- a/README
+++ b/README
@@ -371,14 +371,15 @@ The following options need to be configured:
                within "Boot Delay" after reset.
 
                CONFIG_BOOTARGS
-               This can be used to pass arguments to the bootm command.
-               The value of CONFIG_BOOTARGS goes into the environment
-               value "bootargs".
+                This can be used to pass arguments to the bootm
+                command. The value of CONFIG_BOOTARGS goes into the
+                environment value "bootargs".
 
                CONFIG_RAMBOOT and CONFIG_NFSBOOT
-               The value of these goes into the environment as "ramboot" and
-               "nfsboot" respectively, and can be used as a convenience, when
-               switching between booting from ram and nfs.
+                The value of these goes into the environment as
+                "ramboot" and "nfsboot" respectively, and can be used
+                as a convenience, when switching between booting from
+                ram and nfs.
 
 - Pre-Boot Commands:
                CONFIG_PREBOOT
@@ -970,11 +971,27 @@ The following options need to be configured:
    10  common/cmd_bootm.c      Ramdisk header is OK
   -12  common/cmd_bootm.c      Ramdisk data   has bad     checksum
    11  common/cmd_bootm.c      Ramdisk data   has correct checksum
+   12  common/cmd_bootm.c      Ramdisk verification complete, start loading
   -13  common/cmd_bootm.c      Wrong Image Type (not PPC Linux Ramdisk)
    13  common/cmd_bootm.c      Start multifile image verification
    14  common/cmd_bootm.c      No initial ramdisk, no multifile, continue.
-
-
+   15  common/cmd_bootm.c      All preparation done, transferring control to OS
+
+   -1  common/cmd_doc.c        Bad usage of "doc" command
+   -1  common/cmd_doc.c        No boot device
+   -1  common/cmd_doc.c        Unknown Chip ID on boot device
+   -1  common/cmd_doc.c        Read Error on boot device
+   -1  common/cmd_doc.c        Image header has bad magic number
+
+   -1  common/cmd_ide.c        Bad usage of "ide" command
+   -1  common/cmd_ide.c        No boot device
+   -1  common/cmd_ide.c        Unknown boot device 
+   -1  common/cmd_ide.c        Unknown partition table
+   -1  common/cmd_ide.c        Invalid partition type
+   -1  common/cmd_ide.c        Read Error on boot device
+   -1  common/cmd_ide.c        Image header has bad magic number
+
+   -1  common/cmd_nvedit.c     Environment not changable, but has bad CRC
 
 
 Configuration Settings:
diff --git a/board/bmw/Makefile b/board/bmw/Makefile
new file mode 100644 (file)
index 0000000..06c57c3
--- /dev/null
@@ -0,0 +1,43 @@
+#
+# (C) Copyright 2002
+# James F. Dougherty, Broadcom Corporation, jfd@broadcom.com
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB    = lib$(BOARD).a
+
+OBJS   = $(BOARD).o flash.o ns16550.o serial.o m48t59y.o
+          
+SOBJS  = early_init.o
+
+$(LIB):        .depend $(OBJS) $(SOBJS)
+       $(AR) crv $@ $^
+
+#########################################################################
+
+.depend:       Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+               $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/board/bmw/README b/board/bmw/README
new file mode 100644 (file)
index 0000000..9b90565
--- /dev/null
@@ -0,0 +1,340 @@
+Broadcom 95xx BMW CPCI Platform
+
+Overview
+=========
+BMW is an MPC8245 system controller featuring:
+* 3U CPCI Form Factor
+* BCM5703 Gigabit Ethernet
+* M48T59Y NVRAM
+* 16MB DOC
+* DIP Socket for Socketed DOC up to 1GB
+* 64MB SDRAM 
+* LCD Display
+* Configurable Jumper options for 66,85, and 100Mhz memory bus
+
+
+BMW System Address Map
+======================
+BMW uses the MPC8245 CHRP Address MAP B found in the MPC8245 Users Manual
+(P.121, Section 3.1 Address Maps, Address Map B). Other I/O devices found
+onboard the processor module are listed briefly below:
+
+0x00000000 - 0x40000000 - 64MB SDRAM SIMM
+                          (Unregistered PC-100 SDRAM DIMM Module)
+
+0xFF000000 - 0xFF001FFF - M-Systems DiskOnChip (TM) 2000 
+                          TSOP 16MB (MD2211-D16-V3)
+
+0x70000000 - 0x70001FFF - M-Systems DiskOnChip (TM) 2000
+                          DIP32 (Socketed 16MB - 1GB ) *
+                          NOTE: this is not populated on all systems.
+
+0x7c000000 - 0x7c000000 - Reset Register 
+                          (Write 0 to reset)
+
+0x7c000001 - 0x7c000001 - System LED 
+                          (Clear Bit 7 to turn on, set to shut off)
+
+0x7c000002 - 0x7c000002 - M48T59 Watchdog IRQ3 
+                          (Clear bit 7 to reset, set to assert IRQ3)
+
+0x7c000003 - 0x7c000003 - M48T59 Write-Protect Register
+                          (Clear bit 7 to make R/W, set to make R/O)
+
+0x7c002000 - 0x7c002003 - Infineon OSRAM DLR2416 4 Character 
+                          5x7 Dot Matrix Alphanumeric Display
+                          (Each byte sets the appropriate character)
+
+0x7c004000 - 0x7c005FF0 - SGS-THOMSON M48T59Y 8K NVRAM/RTC
+                          NVRAM Memory Region
+
+0x7c005FF0 - 0x7c005FFF - SGS-THOMSON M48T59Y 8K NVRAM/RTC 
+                          Realtime Clock Registers
+
+0xFFF00000 - 0xFFF80000 - 512K PLCC32 BootRom
+                          (AMD AM29F040, ST 29W040B)
+
+0xFFF00100 -              System Reset Vector 
+
+
+IO/MMU (BAT) Configuration
+======================
+The following Block-Address-Translation (BAT) configuration
+is recommended to access all I/O devices.
+
+#define CFG_IBAT0L  (0x00000000 | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT0U  (0x00000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_IBAT1L  (0x70000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT1U  (0x70000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_IBAT2L  (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT2U  (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_IBAT3L  (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT3U  (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_DBAT0L  CFG_IBAT0L
+#define CFG_DBAT0U  CFG_IBAT0U
+#define CFG_DBAT1L  CFG_IBAT1L
+#define CFG_DBAT1U  CFG_IBAT1U
+#define CFG_DBAT2L  CFG_IBAT2L
+#define CFG_DBAT2U  CFG_IBAT2U
+#define CFG_DBAT3L  CFG_IBAT3L
+#define CFG_DBAT3U  CFG_IBAT3U
+
+
+Interrupt Mappings
+======================
+BMW uses MPC8245 discrete mode interrupts. With the following 
+hardwired mappings:
+
+BCM5701 10/100/1000 Ethernet           IRQ1
+CompactPCI Interrupt A                 IRQ2
+RTC/Watchdog Interrupt                 IRQ3
+Internal NS16552 UART                  IRQ4
+
+
+Jumper Settings
+======================
+
+BMW has a jumper (JP600) for selecting 66, 85, or 100Mhz memory bus.
+A jumper (X) is a 0 bit.
+
+Hence 66= 10110
+      85= 11000
+     100= 10000
+
+Jumper Settings for various Speeds
+=======================
+J1 J2 J3 J4 J5
+    X        X    66Mhz
+=======================
+J1 J2 J3 J4 J5
+       X  X  X    85Mhz
+=======================
+J1 J2 J3 J4 J5
+    X  X  X  X   100Mhz
+=======================
+
+Obviously, 100Mhz memory bus is recommended for optimum performance.
+
+
+PPCBoot 
+===============
+Broadcom BMW board is supported under config_BWM option.
+Supported features:
+
+- NVRAM setenv/getenv (used by Linux Kernel for configuration variables)
+- BCM570x TFTP file transfer support
+- LCD Display Support
+- DOC Support - (underway)
+
+
+
+PPCBoot 1.2.0 (Aug  6 2002 - 17:44:48)
+
+CPU:   MPC8245 Revision 16.20 at 264 MHz: 16 kB I-Cache 16 kB D-Cache
+Board: BMW MPC8245/KAHLUA2 - CHRP (MAP B)
+Built: Aug  6 2002 at 17:44:37
+Local Bus at 66 MHz
+DRAM:  64 MB
+FLASH: 4095 MB
+In:    serial
+Out:   serial
+Err:   serial
+DOC:   No DiskOnChip found
+Hit any key to stop autoboot:  0 
+=>printenv
+bootdelay=5
+baudrate=9600
+clocks_in_mhz=1
+hostname=switch-2
+bootcmd=tftp 100000 vmlinux.img;bootm
+gateway=10.16.64.1
+ethaddr=00:00:10:18:10:10
+nfsroot=172.16.40.111:/boot/root-fs
+filesize=5ec8c
+netmask=255.255.240.0
+ipaddr=172.16.40.114
+serverip=172.16.40.111
+root=/dev/nfs
+stdin=serial
+stdout=serial
+stderr=serial
+
+Environment size: 315/8172 bytes
+=>boot
+
+
+
+
+
+
+
+DevTools
+========
+ELDK
+        DENX Embedded Linux Development Kit
+
+ROM Emulator
+       Grammar Engine PROMICE P1160-90-AI21E (2MBx8bit, 90ns access time)
+       Grammar Engine PL32E 32Pin PLCC Emulation cables
+       Grammar Engine 3VA8CON (3Volt adapter with Short cables)
+       Grammar Engine FPNET PromICE Ethernet Adapters
+
+ICE
+       WRS/EST VisionICE-II (PPC8240)
+
+
+
+=>reset
+
+
+PPCBoot 1.2.0 (Aug  6 2002 - 17:44:48)
+
+CPU:   MPC8245 Revision 16.20 at 264 MHz: 16 kB I-Cache 16 kB D-Cache
+Board: BMW MPC8245/KAHLUA2 - CHRP (MAP B)
+Built: Aug  6 2002 at 17:44:37
+Local Bus at 66 MHz
+DRAM:  64 MB
+FLASH: 4095 MB
+In:    serial
+Out:   serial
+Err:   serial
+DOC:   No DiskOnChip found
+Hit any key to stop autoboot:  0 
+
+Broadcom BCM5701 1000Base-T: bus 0, device 13, function 0: MBAR=0x80100000
+BCM570x PCI Memory base address @0x80100000
+eth0:Broadcom BCM5701 1000Base-T: 100 Mbps half duplex link up, flow control OFF
+eth0: Broadcom BCM5701 1000Base-T @0x80100000,node addr 000010181010
+eth0: BCM5700 with Broadcom BCM5701 Integrated Copper transceiver found
+eth0: 32-bit PCI 33MHz, MTU: 1500,Rx Checksum ON
+ARP broadcast 1
+TFTP from server 172.16.40.111; our IP address is 172.16.40.114
+Filename 'vmlinux.img'.
+Load address: 0x100000
+Loading: #################################################################
+         ####################################T #############################
+         ######################
+done
+Bytes transferred = 777199 (bdbef hex)
+
+eth0:Broadcom BCM5701 1000Base-T,HALT,POWER DOWN,done - offline.
+## Booting image at 00100000 ...
+   Image Name:   vmlinux.bin.gz
+   Created:      2002-08-06   6:30:13 UTC
+   Image Type:   PowerPC Linux Kernel Image (gzip compressed)
+   Data Size:    777135 Bytes = 758 kB = 0 MB
+   Load Address: 00000000
+   Entry Point:  00000000
+   Verifying Checksum ... OK
+   Uncompressing Kernel Image ... OK
+Memory BAT mapping: BAT2=64Mb, BAT3=0Mb, residual: 0Mb
+Linux version 2.4.19-rc3 (jfd@que) (gcc version 2.95.3 20010111 (prerelease/franzo/20010111)) #168 Mon Aug 5 23:29:20 PDT 2002
+CPU:82xx: 32 I-Cache Block Size, 32 D-Cache Block Size PVR: 0x810000
+PPCBoot Environment: 0xc01b08f0
+IP PNP: 802.3 Ethernet Address=<0:0:10:18:10:10>
+cpu0: MPC8245/KAHLUA-II : BMW Platform : 64MB RAM: BPLD Rev. 6e
+NOTICE: mounting root file system via NFS
+IP PNP: switch-2: eth0 IP 172.16.40.114/255.255.240.0 gateway 10.16.64.1 server 172.16.40.111
+On node 0 totalpages: 16384
+zone(0): 16384 pages.
+zone(1): 0 pages.
+zone(2): 0 pages.
+Kernel command line: console=ttyS0,9600 ip=172.16.40.114:172.16.40.111:10.16.64.1:255.255.240.0:switch-2:eth0 root=/dev/nfs rw nfsroot=172.16.40.111:/boot/root-fs,timeo=200,retrans=500 nfsaddrs=172.16.40.114:172.16.40.111
+root_dev_setup:/dev/nfs or 00:ff
+time_init: decrementer frequency = 16.501145 MHz
+Calibrating delay loop... 175.71 BogoMIPS
+Memory: 62572k available (1396k kernel code, 436k data, 100k init, 0k highmem)
+Dentry cache hash table entries: 8192 (order: 4, 65536 bytes)
+Inode cache hash table entries: 4096 (order: 3, 32768 bytes)
+Mount-cache hash table entries: 1024 (order: 1, 8192 bytes)
+Buffer-cache hash table entries: 4096 (order: 2, 16384 bytes)
+Page-cache hash table entries: 16384 (order: 4, 65536 bytes)
+POSIX conformance testing by UNIFIX
+PCI: Probing PCI hardware
+Linux NET4.0 for Linux 2.4
+Based upon Swansea University Computer Society NET3.039
+Initializing RT netlink socket
+Starting kswapd
+devfs: v1.12a (20020514) Richard Gooch (rgooch@atnf.csiro.au)
+devfs: devfs_debug: 0x0
+devfs: boot_options: 0x1
+Installing knfsd (copyright (C) 1996 okir@monad.swb.de).
+pty: 256 Unix98 ptys configured
+Serial driver version 5.05c (2001-07-08) with MANY_PORTS SHARE_IRQ SERIAL_PCI enabled
+Testing ttyS0 (0xf7f51500, 0xf7f51500)...
+Testing ttyS1 (0xfc004600, 0xfc004600)...
+ttyS00 at 0xf7f51500 (irq = 24) is a ST16650
+ttyS01 at 0xfc004600 (irq = 25) is a 16550A
+Real Time Clock Driver v1.10e
+RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
+loop: loaded (max 8 devices)
+TFFS 5.1.1 Flash disk driver for DiskOnChip
+Copyright (C) 1998,2001 M-Systems Flash Disk Pioneers Ltd.
+DOC device(s) found: 1
+fl_init: registered device at major: 100
+fl_geninit: registered device at major: 100
+Partition check:
+ fla: p1
+partition: /dev/fl/0: start_sect: 0,nr_sects: 32000 Fl_blk_size[]: 16000KB
+partition: /dev/fl/1: start_sect: 2,nr_sects: 31998 Fl_blk_size[]: 15999KB
+partition: /dev/fl/2: start_sect: 0,nr_sects: 0 Fl_blk_size[]: 0KB
+partition: /dev/fl/3: start_sect: 0,nr_sects: 0 Fl_blk_size[]: 0KB
+Broadcom Gigabit Ethernet Driver bcm5700 ver. 3.0.7 (07/17/02)
+eth0: Broadcom BCM5701 found at mem bfff0000, IRQ 1, node addr 000010181010
+eth0: Broadcom BCM5701 Integrated Copper transceiver found
+eth0: Scatter-gather ON, 64-bit DMA ON, Tx Checksum ON, Rx Checksum ON, 802.1Q VLAN ON
+bond0 registered without MII link monitoring, in bonding mode.
+rtc: unable to get misc minor
+NET4: Linux TCP/IP 1.0 for NET4.0
+IP Protocols: ICMP, UDP, TCP, IGMP
+IP: routing cache hash table of 512 buckets, 4Kbytes
+TCP: Hash tables configured (established 4096 bind 4096)
+bcm5700: eth0 NIC Link is UP, 100 Mbps half duplex
+IP-Config: Gateway not on directly connected network.
+NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
+802.1Q VLAN Support v1.7 Ben Greear <greearb@candelatech.com>
+All bugs added by David S. Miller <davem@redhat.com>
+Looking up port of RPC 100003/2 on 172.16.40.111
+Looking up port of RPC 100005/1 on 172.16.40.111
+VFS: Mounted root (nfs filesystem).
+Mounted devfs on /dev
+Freeing unused kernel memory: 100k init
+INIT: version 2.78 booting
+Mounting local filesystems...
+not mounted anything
+Setting up symlinks in /dev...done.
+Setting up extra devices in /dev...done.
+Starting devfsd...Started device management daemon for /dev
+INIT: Entering runlevel: 2
+Starting internet superserver: inetd.
+
+
+Welcome to Linux/PPC
+MPC8245/BMW
+
+
+
+switch-2 login: root
+Password: 
+PAM_unix[49]: (login) session opened for user root by LOGIN(uid=0)
+Last login: Thu Nov 25 11:51:14 1920 on console
+
+
+Welcome to Linux/PPC
+MPC8245/BMW
+
+
+
+login[49]: ROOT LOGIN on `console'
+
+root@switch-2:~# cat /proc/cpuinfo
+cpu             : 82xx
+revision        : 16.20 (pvr 8081 1014)
+bogomips        : 175.71
+vendor          : Broadcom
+machine         : BMW/MPC8245
+root@switch-2:~# 
diff --git a/board/bmw/bmw.c b/board/bmw/bmw.c
new file mode 100644 (file)
index 0000000..5efc774
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * (C) Copyright 2002
+ * James F. Dougherty, Broadcom Corporation, jfd@broadcom.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppcboot.h>
+#include <ppcboot.h>
+#include <watchdog.h>
+#include <command.h>
+#include <malloc.h>
+#include <devices.h>
+#include <syscall.h>
+#include <net.h>
+#include <version.h>
+#include <dtt.h>
+#include <mpc824x.h>
+#include <asm/processor.h>
+#include <linux/mtd/doc2000.h>
+
+#include "bmw.h"
+#include "m48t59y.h"
+#include <pci.h>
+
+
+/* We have to clear the initial data area here. Couldn't have done it
+ * earlier because DRAM had not been initialized.
+ */
+int board_pre_init(void)
+{
+    memset((void *)(CFG_INIT_RAM_ADDR + CFG_INIT_DATA_OFFSET),
+          0,
+          CFG_INIT_DATA_SIZE);
+
+    return 0;
+}
+
+int checkboard(void)
+{
+    ulong busfreq  = get_bus_freq(0);
+    char  buf[32];
+
+    printf("BMW MPC8245/KAHLUA2 - CHRP (MAP B)\n");
+    printf("Built: %s at %s\n", __DATE__ , __TIME__ );
+    /* printf("MPLD:  Revision %d\n", SYS_REVID_GET()); */
+    printf("Local Bus at %s MHz\n", strmhz(buf, busfreq));
+    return 0;
+}
+
+long int initdram(int board_type)
+{
+    return 64*1024*1024;
+}
+
+
+void
+get_tod(void)
+{
+    int year, month, day, hour, minute, second;
+
+    m48_tod_get(&year,
+               &month,
+               &day,
+               &hour,
+               &minute,
+               &second);
+
+    printf("  Current date/time: %d/%d/%d %d:%d:%d \n",
+          month, day, year, hour, minute, second);
+
+}
+
+/*
+ * EPIC, PCI, and I/O devices.
+ * Initialize Mousse Platform, probe for PCI devices,
+ * Query configuration parameters if not set.
+ */
+int misc_init_f (void)
+{
+#if 0
+    m48_tod_init(); /* Init SGS M48T59Y TOD/NVRAM */
+    printf("RTC:   M48T589 TOD/NVRAM (%d) bytes\n",
+          TOD_NVRAM_SIZE);
+    get_tod();
+#endif
+
+    sys_led_msg("BOOT");
+    return 0;
+}
+
+
+
+
+
+/*
+ * Initialize PCI Devices, report devices found.
+ */
+struct pci_controller hose;
+
+void pci_init (bd_t *bd)
+{
+    pci_mpc824x_init(bd, &hose);
+    /* pci_dev_init(0); */
+}
+
+/*
+ * Write characters to LCD display.
+ * Note that the bytes for the first character is the last address.
+ */
+void
+sys_led_msg(char* msg)
+{
+    LED_REG(0) = msg[3];
+    LED_REG(1) = msg[2];
+    LED_REG(2) = msg[1];
+    LED_REG(3) = msg[0];
+}
+
+/*
+ * Map onboard TSOP-16MB DOC FLASH chip.
+ */
+void doc_init (void)
+{
+    doc_probe(DOC_BASE_ADDR);
+}
+
+#define NV_ADDR        ((volatile unsigned char *) CFG_ENV_ADDR)
+
+/* Read from NVRAM */
+void*
+nvram_read(void *dest, const long src, size_t count)
+{
+    int i;
+    volatile unsigned char* d = (unsigned char*)dest;
+    volatile unsigned char* s = (unsigned char*)src;
+
+    for( i = 0; i < count;i++)
+       d[i] = s[i];
+
+    return dest;
+}
+
+/* Write to NVRAM */
+void
+nvram_write(long dest, const void *src, size_t count)
+{
+    int i;
+    volatile unsigned char* d = (unsigned char*)dest;
+    volatile unsigned char* s = (unsigned char*)src;
+
+    SYS_TOD_UNPROTECT();
+
+    for( i = 0; i < count;i++)
+       d[i] = s[i];
+
+    SYS_TOD_PROTECT();
+}
diff --git a/board/bmw/bmw.h b/board/bmw/bmw.h
new file mode 100644 (file)
index 0000000..7f3fd5f
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * BMW/MPC8245 Board definitions.
+ * For more info, see http://www.vooha.com/
+ * 
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002
+ * James Dougherty (jfd@broadcom.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __BMW_H
+#define __BMW_H
+
+/* System addresses */
+
+#define PCI_SPECIAL_BASE       0xfe000000
+#define PCI_SPECIAL_SIZE       0x01000000
+
+#define EUMBBAR_VAL            0x80500000      /* Location of EUMB region */
+#define EUMBSIZE               0x00100000      /* Size of EUMB region */
+
+/* Extended ROM space devices */
+#define DOC_BASE_ADDR           0xff000000      /* Onboard DOC TSOP 16MB */
+#define DOC2_BASE_ADDR          0x70000000      /* DIP32 socket -> 1GB */
+#define XROM_BASE_ADDR          0x7c000000      /* RCS2 (PAL / Satellite IO) */
+#define PLD_REG_BASE           XROM_BASE_ADDR
+#define LED_REG_BASE           (XROM_BASE_ADDR | 0x2000)
+#define TOD_BASE               (XROM_BASE_ADDR | 0x4000)
+#define LED_REG(x)              (*(volatile unsigned char *) \
+                                  (LED_REG_BASE + (x)))
+#define XROM_DEV_SIZE          0x00006000
+
+#define ENET_DEV_BASE          0x80000000
+
+#define PLD_REG(off)           (*(volatile unsigned char *)\
+                                  (PLD_REG_BASE + (off)))
+
+#define PLD_REVID_B1           0x7f    /* Fix me */
+#define PLD_REVID_B2           0x01    /* Fix me */
+
+#define SYS_HARD_RESET()       { for (;;) PLD_REG(0) = 0; } /* clr 0x80 bit */
+#define SYS_REVID_GET()                ((int) PLD_REG(0) & 0x7f)
+#define SYS_LED_OFF()          (PLD_REG(1) |= 0x80)
+#define SYS_LED_ON()           (PLD_REG(1) &= ~0x80)
+#define SYS_WATCHDOG_IRQ3()    (PLD_REG(2) |= 0x80)
+#define SYS_WATCHDOG_RESET()   (PLD_REG(2) &= ~0x80)
+#define SYS_TOD_PROTECT()      (PLD_REG(3) |= 0x80)
+#define SYS_TOD_UNPROTECT()    (PLD_REG(3) &= ~0x80)
+
+#define        TOD_REG_BASE            (TOD_BASE | 0x1ff0)
+#define        TOD_NVRAM_BASE          TOD_BASE
+#define        TOD_NVRAM_SIZE          0x1ff0
+#define        TOD_NVRAM_LIMIT         (TOD_NVRAM_BASE + TOD_NVRAM_SIZE)
+#define RTC(r)                 (TOD_BASE + r)
+
+/* Onboard BCM570x device */
+#define        PCI_ENET_IOADDR         0x80000000
+#define        PCI_ENET_MEMADDR        0x80000000 
+
+
+#ifndef __ASSEMBLY__
+/* C Function prototypes */
+void sys_led_msg(char* msg);
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __BMW_H */
diff --git a/board/bmw/config.mk b/board/bmw/config.mk
new file mode 100644 (file)
index 0000000..7facadf
--- /dev/null
@@ -0,0 +1,32 @@
+#
+# (C) Copyright 2001
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+#
+# CU824 board
+#
+
+TEXT_BASE = 0xFFF00000
+# NOTE: The flags below affect how the BCM570x driver is compiled
+PLATFORM_CPPFLAGS += -DEMBEDDED -DBIG_ENDIAN_HOST -DINCLUDE_5701_AX_FIX=1\
+                     -DDBG=0 -DT3_JUMBO_RCV_RCB_ENTRY_COUNT=256\
+                     -DTEXT_BASE=$(TEXT_BASE)
diff --git a/board/bmw/early_init.S b/board/bmw/early_init.S
new file mode 100644 (file)
index 0000000..52d64c0
--- /dev/null
@@ -0,0 +1,1172 @@
+#include <ppc_asm.tmpl>
+#include <mpc824x.h>
+#include <ppc_defs.h>
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#define USE_V2_INIT 1 /* Jimmy Blair's initialization. */
+
+
+/* 
+ * Initialize the MMU using BAT entries and hardwired TLB 
+ * This obviates the need for any code in cpu_init_f which 
+ * configures the BAT registers.
+*/
+#define MEMORY_MGMT_MSR_BITS (MSR_DR | MSR_IR) /* Data and Inst Relocate */
+       .global iommu_setup
+       /* Initialize IO/MMU mappings via BAT method Ch. 7, 
+        * PPC Programming Reference 
+         */
+iommu_setup:
+
+/* initialize the BAT registers (SPRs 528 - 543 */
+#define        mtibat0u(x)     mtspr   528,(x)                 /* SPR 528 (IBAT0U) */
+#define mtibat0l(x)    mtspr   529,(x)                 /* SPR 529 (IBAT0L) */
+#define mtibat1u(x)    mtspr   530,(x)                 /* SPR 530 (IBAT1U) */
+#define mtibat1l(x)    mtspr   531,(x)                 /* SPR 531 (IBAT1L) */
+#define mtibat2u(x)    mtspr   532,(x)                 /* SPR 532 (IBAT2U) */
+#define mtibat2l(x)    mtspr   533,(x)                 /* SPR 533 (IBAT2L) */
+#define mtibat3u(x)    mtspr   534,(x)                 /* SPR 534 (IBAT3U) */
+#define mtibat3l(x)    mtspr   535,(x)                 /* SPR 535 (IBAT3L) */
+#define mtdbat0u(x)    mtspr   536,(x)                 /* SPR 536 (DBAT0U) */
+#define mtdbat0l(x)    mtspr   537,(x)                 /* SPR 537 (DBAT0L) */
+#define mtdbat1u(x)    mtspr   538,(x)                 /* SPR 538 (DBAT1U) */
+#define mtdbat1l(x)    mtspr   539,(x)                 /* SPR 539 (DBAT1L) */
+#define mtdbat2u(x)    mtspr   540,(x)                 /* SPR 540 (DBAT2U) */
+#define mtdbat2l(x)    mtspr   541,(x)                 /* SPR 541 (DBAT2L) */
+#define mtdbat3u(x)    mtspr   542,(x)                 /* SPR 542 (DBAT3U) */
+#define mtdbat3l(x)    mtspr   543,(x)                 /* SPR 543 (DBAT3L) */
+
+
+/* PowerPC processors do not necessarily initialize the BAT
+   registers on power-up or reset.  So they are in an unknown
+   state.  Before programming the BATs for the first time, all
+   BAT registers MUST have their Vs and Vp bits cleared in the
+   upper BAT half in order to avoid possibly having 2 BATs
+   valid and mapping the same memory region.
+
+   The reason for this is that, even with address translation
+   disabled, multiple BAT hits for an address are treated as
+   programming errors and can cause unpredictable results.
+
+   It is up to the software to make sure it never has 2 IBAT
+   mappings or 2 DBAT mappings that are valid for the same
+   addresses.  It is not necessary to perform this code
+   sequence every time the BATs are programmed, only when
+   there is a possibility that there may be overlapping BAT
+   entries.
+        
+   When programming the BATs in non-reset scenarios, even if
+   you are sure that your new mapping will not temporarily
+   create overlapping regions, it is still a wise idea to
+   invalidate a BAT entry by setting its upper BAT register to
+   all 0's before programming it.  This will avoid having a
+   BAT marked valid that is in an unknown or transient state
+*/
+
+        addis   r5,0,0x0000
+       mtibat0u(r5)
+       mtibat0l(r5)
+       mtibat1u(r5)
+       mtibat1l(r5)
+       mtibat2u(r5)
+       mtibat2l(r5)
+       mtibat3u(r5)
+       mtibat3l(r5)
+       mtdbat0u(r5)
+       mtdbat0l(r5)
+       mtdbat1u(r5)
+       mtdbat1l(r5)
+       mtdbat2u(r5)
+       mtdbat2l(r5)
+       mtdbat3u(r5)
+       mtdbat3l(r5)
+        isync
+
+/*
+ *  Set up I/D BAT0
+ */
+        lis     r4, CFG_DBAT0L@h
+        ori     r4, r4, CFG_DBAT0L@l
+        lis     r3, CFG_DBAT0U@h
+        ori     r3, r3, CFG_DBAT0U@l
+
+        mtdbat0l(r4)
+        isync
+        mtdbat0u(r3)
+        isync
+        sync
+
+        lis     r4, CFG_IBAT0L@h
+        ori     r4, r4, CFG_IBAT0L@l
+        lis     r3, CFG_IBAT0U@h
+        ori     r3, r3, CFG_IBAT0U@l
+
+        isync
+        mtibat0l(r4)
+        isync
+       mtibat0u(r3)
+        isync
+
+/*
+ *  Set up I/D BAT1
+ */
+        lis     r4, CFG_IBAT1L@h
+        ori     r4, r4, CFG_IBAT1L@l
+        lis     r3, CFG_IBAT1U@h 
+        ori     r3, r3, CFG_IBAT1U@l 
+
+        isync
+        mtibat1l(r4)
+        isync
+        mtibat1u(r3)
+        isync
+        mtdbat1l(r4)
+        isync
+        mtdbat1u(r3)
+        isync
+        sync
+
+/*
+ *  Set up I/D BAT2
+ */
+        lis     r4, CFG_IBAT2L@h
+        ori     r4, r4, CFG_IBAT2L@l 
+        lis     r3, CFG_IBAT2U@h 
+        ori     r3, r3, CFG_IBAT2U@l
+
+        isync
+        mtibat2l(r4)
+        isync
+        mtibat2u(r3)
+        isync
+        mtdbat2l(r4)
+        isync
+        mtdbat2u(r3)
+        isync
+        sync
+
+/*
+ *  Setup I/D BAT3
+ */
+        lis     r4, CFG_IBAT3L@h
+        ori     r4, r4, CFG_IBAT3L@l
+        lis     r3, CFG_IBAT3U@h
+        ori     r3, r3, CFG_IBAT3U@l
+
+        isync
+        mtibat3l(r4)
+        isync
+        mtibat3u(r3)
+        isync
+        mtdbat3l(r4)
+        isync
+        mtdbat3u(r3)
+        isync
+        sync
+
+
+/*
+ *  Invalidate all 64 TLB's
+ */
+        lis     r3, 0
+        mtctr   r3
+        lis     r5, 4
+
+tlblp:
+        tlbie   r3
+        sync
+        addi    r3, r3, 0x1000
+        cmplw   r3, r5
+        blt     tlblp
+
+        sync
+
+/*
+ *  Enable Data Translation
+ */
+       lis     r4, MEMORY_MGMT_MSR_BITS@h
+       ori     r4, r4, MEMORY_MGMT_MSR_BITS@l
+       mfmsr   r3
+       or      r3, r4, r3
+       mtmsr   r3
+       isync
+       sync
+
+        blr
+
+
+#ifdef USE_V2_INIT
+/* #define USER_I_CACHE_ENABLE 1*/ /* Fast rom boots */
+/* Macro for hiadjust and lo */
+#define HIADJ(arg)     arg@ha
+#define HI(arg)                arg@h
+#define LO(arg)                arg@l
+
+#undef LOADPTR
+#define        LOADPTR(reg,const32) \
+         addis reg,r0,HIADJ(const32); addi reg,reg,LO(const32)
+
+.globl  early_init_f
+
+early_init_f:
+/* MPC8245/BMW CPCI System Init
+ * Jimmy Blair, Broadcom Corp, 2002.
+ */
+        mflr    r11
+       /* Zero-out registers */
+
+       addis   r0,r0,0
+       mtspr   SPRG0,r0
+       mtspr   SPRG1,r0
+       mtspr   SPRG2,r0
+       mtspr   SPRG3,r0
+
+       /* Set MPU/MSR to a known state. Turn on FP */
+
+       LOADPTR (r3, MSR_FP)
+       sync
+       mtmsr   r3
+       isync
+
+       /* Init the floating point control/status register */
+
+       mtfsfi  7,0x0
+       mtfsfi  6,0x0
+       mtfsfi  5,0x0
+       mtfsfi  4,0x0
+       mtfsfi  3,0x0
+       mtfsfi  2,0x0
+       mtfsfi  1,0x0
+       mtfsfi  0,0x0
+       isync
+
+       /* Set MPU/MSR to a known state. Turn off FP */
+
+#if 1  /* Turn off floating point (remove to keep FP on) */
+        andi.  r3, r3, 0
+       sync
+       mtmsr   r3
+       isync
+#endif
+
+       /* Init the Segment registers */
+
+       andi.   r3, r3, 0
+       isync
+       mtsr    0,r3
+       isync
+       mtsr    1,r3
+       isync
+       mtsr    2,r3
+       isync
+       mtsr    3,r3
+       isync
+       mtsr    4,r3
+       isync
+       mtsr    5,r3
+       isync
+       mtsr    6,r3
+       isync
+       mtsr    7,r3
+       isync
+       mtsr    8,r3
+       isync
+       mtsr    9,r3
+       isync
+       mtsr    10,r3
+       isync
+       mtsr    11,r3
+       isync
+       mtsr    12,r3
+       isync
+       mtsr    13,r3
+       isync
+       mtsr    14,r3
+       isync
+       mtsr    15,r3
+       isync
+
+       /* Turn off data and instruction cache control bits */
+
+       mfspr   r3, HID0
+       isync
+       rlwinm  r4, r3, 0, 18, 15       /* r4 has ICE and DCE bits cleared */
+       sync
+       isync
+       mtspr   HID0, r4                /* HID0 = r4 */
+       isync
+
+       /* Get cpu type */
+
+       mfspr   r28, PVR
+       rlwinm  r28, r28, 16, 16, 31
+
+       /* invalidate the MPU's data/instruction caches */
+
+       lis     r3, 0x0
+       cmpli   0, 0, r28, CPU_TYPE_603
+       beq     cpuIs603
+       cmpli   0, 0, r28, CPU_TYPE_603E
+       beq     cpuIs603
+       cmpli   0, 0, r28, CPU_TYPE_603P
+       beq     cpuIs603
+       cmpli   0, 0, r28, CPU_TYPE_604R
+       bne     cpuNot604R
+
+cpuIs604R:
+       lis     r3, 0x0
+       mtspr   HID0, r3                /* disable the caches */
+       isync
+       ori     r4, r4, 0x0002          /* disable BTAC by setting bit 30 */
+
+cpuNot604R:
+       ori     r3, r3, (HID0_ICFI |HID0_DCI)
+
+cpuIs603:
+       ori     r3, r3, (HID0_ICE | HID0_DCE)
+       or      r4, r4, r3              /* set bits */
+       sync
+       isync
+       mtspr   HID0, r4                /* HID0 = r4 */
+       andc    r4, r4, r3              /* clear bits */
+       isync
+       cmpli   0, 0, r28, CPU_TYPE_604
+       beq     cpuIs604
+       cmpli   0, 0, r28, CPU_TYPE_604E
+       beq     cpuIs604
+       cmpli   0, 0, r28, CPU_TYPE_604R
+       beq     cpuIs604
+       mtspr   HID0, r4
+       isync
+
+#ifdef USER_I_CACHE_ENABLE
+       b       instCacheOn603
+#else
+       b       cacheEnableDone
+#endif
+
+cpuIs604:
+       LOADPTR (r5, 0x1000)            /* loop count, 0x1000 */
+       mtspr   CTR, r5
+loopDelay:
+       nop
+       bdnz    loopDelay
+       isync
+       mtspr   HID0, r4
+       isync
+
+       /* turn the Instruction cache ON for faster FLASH ROM boots */
+
+#ifdef USER_I_CACHE_ENABLE
+
+       ori     r4, r4, (HID0_ICE | HID0_ICFI)
+       isync                           /* Synchronize for ICE enable */
+       b       writeReg4
+instCacheOn603:
+       ori     r4, r4, (HID0_ICE | HID0_ICFI)
+       rlwinm  r3, r4, 0, 21, 19       /* clear the ICFI bit */
+
+       /*
+         * The setting of the instruction cache enable (ICE) bit must be
+         * preceded by an isync instruction to prevent the cache from being
+         * enabled or disabled while an instruction access is in progress.
+         */
+       isync
+writeReg4:
+       mtspr   HID0, r4                /* Enable Instr Cache & Inval cache */
+       cmpli   0, 0, r28, CPU_TYPE_604
+       beq     cacheEnableDone
+       cmpli   0, 0, r28, CPU_TYPE_604E
+       beq     cacheEnableDone
+
+       mtspr   HID0, r3                /* using 2 consec instructions */
+                                       /* PPC603 recommendation */
+#endif
+cacheEnableDone:
+
+       /* Detect map A or B */
+
+       addis   r5,r0, HI(CHRP_REG_ADDR)
+       addis   r6,r0, HI(CHRP_REG_DATA)
+       LOADPTR (r7, KAHLUA_ID)         /* Kahlua PCI controller ID */
+       LOADPTR (r8, BMC_BASE)
+
+       stwbrx  r8,0,(r5)
+       lwbrx   r3,0,(r6)               /* Store read value to r3 */
+       cmp     0,0,r3,r7
+       beq     cr0, X4_KAHLUA_START
+
+        /* It's not an 8240, is it an 8245? */
+
+       LOADPTR (r7, KAHLUA2_ID)        /* Kahlua PCI controller ID */
+       cmp     0,0,r3,r7
+       beq     cr0, X4_KAHLUA_START
+
+        /* Save the PCI controller type in r7 */
+       mr      r7, r3
+
+       LOADPTR (r5, PREP_REG_ADDR)
+       LOADPTR (r6, PREP_REG_DATA)
+
+X4_KAHLUA_START:
+       /* MPC8245 changes begin here */
+       LOADPTR (r3, MPC107_PCI_CMD)    /* PCI command reg */
+       stwbrx  r3,0,r5
+       li      r4, 6                   /* Command register value */
+       sthbrx  r4, 0, r6
+
+       LOADPTR (r3, MPC107_PCI_STAT)   /* PCI status reg */
+       stwbrx  r3,0,r5
+       li      r4, -1                  /* Write-to-clear all bits */
+       li      r3, 2                   /* PCI_STATUS is at +2 offset */
+       sthbrx  r4, r3, r6
+
+       /*-------PROC_INT1_ADR */
+       
+       LOADPTR (r3, PROC_INT1_ADR)     /* Processor I/F Config 1 reg. */
+       stwbrx  r3,0,r5
+       LOADPTR (r4, 0xff141b98)
+       stwbrx  r4,0,r6
+
+       /*-------PROC_INT2_ADR */
+
+       LOADPTR (r3, PROC_INT2_ADR)     /* Processor I/F Config 2 reg. */
+       stwbrx  r3,0,r5
+        lis    r4, 0x2000              /* Flush PCI config writes */
+       stwbrx  r4,0,r6
+
+       LOADPTR (r9, KAHLUA2_ID)        
+        cmpl   0, 0, r7, r9
+        bne     L1not8245
+
+        /* MIOCR1 -- turn on bit for DLL delay */
+
+       LOADPTR (r3, MIOCR1_ADR_X)            
+       stwbrx  r3,0,r5
+        li      r4, 0x04
+       stb     r4, MIOCR1_SHIFT(r6)
+
+        /* For the MPC8245, set register 77 to %00100000 (see Errata #15) */
+        /* SDRAM_CLK_DEL (0x77)*/
+
+       LOADPTR (r3, MIOCR2_ADR_X)            
+       stwbrx  r3,0,r5
+        li      r4, 0x10
+       stb     r4, MIOCR2_SHIFT(r6)
+
+        /* PMCR2 -- set PCI hold delay to <10>b for 33 MHz */
+
+       LOADPTR (r3, PMCR2_ADR_X)             
+       stwbrx  r3,0,r5
+        li      r4, 0x20
+       stb     r4, PMCR2_SHIFT(r6)
+
+       /* Initialize EUMBBAR early since 8245 has internal UART in EUMB */
+
+       LOADPTR (r3, EUMBBAR)
+       stwbrx  r3,0,r5
+       LOADPTR (r4, CFG_EUMB_ADDR)
+       stwbrx  r4,0,r6
+
+L1not8245:
+
+        /* Toggle the DLL reset bit in AMBOR */
+
+       LOADPTR (r3, AMBOR)     
+       stwbrx  r3,0,r5
+       lbz     r4, 0(r6)
+
+        andi.   r4, r4, 0xdf
+       stb     r4, 0(r6)               /* Clear DLL_RESET */
+        sync
+
+        ori     r4, r4, 0x20           /* Set DLL_RESET */
+       stb     r4, 0(r6)               
+        sync
+
+        andi.   r4, r4, 0xdf
+       stb     r4, 0(r6)               /* Clear DLL_RESET */
+
+
+       /* Enable RCS2, use supplied timings */
+       LOADPTR (r3, ERCR1)
+       stwbrx  r3,0,r5
+       LOADPTR (r4, 0x80408000)
+       stwbrx  r4,0,r6
+
+       /* Disable RCS3 parameters */
+       LOADPTR (r3, ERCR2)
+       stwbrx  r3,0,r5
+       LOADPTR (r4, 0x00000000)
+       stwbrx  r4,0,r6
+
+       /* RCS3 at 0x70000000, 64KBytes */
+       LOADPTR (r3, ERCR2)
+       stwbrx  r3,0,r5
+       LOADPTR (r4, 0x00000004)
+       stwbrx  r4,0,r6
+
+       /*-------MCCR1 */
+
+#ifdef INCLUDE_ECC
+#define MC_ECC                         1
+#else /* INCLUDE_ECC */
+#define MC_ECC                         0
+#endif /* INCLUDE_ECC */
+
+#define MC1_ROMNAL                     8               /* 0-15 */
+#define MC1_ROMFAL                     11              /* 0-31 */
+#define MC1_DBUS_SIZE                  0               /* 0-3, read only */
+#define MC1_BURST                      0               /* 0-1 */
+#define MC1_MEMGO                      0               /* 0-1 */
+#define MC1_SREN                       1               /* 0-1 */
+#define MC1_RAM_TYPE                   0               /* 0-1 */
+#define MC1_PCKEN                      MC_ECC          /* 0-1 */
+#define MC1_BANKBITS                   0x5555          /* 2 bits/bank 7-0 */
+
+       LOADPTR (r3, MEM_CONT1_ADR)     /* Set MCCR1 (F0) */
+       stwbrx  r3,0,r5
+       LOADPTR(r4, \
+               MC1_ROMNAL << 28 | MC1_ROMFAL << 23 | \
+               MC1_DBUS_SIZE << 21 | MC1_BURST << 20 | \
+               MC1_MEMGO << 19 | MC1_SREN << 18 | \
+               MC1_RAM_TYPE << 17 | MC1_PCKEN << 16 )
+       li      r3, MC1_BANKBITS
+        cmpl   0, 0, r7, r9            /* Check for Kahlua2 */
+        bne     BankBitsAdd
+        cmpli   0, 0, r3, 0x5555
+        beq     K2BankBitsHack         /* On 8245, 5555 ==> 0 */
+BankBitsAdd:
+       ori     r4, r3, 0
+K2BankBitsHack:
+       stwbrx  r4, 0, r6
+
+       /*------- MCCR2 */
+
+#define MC2_TS_WAIT_TIMER              0               /* 0-7 */
+#define MC2_ASRISE                     8               /* 0-15 */
+#define MC2_ASFALL                     4               /* 0-15 */
+#define MC2_INLINE_PAR_NOT_ECC         0               /* 0-1 */
+#define MC2_WRITE_PARITY_CHK_EN                MC_ECC          /* 0-1 */
+#define MC2_INLRD_PARECC_CHK_EN                MC_ECC          /* 0-1 */
+#define MC2_ECC_EN                     0               /* 0-1 */
+#define MC2_EDO                                0               /* 0-1 */
+/* 
+*  N.B. This refresh interval looks good up to 85 MHz with Hynix SDRAM.
+*  May need to be decreased for 100 MHz
+*/
+#define MC2_REFINT                     0x3a5           /* 0-0x3fff */
+#define MC2_RSV_PG                     0               /* 0-1 */
+#define MC2_RMW_PAR                    MC_ECC          /* 0-1 */
+
+       LOADPTR (r3, MEM_CONT2_ADR)     /* Set MCCR2 (F4) */
+       stwbrx  r3,0,r5
+       LOADPTR(r4, \
+               MC2_TS_WAIT_TIMER << 29 | MC2_ASRISE << 25 | \
+               MC2_ASFALL << 21 | MC2_INLINE_PAR_NOT_ECC << 20 | \
+               MC2_WRITE_PARITY_CHK_EN << 19 | \
+               MC2_INLRD_PARECC_CHK_EN << 18 | \
+               MC2_ECC_EN << 17 | MC2_EDO << 16 | \
+               MC2_REFINT << 2 | MC2_RSV_PG << 1 | MC2_RMW_PAR)
+        cmpl   0, 0, r7, r9            /* Check for Kahlua2 */
+        bne     notK2
+        /* clear Kahlua2 reserved bits */
+       LOADPTR (r3, 0xfffcffff)
+       and     r4, r4, r3
+notK2:
+       stwbrx  r4,0,r6
+
+       /*------- MCCR3 */
+
+#define MC_BSTOPRE                     0x079           /* 0-0x7ff */
+
+#define MC3_BSTOPRE_U                  (MC_BSTOPRE >> 4 & 0xf)
+#define MC3_REFREC                     8               /* 0-15 */
+#define MC3_RDLAT                      (4+MC_ECC)      /* 0-15 */
+#define MC3_CPX                                0               /* 0-1 */
+#define MC3_RAS6P                      0               /* 0-15 */
+#define MC3_CAS5                       0               /* 0-7 */
+#define MC3_CP4                                0               /* 0-7 */
+#define MC3_CAS3                       0               /* 0-7 */
+#define MC3_RCD2                       0               /* 0-7 */
+#define MC3_RP1                                0               /* 0-7 */
+
+       LOADPTR (r3, MEM_CONT3_ADR)     /* Set MCCR3 (F8) */
+       stwbrx  r3,0,r5
+       LOADPTR(r4, \
+               MC3_BSTOPRE_U << 28 | MC3_REFREC << 24 | \
+               MC3_RDLAT << 20 | MC3_CPX << 19 | \
+               MC3_RAS6P << 15 | MC3_CAS5 << 12 | MC3_CP4 << 9 | \
+               MC3_CAS3 << 6 | MC3_RCD2 << 3 | MC3_RP1)
+        cmpl   0, 0, r7, r9              /* Check for Kahlua2 */
+        bne     notK2b
+        /* clear Kahlua2 reserved bits */
+       LOADPTR (r3, 0xff000000)
+       and     r4, r4, r3
+notK2b:
+       stwbrx  r4,0,r6
+
+       /*------- MCCR4 */
+
+#define MC4_PRETOACT                   3               /* 0-15 */
+#define MC4_ACTOPRE                    5               /* 0-15 */
+#define MC4_WMODE                      0               /* 0-1 */
+#define MC4_INLINE                     MC_ECC          /* 0-1 */
+#define MC4_REGISTERED                 (1-MC_ECC)      /* 0-1 */
+#define MC4_BSTOPRE_UU                 (MC_BSTOPRE >> 8 & 3)
+#define MC4_REGDIMM                    0               /* 0-1 */
+#define MC4_SDMODE_CAS                 2               /* 0-7 */
+#define MC4_DBUS_RCS1                  1               /* 0-1, 8-bit */
+#define MC4_SDMODE_WRAP                        0               /* 0-1 */
+#define MC4_SDMODE_BURST               2               /* 0-7 */
+#define MC4_ACTORW                     3               /* 0-15 */
+#define MC4_BSTOPRE_L                  (MC_BSTOPRE & 0xf)
+
+       LOADPTR (r3, MEM_CONT4_ADR)     /* Set MCCR4 (FC) */
+       stwbrx  r3,0,r5
+       LOADPTR(r4, \
+               MC4_PRETOACT << 28 | MC4_ACTOPRE << 24 | \
+               MC4_WMODE << 23 | MC4_INLINE << 22 | \
+               MC4_REGISTERED << 20 | MC4_BSTOPRE_UU << 18 | \
+               MC4_DBUS_RCS1 << 17 | \
+               MC4_REGDIMM << 15 | MC4_SDMODE_CAS << 12 | \
+               MC4_SDMODE_WRAP << 11 | MC4_SDMODE_BURST << 8 | \
+               MC4_ACTORW << 4 | MC4_BSTOPRE_L)
+        cmpl   0, 0, r7, r9                /* Check for Kahlua 2 */
+        bne     notK2c
+        /* Turn on Kahlua2 extended ROM space */
+       LOADPTR (r3, 0x00200000)
+       or      r4, r4, r3
+notK2c:
+       stwbrx  r4,0,r6
+
+#ifdef INCLUDE_ECC
+       /*------- MEM_ERREN1 */
+
+       LOADPTR (r3, MEM_ERREN1_ADR)    /* Set MEM_ERREN1 (c0) */
+       stwbrx  r3,0,r5
+       lwbrx   r4,0,r6
+       ori     r4,r4,4                 /* Set MEM_PERR_EN */
+       stwbrx  r4,0,r6
+#endif /* INCLUDE_ECC */
+
+       /*------- MSAR/MEAR */
+
+       LOADPTR (r3, MEM_START1_ADR)    /* Set MSAR1 (80) */
+       stwbrx  r3,0,r5
+       LOADPTR (r4, 0xc0804000)
+       stwbrx  r4,0,r6
+
+       LOADPTR (r3, MEM_START2_ADR)    /* Set MSAR2 (84) */
+       stwbrx  r3,0,r5
+       LOADPTR (r4, 0xc0804000)
+       stwbrx  r4,0,r6
+
+       LOADPTR (r3, XMEM_START1_ADR)   /* Set MESAR1 (88) */
+       stwbrx  r3,0,r5
+       LOADPTR (r4, 0x00000000)
+       stwbrx  r4,0,r6
+
+       LOADPTR (r3, XMEM_START2_ADR)   /* Set MESAR2 (8c) */
+       stwbrx  r3,0,r5
+       LOADPTR (r4, 0x01010101)
+       stwbrx  r4,0,r6
+
+       LOADPTR (r3, MEM_END1_ADR)      /* Set MEAR1 (90) */
+       stwbrx  r3,0,r5
+       LOADPTR (r4, 0xffbf7f3f)
+       stwbrx  r4,0,r6
+
+       LOADPTR (r3, MEM_END2_ADR)      /* Set MEAR2 (94) */
+       stwbrx  r3,0,r5
+       LOADPTR (r4, 0xffbf7f3f)
+       stwbrx  r4,0,r6
+
+       LOADPTR (r3, XMEM_END1_ADR)     /* MEEAR1 (98) */
+       stwbrx  r3,0,r5
+       LOADPTR (r4, 0x00000000)
+       stwbrx  r4,0,r6
+
+       LOADPTR (r3, XMEM_END2_ADR)     /* MEEAR2 (9c) */
+       stwbrx  r3,0,r5
+       LOADPTR (r4, 0x01010101)
+       stwbrx  r4,0,r6
+
+       /*-------ODCR */
+
+       LOADPTR (r3, ODCR_ADR_X)        /* Set ODCR */
+       stwbrx  r3,0,r5
+
+       li      r4, 0x7f
+       stb     r4, ODCR_SHIFT(r6)      /* ODCR is at +3 offset */
+
+       /*-------MBEN */
+
+       LOADPTR (r3, MEM_EN_ADR)        /* Set MBEN (a0) */
+       stwbrx  r3,0,r5
+       li      r4, 0x01                /* Enable bank 0 */
+       stb     r4, 0(r6)               /* MBEN is at +0 offset */
+
+#if 0   /* Jimmy:  I think page made is broken */
+       /*-------PGMAX */
+
+       LOADPTR (r3, MPM_ADR_X)
+       stwbrx  r3,0,r5
+       li      r4, 0x32
+       stb     r4, MPM_SHIFT(r6)               /* PAGE_MODE is at +3 offset */
+#endif
+
+       /* Wait before initializing other registers */
+
+       lis     r4,0x0001
+       mtctr   r4
+
+KahluaX4wait200us:
+       bdnz    KahluaX4wait200us
+
+       /* Set MEMGO bit */
+
+       LOADPTR (r3, MEM_CONT1_ADR)     /* MCCR1 (F0) |= PGMAX */
+       stwbrx  r3,0,r5
+       lwbrx   r4,0,r6                 /* old MCCR1 */
+       oris    r4,r4,0x0008            /* MEMGO=1 */
+       stwbrx  r4, 0, r6
+
+       /* Wait again */
+
+       addis   r4,r0,0x0002
+       ori     r4,r4,0xffff
+
+       mtctr   r4
+
+KahluaX4wait8ref:
+       bdnz    KahluaX4wait8ref
+
+       sync
+       eieio
+        mtlr    r11
+       blr
+
+#else /* USE_V2_INIT */
+
+
+
+/* PPCBoot works, but memory will not run reliably for all address ranges.
+ * Early PPCBoot Working init, but 2.4.19 kernel will crash since memory is not
+ * initialized correctly. Could work if debugged.
+ */
+/* PCI Support routines */
+
+    .globl __pci_config_read_32
+__pci_config_read_32:
+    lis     r4, 0xfec0
+    stwbrx   r3, r0, r4
+    sync
+    lis     r4, 0xfee0
+    lwbrx   r3, 0, r4
+    blr
+    .globl __pci_config_read_16
+__pci_config_read_16:
+    lis     r4, 0xfec0
+    andi.    r5, r3, 2
+    stwbrx  r3, r0, r4
+    sync
+    oris     r4, r5, 0xfee0
+    lhbrx    r3, r0, r4
+    blr
+    .globl __pci_config_read_8
+__pci_config_read_8:
+    lis     r4, 0xfec0
+    andi.    r5, r3, 3
+    stwbrx  r3, r0, r4
+    sync
+    oris     r4, r5, 0xfee0
+    lbz      r3, 0(4)
+    blr
+    .globl __pci_config_write_32
+__pci_config_write_32:
+    lis     r5, 0xfec0
+    stwbrx   r3, r0, r5
+    sync
+    lis      r5, 0xfee0
+    stwbrx   r4, r0, r5
+    sync
+    blr
+    .globl __pci_config_write_16
+__pci_config_write_16:
+    lis     r5, 0xfec0
+    andi.    r6, r3, 2
+    stwbrx  r3, r0, 5
+    sync
+    oris     r5, r6, 0xfee0
+    sthbrx    r4, r0, r5
+    sync
+    blr
+    .globl __pci_config_write_8
+__pci_config_write_8:
+    lis      r5, 0xfec0
+    andi.    r6, r3, 3
+    stwbrx   r3, r0, r5
+    sync
+    oris      r5, r6, 0xfee0
+    stb       r4, 0(r5)
+    sync
+    blr
+    .globl  in_8
+in_8:
+    oris    r3, r3, 0xfe00
+    lbz     r3,0(r3)
+    blr
+    .globl  in_16
+in_16:
+    oris    r3, r3, 0xfe00
+    lhbrx   r3, 0, r3
+    blr
+    .globl in_16_ne
+in_16_ne:
+    oris    r3, r3, 0xfe00
+    lhzx    r3, 0, r3
+    blr
+    .globl  in_32
+in_32:
+    oris    r3, r3, 0xfe00
+    lwbrx   r3, 0, r3
+    blr
+    .globl  out_8
+out_8:
+    oris    r3, r3, 0xfe00
+    stb     r4, 0(r3)
+    eieio
+    blr
+    .globl  out_16
+out_16:
+    oris    r3, r3, 0xfe00
+    sthbrx  r4, 0, r3
+    eieio
+    blr
+    .globl  out_16_ne
+out_16_ne:
+    oris    r3, r3, 0xfe00
+    sth     r4, 0(r3)
+    eieio
+    blr
+    .globl  out_32
+out_32:
+    oris    r3, r3, 0xfe00
+    stwbrx  r4, 0, r3
+    eieio
+    blr
+    .globl  read_8
+read_8:
+    lbz     r3,0(r3)
+    blr
+    .globl  read_16
+read_16:
+    lhbrx   r3, 0, r3
+    blr
+    .globl  read_32
+read_32:
+    lwbrx   r3, 0, r3
+    blr
+    .globl  read_32_ne
+read_32_ne:
+    lwz     r3, 0(r3)
+    blr
+    .globl  write_8
+write_8:
+    stb     r4, 0(r3)
+    eieio
+    blr
+    .globl  write_16
+write_16:
+    sthbrx  r4, 0, r3
+    eieio
+    blr
+    .globl  write_32
+write_32:
+    stwbrx  r4, 0, r3
+    eieio
+    blr
+    .globl  write_32_ne
+write_32_ne:
+    stw     r4, 0(r3)
+    eieio
+    blr
+  
+
+.globl  early_init_f
+
+early_init_f:
+        mflr    r11
+        lis     r10, 0x8000
+
+        /* PCI Latency Timer */
+        li      r4, 0x0d
+        ori     r3, r10, PLTR@l
+        bl      __pci_config_write_8
+        
+        /* Cache Line Size */
+        li      r4, 0x08
+        ori     r3, r10, PCLSR@l
+        bl      __pci_config_write_8
+        
+        /* PCI Cmd */
+        li      r4, 6
+        ori     r3, r10, PCICR@l
+        bl      __pci_config_write_16
+        
+#if 1
+        /* PCI Stat */
+        ori     r3, r10, PCISR@l
+        bl      __pci_config_read_16
+        ori     r4, r4, 0xffff
+        ori     r3, r10, PCISR@l
+        bl      __pci_config_write_16
+#endif        
+
+        /* PICR1 */
+        lis     r4, 0xff14
+        ori     r4, r4, 0x1b98
+        ori     r3, r10, PICR1@l
+        bl      __pci_config_write_32
+
+
+        /* PICR2 */
+        lis     r4, 0x0404
+        ori     r4, r4, 0x0004
+        ori     r3, r10, PICR2@l
+        bl      __pci_config_write_32
+
+       /* MIOCR1 */
+        li      r4, 0x04
+        ori     r3, r10, MIOCR1@l
+        bl      __pci_config_write_8
+
+       /* For the MPC8245, set register 77 to %00100000 (see Errata #15) */
+       /* SDRAM_CLK_DEL (0x77)*/
+        li      r4, 0x10
+        ori     r3, r10, MIOCR2@l
+        bl      __pci_config_write_8
+
+        /* EUMBBAR */
+        lis     r4, 0xfc00
+        ori     r3, r10, EUMBBAR@l
+        bl      __pci_config_write_32
+
+       /* AMBOR */
+
+       /* Even if Address Map B is not being used (though it should),
+        * the memory DLL needs to be cleared/set/cleared before using memory.
+       */
+
+        ori     r3, r10, AMBOR@l
+        bl      __pci_config_read_8    /* get Current bits */
+
+        andi.   r4, r4, 0xffdf
+        ori     r3, r10, AMBOR@l
+        bl      __pci_config_write_16  /* Clear DLL_RESET */
+
+        ori    r4, r4, 0x0020
+        ori     r3, r10, AMBOR@l
+        bl      __pci_config_write_16  /* Set DLL_RESET */
+
+        andi.   r4, r4, 0xffdf
+        ori     r3, r10, AMBOR@l
+        bl      __pci_config_write_16  /* Clear DLL_RESET */
+
+        /* ERCR1 */
+        lis     r4, 0x8040             /* Enable RCS2, use supplied timings */
+        ori     r4, r4, 0x8000
+        ori     r3, r10, ERCR1@l
+        bl      __pci_config_write_32
+
+        /* ERCR2 */
+        lis     r4, 0x0000             /* Disable RCS3 parms */
+        ori     r4, r4, 0x0000
+        ori     r3, r10, ERCR2@l
+        bl      __pci_config_write_32
+
+        /* ERCR3 */
+        lis     r4, 0x0000             /* RCS3 at 0x70000000, 64K bytes */
+        ori     r4, r4, 0x0004
+        ori     r3, r10, ERCR2@l
+        bl      __pci_config_write_32
+
+       /* Preserve memgo bit */
+        /* MCCR1 */
+
+//     lis     r4, 0x75a8               // Safe Local ROM = 11+3 clocks
+       lis     r4, 0x75a0               // Safe Local ROM = 11+3 clocks
+//      lis     r4, 0x73a0               // Fast Local ROM = 7+3 clocks
+//      oris    r4, r4, 0x0010           // Burst ROM/Flash enable
+//      oris    r4, r4, 0x0004           // Self-refresh enable
+
+//      ori     r4,r4,0xFFFF            // 16Mbit  2bank SDRAM
+//      ori     r4,r4,0xAAAA            // 256Mbit 4bank SDRAM (8245 only)
+//      ori     r4,r4,0x5555            // 64Mbit  2bank SDRAM
+        ori     r4,r4,0x0000            // 64Mbit  4bank SDRAM
+
+        ori     r3, r10, MCCR1@l
+        bl      __pci_config_write_32
+
+        /* MCCR2 */
+
+        lis     r4,0x0000
+/*      oris    r4,r4,0x4000            // TS_WAIT_TIMER = 3 clocks */
+        oris    r4,r4,0x1000            // ASRISE = 8 clocks 
+        oris    r4,r4,0x0080            // ASFALL = 8 clocks 
+/*      oris    r4,r4,0x0010            // SDRAM Parity (else ECC) */
+/*      oris    r4,r4,0x0008            // Write parity check */
+/*      oris    r4,r4,0x0004            // SDRAM inline reads */
+
+
+/* Select a refresh rate; it needs to match the bus speed; if too */
+/* slow, data may be lost; if too fast, performance is lost.  We */
+/* use the fastest value so we run at all speeds. */
+/* Refresh = (15600ns/busclk) - (213 (see UM)). */
+
+/*      ori     r4,r4,0x1d2c            // 133 MHz mem bus        = 1867 */
+/*      ori     r4,r4,0x150c            // 100 MHz mem bus        = 1347 */
+/*      ori     r4,r4,0x10fc            //  83 MHz mem bus        = 1087 */
+/*      ori     r4,r4,0x0cc4            //  66 MHz mem bus        =  817 */
+        ori     r4,r4,0x04cc            //  33 MHz mem bus (SAFE) =  307 */
+/*      ori     r4,r4,0x0002            // Reserve a page */
+/*      ori     r4,r4,0x0001            // RWM parity */
+
+        ori     r3, r10, MCCR2@l
+        bl      __pci_config_write_32
+
+
+        /* MCCR3 */
+        lis     r4,0x0000               // BSTOPRE_M = 7 (see A/N)
+        oris    r4,r4,0x0500            // REFREC    = 8 clocks
+        ori     r3, r10, MCCR3@l
+        bl      __pci_config_write_32
+
+        /* MCCR4 */                     /* Turn on registered buffer mode */
+        lis     r4, 0x2000              // PRETOACT = 3 clocks
+        oris    r4,r4,0x0400            // ACTOPRE  = 5 clocks
+//      oris    r4,r4,0x0080            // Enable 8-beat burst (32-bit bus)
+//      oris    r4,r4,0x0040            // Enable Inline ECC/Parity
+        oris    r4,r4,0x0020            // EXTROM enabled
+        oris    r4,r4,0x0010            // Registered buffers
+//      oris    r4,r4,0x0000            // BSTOPRE_U = 0 (see A/N)
+        oris    r4,r4,0x0002            // DBUS_SIZ[2] (8 bit on RCS1)
+
+//      ori     r4,r4,0x8000            // Registered DIMMs
+        ori     r4,r4,0x2000            //CAS Latency (CL=3) (see RDLAT) 
+//      ori     r4,r4,0x2000            // CAS Latency (CL=2) (see RDLAT)
+//      ori     r4,r4,0x0300            // Sequential wrap/8-beat burst
+        ori     r4,r4,0x0200            // Sequential wrap/4-beat burst
+        ori     r4,r4,0x0030            // ACTORW  = 3 clocks
+        ori     r4,r4,0x0009            // BSTOPRE_L = 9 (see A/N)
+
+        ori     r3, r10, MCCR4@l
+        bl      __pci_config_write_32
+
+       /* MSAR1 */
+        lis     r4, 0xc0804000@h
+        ori     r4, r4, 0xc0804000@l
+        ori     r3, r10, MSAR1@l
+        bl      __pci_config_write_32
+
+       /* MSAR2 */
+        lis     r4, 0xc0804000@h
+        ori     r4, r4, 0xc0804000@l
+        ori     r3, r10, MSAR2@l
+        bl      __pci_config_write_32
+
+       /* MESAR1 */
+        lis     r4, 0x00000000@h
+        ori     r4, r4, 0x00000000@l
+        ori     r3, r10, EMSAR1@l
+        bl      __pci_config_write_32
+
+       /* MESAR2 */
+        lis     r4, 0x01010101@h
+        ori     r4, r4, 0x01010101@l
+        ori     r3, r10, EMSAR2@l
+        bl      __pci_config_write_32
+
+       /* MEAR1 */
+        lis     r4, 0xffbf7f3f@h
+        ori     r4, r4, 0xffbf7f3f@l
+        ori     r3, r10, MEAR1@l
+        bl      __pci_config_write_32
+
+       /* MEAR2 */
+        lis     r4, 0xffbf7f3f@h
+        ori     r4, r4, 0xffbf7f3f@l
+        ori     r3, r10, MEAR2@l
+        bl      __pci_config_write_32
+
+       /* MEEAR1 */
+        lis     r4, 0x00000000@h
+        ori     r4, r4, 0x00000000@l
+        ori     r3, r10, EMEAR1@l
+        bl      __pci_config_write_32
+
+       /* MEEAR2 */
+        lis     r4, 0x01010101@h
+        ori     r4, r4, 0x01010101@l
+        ori     r3, r10, EMEAR2@l
+        bl      __pci_config_write_32
+
+       /* ODCR */
+        li      r4, 0x7f
+        ori     r3, r10, ODCR@l
+        bl      __pci_config_write_8
+
+       /* MBER */
+        li      r4, 0x01
+        ori     r3, r10, MBER@l
+        bl      __pci_config_write_8
+
+        /* Page CTR aka PGMAX */
+        li      r4, 0x32
+        ori     r3, r10, 0x70
+        bl      __pci_config_write_8
+        
+#if 0
+       /* CLK Drive */
+        ori     r4, r10, 0xfc01 /* Top bit will be ignored */
+        ori     r3, r10, 0x74
+        bl      __pci_config_write_16
+#endif
+
+       /* delay */ 
+        lis     r7, 1
+        mtctr   r7
+label1:        bdnz    label1
+
+        /* Set memgo bit */
+        /* MCCR1 */
+        ori     r3, r10, MCCR1@l
+        bl      __pci_config_read_32
+        lis    r7, 0x0008
+        or     r4, r3, r7
+        ori     r3, r10, MCCR1@l
+        bl      __pci_config_write_32
+
+       /* delay again */ 
+        lis     r7, 1
+        mtctr   r7
+label2:        bdnz    label2
+#if 0
+/* DEBUG: Infinite loop, write then read */
+loop:
+        lis     r7, 0xffff
+        mtctr   r7
+        li     r3, 0x5004
+        lis    r4, 0xa0a0
+        ori    r4, r4, 0x5050
+       bl write_32_ne
+        li     r3, 0x5004
+       bl read_32_ne
+       bdnz    loop
+#endif
+        mtlr    r11
+        blr
+#endif
+
diff --git a/board/bmw/flash.c b/board/bmw/flash.c
new file mode 100644 (file)
index 0000000..c433b51
--- /dev/null
@@ -0,0 +1,757 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppcboot.h>
+#include <mpc824x.h>
+#include <asm/processor.h>
+#include <asm/pci_io.h>
+
+#define ROM_CS0_START  0xFF800000
+#define ROM_CS1_START  0xFF000000
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips    */
+
+#if defined(CFG_ENV_IS_IN_FLASH)
+# ifndef  CFG_ENV_ADDR
+#  define CFG_ENV_ADDR  (CFG_FLASH_BASE + CFG_ENV_OFFSET)
+# endif
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE  CFG_ENV_SECT_SIZE
+# endif
+# ifndef  CFG_ENV_SECT_SIZE
+#  define CFG_ENV_SECT_SIZE  CFG_ENV_SIZE
+# endif
+#endif
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+#if 0
+static void flash_get_offsets (ulong base, flash_info_t *info);
+#endif /* 0 */
+
+/*flash command address offsets*/
+
+#if 0
+#define ADDR0           (0x555)
+#define ADDR1           (0x2AA)
+#define ADDR3           (0x001)
+#else
+#define ADDR0          (0xAAA)
+#define ADDR1          (0x555)
+#define ADDR3          (0x001)
+#endif
+
+#define FLASH_WORD_SIZE unsigned char
+
+/*-----------------------------------------------------------------------
+ */
+
+#if 0
+static int byte_parity_odd(unsigned char x) __attribute__ ((const));
+#endif /* 0 */
+static unsigned long flash_id(unsigned char mfct, unsigned char chip) __attribute__ ((const));
+
+typedef struct
+{
+  FLASH_WORD_SIZE extval;
+  unsigned short intval;
+} map_entry;
+
+#if 0
+static int
+byte_parity_odd(unsigned char x)
+{
+  x ^= x >> 4;
+  x ^= x >> 2;
+  x ^= x >> 1;
+  return (x & 0x1) != 0;
+}
+#endif /* 0 */
+
+
+
+static unsigned long
+flash_id(unsigned char mfct, unsigned char chip)
+{
+  static const map_entry mfct_map[] =
+    {
+      {(FLASH_WORD_SIZE) AMD_MANUFACT, (unsigned short) ((unsigned long) FLASH_MAN_AMD >> 16)},
+      {(FLASH_WORD_SIZE) FUJ_MANUFACT, (unsigned short) ((unsigned long) FLASH_MAN_FUJ >> 16)},
+      {(FLASH_WORD_SIZE) STM_MANUFACT, (unsigned short) ((unsigned long) FLASH_MAN_STM >> 16)},
+      {(FLASH_WORD_SIZE) MT_MANUFACT,  (unsigned short) ((unsigned long) FLASH_MAN_MT >> 16)},
+      {(FLASH_WORD_SIZE) INTEL_MANUFACT,(unsigned short) ((unsigned long) FLASH_MAN_INTEL >> 16)},
+      {(FLASH_WORD_SIZE) INTEL_ALT_MANU,(unsigned short) ((unsigned long) FLASH_MAN_INTEL >> 16)}
+    };
+
+  static const map_entry chip_map[] =
+  {
+    {AMD_ID_F040B,     FLASH_AM040},
+    {(FLASH_WORD_SIZE) STM_ID_x800AB,  FLASH_STM800AB}
+  };
+
+  const map_entry *p;
+  unsigned long result = FLASH_UNKNOWN;
+
+  /* find chip id */
+  for(p = &chip_map[0]; p < &chip_map[sizeof chip_map / sizeof chip_map[0]]; p++)
+    if(p->extval == chip)
+    {
+      result = FLASH_VENDMASK | p->intval;
+      break;
+    }
+
+  /* find vendor id */
+  for(p = &mfct_map[0]; p < &mfct_map[sizeof mfct_map / sizeof mfct_map[0]]; p++)
+    if(p->extval == mfct)
+    {
+      result &= ~FLASH_VENDMASK;
+      result |= (unsigned long) p->intval << 16;
+      break;
+    }
+
+  return result;
+}
+
+
+
+unsigned long
+flash_init(void)
+{
+  unsigned long i;
+  unsigned char j;
+  static const ulong flash_banks[] = CFG_FLASH_BANKS;
+
+  /* Init: no FLASHes known */
+  for (i = 0; i < CFG_MAX_FLASH_BANKS; i++)
+  {
+    flash_info_t * const pflinfo = &flash_info[i];
+    pflinfo->flash_id = FLASH_UNKNOWN;
+    pflinfo->size = 0;
+    pflinfo->sector_count = 0;
+  }
+
+  for(i = 0; i < sizeof flash_banks / sizeof flash_banks[0]; i++)
+  {
+    flash_info_t * const pflinfo = &flash_info[i];
+    const unsigned long base_address = flash_banks[i];
+    volatile FLASH_WORD_SIZE * const flash = (FLASH_WORD_SIZE *) base_address;
+#if 0
+    volatile FLASH_WORD_SIZE * addr2;
+#endif
+#if 0
+    /* write autoselect sequence */
+    flash[0x5555] = 0xaa;
+    flash[0x2aaa] = 0x55;
+    flash[0x5555] = 0x90;
+#else
+    flash[0xAAA << (3 * i)] = 0xaa;
+    flash[0x555 << (3 * i)] = 0x55;
+    flash[0xAAA << (3 * i)] = 0x90;
+#endif
+    __asm__ __volatile__("sync");
+
+#if 0
+    pflinfo->flash_id = flash_id(flash[0x0], flash[0x1]);
+#else
+    pflinfo->flash_id = flash_id(flash[0x0], flash[0x2 + 14 * i]);
+#endif
+    
+    switch(pflinfo->flash_id & FLASH_TYPEMASK)
+    {
+      case FLASH_AM040:
+        pflinfo->size = 0x00080000;
+       pflinfo->sector_count = 8;
+        for(j = 0; j < 8; j++)
+       {
+         pflinfo->start[j] = base_address + 0x00010000 * j;
+         pflinfo->protect[j] = flash[(j << 16) | 0x2];
+       }
+       break;
+      case FLASH_STM800AB:
+       pflinfo->size = 0x00100000;
+       pflinfo->sector_count = 19;
+       pflinfo->start[0] = base_address;
+       pflinfo->start[1] = base_address + 0x4000;
+       pflinfo->start[2] = base_address + 0x6000;
+       pflinfo->start[3] = base_address + 0x8000;
+       for(j = 1; j < 16; j++)
+       {
+         pflinfo->start[j+3] = base_address + 0x00010000 * j;
+       }
+#if 0
+        /* check for protected sectors */
+        for (j = 0; j < pflinfo->sector_count; j++) {
+          /* read sector protection at sector address, (A7 .. A0) = 0x02 */
+          /* D0 = 1 if protected */
+          addr2 = (volatile FLASH_WORD_SIZE *)(pflinfo->start[j]);
+            if (pflinfo->flash_id & FLASH_MAN_SST)
+              pflinfo->protect[j] = 0;
+            else
+              pflinfo->protect[j] = addr2[2] & 1;
+        }
+#endif
+       break;
+    }
+    /* Protect monitor and environment sectors
+     */
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+    flash_protect(FLAG_PROTECT_SET,
+               CFG_MONITOR_BASE,
+               CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1,
+               &flash_info[0]);
+#endif
+
+#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR)
+    flash_protect(FLAG_PROTECT_SET,
+               CFG_ENV_ADDR,
+               CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
+               &flash_info[0]);
+#endif
+
+    /* reset device to read mode */
+    flash[0x0000] = 0xf0;
+    __asm__ __volatile__("sync");
+  }
+
+    return flash_info[0].size + flash_info[1].size;
+}
+
+#if 0
+static void
+flash_get_offsets (ulong base, flash_info_t *info)
+{
+    int i;
+
+    /* set up sector start address table */
+        if (info->flash_id & FLASH_MAN_SST)
+          {
+            for (i = 0; i < info->sector_count; i++)
+              info->start[i] = base + (i * 0x00010000);
+          }
+        else
+    if (info->flash_id & FLASH_BTYPE) {
+        /* set sector offsets for bottom boot block type    */
+        info->start[0] = base + 0x00000000;
+        info->start[1] = base + 0x00004000;
+        info->start[2] = base + 0x00006000;
+        info->start[3] = base + 0x00008000;
+        for (i = 4; i < info->sector_count; i++) {
+            info->start[i] = base + (i * 0x00010000) - 0x00030000;
+        }
+    } else {
+        /* set sector offsets for top boot block type       */
+        i = info->sector_count - 1;
+        info->start[i--] = base + info->size - 0x00004000;
+        info->start[i--] = base + info->size - 0x00006000;
+        info->start[i--] = base + info->size - 0x00008000;
+        for (; i >= 0; i--) {
+            info->start[i] = base + i * 0x00010000;
+        }
+    }
+
+}
+#endif /* 0 */
+
+/*-----------------------------------------------------------------------
+ */
+void
+flash_print_info(flash_info_t *info)
+{
+  static const char unk[] = "Unknown";
+  const char *mfct = unk, *type = unk;
+  unsigned int i;
+
+  if(info->flash_id != FLASH_UNKNOWN)
+  {
+    switch(info->flash_id & FLASH_VENDMASK)
+    {
+      case FLASH_MAN_AMD:      mfct = "AMD";                           break;
+      case FLASH_MAN_FUJ:      mfct = "FUJITSU";                       break;
+      case FLASH_MAN_STM:      mfct = "STM";                           break;
+      case FLASH_MAN_SST:      mfct = "SST";                           break;
+      case FLASH_MAN_BM:       mfct = "Bright Microelectonics";        break;
+      case FLASH_MAN_INTEL:    mfct = "Intel";                         break;
+    }
+
+    switch(info->flash_id & FLASH_TYPEMASK)
+    {
+      case FLASH_AM040:                type = "AM29F040B (512K * 8, uniform sector size)";     break;
+      case FLASH_AM400B:       type = "AM29LV400B (4 Mbit, bottom boot sect)";         break;
+      case FLASH_AM400T:       type = "AM29LV400T (4 Mbit, top boot sector)";          break;
+      case FLASH_AM800B:       type = "AM29LV800B (8 Mbit, bottom boot sect)";         break;
+      case FLASH_AM800T:       type = "AM29LV800T (8 Mbit, top boot sector)";          break;
+      case FLASH_AM160T:       type = "AM29LV160T (16 Mbit, top boot sector)";         break;
+      case FLASH_AM320B:       type = "AM29LV320B (32 Mbit, bottom boot sect)";        break;
+      case FLASH_AM320T:       type = "AM29LV320T (32 Mbit, top boot sector)";         break;
+      case FLASH_STM800AB:     type = "M29W800AB (8 Mbit, bottom boot sect)";          break;
+      case FLASH_SST800A:      type = "SST39LF/VF800 (8 Mbit, uniform sector size)";   break;
+      case FLASH_SST160A:      type = "SST39LF/VF160 (16 Mbit, uniform sector size)";  break;
+    }
+  }
+
+  printf(
+    "\n  Brand: %s Type: %s\n"
+    "  Size: %lu KB in %d Sectors\n",
+    mfct,
+    type,
+    info->size >> 10,
+    info->sector_count
+  );
+
+  printf ("  Sector Start Addresses:");
+
+  for (i = 0; i < info->sector_count; i++)
+  {
+    unsigned long size;
+    unsigned int erased;
+    unsigned long * flash = (unsigned long *) info->start[i];
+
+    /*
+     * Check if whole sector is erased
+     */
+    size =
+      (i != (info->sector_count - 1)) ?
+      (info->start[i + 1] - info->start[i]) >> 2 :
+      (info->start[0] + info->size - info->start[i]) >> 2;
+
+    for(
+      flash = (unsigned long *) info->start[i], erased = 1;
+      (flash != (unsigned long *) info->start[i] + size) && erased;
+      flash++
+    )
+      erased = *flash == ~0x0UL;
+
+    printf(
+      "%s %08lX %s %s",
+      (i % 5) ? "" : "\n   ",
+      info->start[i],
+      erased ? "E" : " ",
+      info->protect[i] ? "RO" : "  "
+    );
+  }
+
+  puts("\n");
+  return;
+}
+
+#if 0
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+ulong
+flash_get_size (vu_long *addr, flash_info_t *info)
+{
+   short i;
+    FLASH_WORD_SIZE value;
+    ulong base = (ulong)addr;
+        volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr;
+
+    printf("flash_get_size: \n");
+    /* Write auto select command: read Manufacturer ID */
+    eieio();
+    addr2[ADDR0] = (FLASH_WORD_SIZE)0xAA;
+    addr2[ADDR1] = (FLASH_WORD_SIZE)0x55;
+    addr2[ADDR0] = (FLASH_WORD_SIZE)0x90;
+    value = addr2[0];
+
+    switch (value) {
+    case (FLASH_WORD_SIZE)AMD_MANUFACT:
+        info->flash_id = FLASH_MAN_AMD;
+        break;
+    case (FLASH_WORD_SIZE)FUJ_MANUFACT:
+        info->flash_id = FLASH_MAN_FUJ;
+        break;
+    case (FLASH_WORD_SIZE)SST_MANUFACT:
+        info->flash_id = FLASH_MAN_SST;
+        break;
+    default:
+        info->flash_id = FLASH_UNKNOWN;
+        info->sector_count = 0;
+        info->size = 0;
+        return (0);         /* no or unknown flash  */
+    }
+    printf("recognised manufacturer");
+
+    value = addr2[ADDR3];          /* device ID        */
+        //        printf("\ndev_code=%x\n", value);
+
+    switch (value) {
+    case (FLASH_WORD_SIZE)AMD_ID_LV400T:
+        info->flash_id += FLASH_AM400T;
+        info->sector_count = 11;
+        info->size = 0x00080000;
+        break;              /* => 0.5 MB        */
+
+    case (FLASH_WORD_SIZE)AMD_ID_LV400B:
+        info->flash_id += FLASH_AM400B;
+        info->sector_count = 11;
+        info->size = 0x00080000;
+        break;              /* => 0.5 MB        */
+
+    case (FLASH_WORD_SIZE)AMD_ID_LV800T:
+        info->flash_id += FLASH_AM800T;
+        info->sector_count = 19;
+        info->size = 0x00100000;
+        break;              /* => 1 MB      */
+
+    case (FLASH_WORD_SIZE)AMD_ID_LV800B:
+        info->flash_id += FLASH_AM800B;
+        info->sector_count = 19;
+        info->size = 0x00100000;
+        break;              /* => 1 MB      */
+
+    case (FLASH_WORD_SIZE)AMD_ID_LV160T:
+        info->flash_id += FLASH_AM160T;
+        info->sector_count = 35;
+        info->size = 0x00200000;
+        break;              /* => 2 MB      */
+
+    case (FLASH_WORD_SIZE)AMD_ID_LV160B:
+        info->flash_id += FLASH_AM160B;
+        info->sector_count = 35;
+        info->size = 0x00200000;
+        break;              /* => 2 MB      */
+
+    case (FLASH_WORD_SIZE)SST_ID_xF800A:
+        info->flash_id += FLASH_SST800A;
+        info->sector_count = 16;
+        info->size = 0x00100000;
+        break;              /* => 1 MB      */
+
+    case (FLASH_WORD_SIZE)SST_ID_xF160A:
+        info->flash_id += FLASH_SST160A;
+        info->sector_count = 32;
+        info->size = 0x00200000;
+        break;              /* => 2 MB      */
+
+    case (FLASH_WORD_SIZE)AMD_ID_F040B:
+        info->flash_id += FLASH_AM040;
+        info->sector_count = 8;
+        info->size = 0x00080000;
+        break;              /* => 0.5 MB      */
+
+    default:
+        info->flash_id = FLASH_UNKNOWN;
+        return (0);         /* => no or unknown flash */
+
+    }
+
+    printf("flash id %lx; sector count %x, size %lx\n", info->flash_id,info->sector_count,info->size);
+    /* set up sector start address table */
+        if (info->flash_id & FLASH_MAN_SST)
+          {
+            for (i = 0; i < info->sector_count; i++)
+              info->start[i] = base + (i * 0x00010000);
+          }
+        else
+    if (info->flash_id & FLASH_BTYPE) {
+        /* set sector offsets for bottom boot block type    */
+        info->start[0] = base + 0x00000000;
+        info->start[1] = base + 0x00004000;
+        info->start[2] = base + 0x00006000;
+        info->start[3] = base + 0x00008000;
+        for (i = 4; i < info->sector_count; i++) {
+            info->start[i] = base + (i * 0x00010000) - 0x00030000;
+        }
+    } else {
+        /* set sector offsets for top boot block type       */
+        i = info->sector_count - 1;
+        info->start[i--] = base + info->size - 0x00004000;
+        info->start[i--] = base + info->size - 0x00006000;
+        info->start[i--] = base + info->size - 0x00008000;
+        for (; i >= 0; i--) {
+            info->start[i] = base + i * 0x00010000;
+        }
+    }
+
+    /* check for protected sectors */
+    for (i = 0; i < info->sector_count; i++) {
+        /* read sector protection at sector address, (A7 .. A0) = 0x02 */
+        /* D0 = 1 if protected */
+        addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]);
+                if (info->flash_id & FLASH_MAN_SST)
+                  info->protect[i] = 0;
+                else
+                  info->protect[i] = addr2[2] & 1;
+    }
+
+    /*
+     * Prevent writes to uninitialized FLASH.
+     */
+    if (info->flash_id != FLASH_UNKNOWN) {
+       addr2 = (FLASH_WORD_SIZE *)info->start[0];
+        *addr2 = (FLASH_WORD_SIZE)0x00F000F0;   /* reset bank */
+    }
+
+    return (info->size);
+}
+
+#endif
+
+
+int
+flash_erase(flash_info_t *info, int s_first, int s_last)
+{
+    volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
+    int flag, prot, sect, l_sect;
+    ulong start, now, last;
+    unsigned char sh8b;
+
+    if ((s_first < 0) || (s_first > s_last)) {
+        if (info->flash_id == FLASH_UNKNOWN) {
+            printf ("- missing\n");
+        } else {
+            printf ("- no sectors to erase\n");
+        }
+        return 1;
+    }
+
+    if ((info->flash_id == FLASH_UNKNOWN) ||
+        (info->flash_id > (FLASH_MAN_STM | FLASH_AMD_COMP))) {
+        printf ("Can't erase unknown flash type - aborted\n");
+        return 1;
+    }
+
+    prot = 0;
+    for (sect=s_first; sect<=s_last; ++sect) {
+        if (info->protect[sect]) {
+            prot++;
+        }
+    }
+
+    if (prot) {
+        printf ("- Warning: %d protected sectors will not be erased!\n",
+            prot);
+    } else {
+        printf ("\n");
+    }
+
+    l_sect = -1;
+
+    /* Check the ROM CS */
+    if ((info->start[0] >= ROM_CS1_START) && (info->start[0] < ROM_CS0_START))
+      sh8b = 3;
+    else
+      sh8b = 0;
+
+    /* Disable interrupts which might cause a timeout here */
+    flag = disable_interrupts();
+
+    addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
+    addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
+    addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00800080;
+    addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
+    addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
+
+    /* Start erase on unprotected sectors */
+    for (sect = s_first; sect<=s_last; sect++) {
+        if (info->protect[sect] == 0) { /* not protected */
+            addr = (FLASH_WORD_SIZE *)(info->start[0] + (
+                               (info->start[sect] - info->start[0]) << sh8b));
+                        if (info->flash_id & FLASH_MAN_SST)
+                          {
+                            addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
+                            addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
+                            addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00800080;
+                            addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
+                            addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
+                            addr[0] = (FLASH_WORD_SIZE)0x00500050;  /* block erase */
+                            udelay(30000);  /* wait 30 ms */
+                          }
+                        else
+                          addr[0] = (FLASH_WORD_SIZE)0x00300030;  /* sector erase */
+            l_sect = sect;
+        }
+    }
+
+    /* re-enable interrupts if necessary */
+    if (flag)
+        enable_interrupts();
+
+    /* wait at least 80us - let's wait 1 ms */
+    udelay (1000);
+
+    /*
+     * We wait for the last triggered sector
+     */
+    if (l_sect < 0)
+        goto DONE;
+
+    start = get_timer (0);
+    last  = start;
+    addr = (FLASH_WORD_SIZE *)(info->start[0] + (
+                       (info->start[l_sect] - info->start[0]) << sh8b));
+    while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
+        if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+            printf ("Timeout\n");
+            return 1;
+        }
+        /* show that we're waiting */
+        if ((now - last) > 1000) {  /* every second */
+            serial_putc ('.');
+            last = now;
+        }
+    }
+
+DONE:
+    /* reset to read mode */
+    addr = (FLASH_WORD_SIZE *)info->start[0];
+    addr[0] = (FLASH_WORD_SIZE)0x00F000F0;  /* reset bank */
+
+    printf (" done\n");
+    return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+    ulong cp, wp, data;
+    int i, l, rc;
+
+    wp = (addr & ~3);   /* get lower word aligned address */
+
+    /*
+     * handle unaligned start bytes
+     */
+    if ((l = addr - wp) != 0) {
+        data = 0;
+        for (i=0, cp=wp; i<l; ++i, ++cp) {
+            data = (data << 8) | (*(uchar *)cp);
+        }
+        for (; i<4 && cnt>0; ++i) {
+            data = (data << 8) | *src++;
+            --cnt;
+            ++cp;
+        }
+        for (; cnt==0 && i<4; ++i, ++cp) {
+            data = (data << 8) | (*(uchar *)cp);
+        }
+
+        if ((rc = write_word(info, wp, data)) != 0) {
+            return (rc);
+        }
+        wp += 4;
+    }
+
+    /*
+     * handle word aligned part
+     */
+    while (cnt >= 4) {
+        data = 0;
+        for (i=0; i<4; ++i) {
+            data = (data << 8) | *src++;
+        }
+        if ((rc = write_word(info, wp, data)) != 0) {
+            return (rc);
+        }
+        wp  += 4;
+        cnt -= 4;
+    }
+
+    if (cnt == 0) {
+        return (0);
+    }
+
+    /*
+     * handle unaligned tail bytes
+     */
+    data = 0;
+    for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+        data = (data << 8) | *src++;
+        --cnt;
+    }
+    for (; i<4; ++i, ++cp) {
+        data = (data << 8) | (*(uchar *)cp);
+    }
+
+    return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+        volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)info->start[0];
+        volatile FLASH_WORD_SIZE *dest2;
+        volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *)&data;
+    ulong start;
+    int flag;
+        int i;
+    unsigned char sh8b;
+
+    /* Check the ROM CS */
+    if ((info->start[0] >= ROM_CS1_START) && (info->start[0] < ROM_CS0_START))
+      sh8b = 3;
+    else
+      sh8b = 0;
+
+    dest2 = (FLASH_WORD_SIZE *)(((dest - info->start[0]) << sh8b) +
+                               info->start[0]);
+
+    /* Check if Flash is (sufficiently) erased */
+    if ((*dest2 & (FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) {
+        return (2);
+    }
+    /* Disable interrupts which might cause a timeout here */
+    flag = disable_interrupts();
+
+        for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++)
+          {
+            addr2[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
+            addr2[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
+            addr2[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00A000A0;
+
+            dest2[i << sh8b] = data2[i];
+
+            /* re-enable interrupts if necessary */
+            if (flag)
+              enable_interrupts();
+
+            /* data polling for D7 */
+            start = get_timer (0);
+            while ((dest2[i << sh8b] & (FLASH_WORD_SIZE)0x00800080) !=
+                   (data2[i] & (FLASH_WORD_SIZE)0x00800080)) {
+              if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+                return (1);
+              }
+            }
+          }
+
+    return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/bmw/m48t59y.c b/board/bmw/m48t59y.c
new file mode 100644 (file)
index 0000000..be31dfd
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * SGS M48-T59Y TOD/NVRAM Driver
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 1999, by Curt McDowell, 08-06-99, Broadcom Corp.
+ *
+ * (C) Copyright 2001, James Dougherty, 07/18/01, Broadcom Corp.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * SGS M48-T59Y TOD/NVRAM Driver
+ *
+ * The SGS M48 an 8K NVRAM starting at offset M48_BASE_ADDR and
+ * continuing for 8176 bytes. After that starts the Time-Of-Day (TOD)
+ * registers which are used to set/get the internal date/time functions.
+ *
+ * This module implements Y2K compliance by taking full year numbers
+ * and translating back and forth from the TOD 2-digit year.
+ *
+ * NOTE: for proper interaction with an operating system, the TOD should
+ * be used to store Universal Coordinated Time (GMT) and timezone
+ * conversions should be used.
+ *
+ * Here is a diagram of the memory layout:
+ *
+ * +---------------------------------------------+ 0xffe0a000
+ * | Non-volatile memory                         | .
+ * |                                             | .
+ * | (8176 bytes of Non-volatile memory)         | .
+ * |                                             | .
+ * +---------------------------------------------+ 0xffe0bff0
+ * | Flags                                       |
+ * +---------------------------------------------+ 0xffe0bff1
+ * | Unused                                      |
+ * +---------------------------------------------+ 0xffe0bff2
+ * | Alarm Seconds                               |
+ * +---------------------------------------------+ 0xffe0bff3
+ * | Alarm Minutes                               |
+ * +---------------------------------------------+ 0xffe0bff4
+ * | Alarm Date                                  |
+ * +---------------------------------------------+ 0xffe0bff5
+ * | Interrupts                                  |
+ * +---------------------------------------------+ 0xffe0bff6
+ * | WatchDog                                    |
+ * +---------------------------------------------+ 0xffe0bff7
+ * | Calibration                                 |
+ * +---------------------------------------------+ 0xffe0bff8
+ * | Seconds                                     |
+ * +---------------------------------------------+ 0xffe0bff9
+ * | Minutes                                     |
+ * +---------------------------------------------+ 0xffe0bffa
+ * | Hours                                       |
+ * +---------------------------------------------+ 0xffe0bffb
+ * | Day                                         |
+ * +---------------------------------------------+ 0xffe0bffc
+ * | Date                                        |
+ * +---------------------------------------------+ 0xffe0bffd
+ * | Month                                       |
+ * +---------------------------------------------+ 0xffe0bffe
+ * | Year (2 digits only)                        |
+ * +---------------------------------------------+ 0xffe0bfff
+ */
+#include <ppcboot.h>
+#include <rtc.h>
+#include "bmw.h"
+
+/*
+ * Imported from mousse.h:
+ *
+ *   TOD_REG_BASE              Base of m48t59y TOD registers
+ *   SYS_TOD_UNPROTECT()       Disable NVRAM write protect
+ *   SYS_TOD_PROTECT()         Re-enable NVRAM write protect
+ */
+
+#define YEAR           0xf
+#define MONTH          0xe
+#define DAY            0xd
+#define DAY_OF_WEEK    0xc
+#define HOUR           0xb
+#define MINUTE         0xa
+#define SECOND         0x9
+#define CONTROL                0x8
+#define WATCH          0x7
+#define INTCTL         0x6
+#define WD_DATE                0x5
+#define WD_HOUR                0x4
+#define WD_MIN         0x3
+#define WD_SEC         0x2
+#define _UNUSED                0x1
+#define FLAGS          0x0
+
+#define M48_ADDR       ((volatile unsigned char *) TOD_REG_BASE)
+
+int m48_tod_init(void)
+{
+    SYS_TOD_UNPROTECT();
+
+    M48_ADDR[CONTROL] = 0;
+    M48_ADDR[WATCH] = 0;
+    M48_ADDR[INTCTL] = 0;
+
+    /*
+     * If the oscillator is currently stopped (as on a new part shipped
+     * from the factory), start it running.
+     *
+     * Here is an example of the TOD bytes on a brand new M48T59Y part:
+     *         00 00 00 00 00 00 00 00 00 88 8c c3 bf c8 f5 01
+     */
+
+    if (M48_ADDR[SECOND] & 0x80)
+       M48_ADDR[SECOND] = 0;
+
+    /* Is battery low */
+    if ( M48_ADDR[FLAGS] & 0x10) {
+        printf("NOTICE: Battery low on Real-Time Clock (replace SNAPHAT).\n");
+    }
+    
+    SYS_TOD_PROTECT();
+
+    return 0;
+}
+
+/*
+ * m48_tod_set
+ */
+
+static int to_bcd(int value)
+{
+    return value / 10 * 16 + value % 10;
+}
+
+static int from_bcd(int value)
+{
+    return value / 16 * 10 + value % 16;
+}
+
+static int day_of_week(int y, int m, int d)    /* 0-6 ==> Sun-Sat */
+{       
+    static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; 
+    y -= m < 3;
+    return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
+}       
+
+/*
+ * Note: the TOD should store the current GMT
+ */
+
+int m48_tod_set(int year,              /* 1980-2079 */
+               int month,              /* 01-12 */
+               int day,                /* 01-31 */
+               int hour,               /* 00-23 */
+               int minute,             /* 00-59 */
+               int second)             /* 00-59 */
+  
+{
+    SYS_TOD_UNPROTECT();
+
+    M48_ADDR[CONTROL] |= 0x80; /* Set WRITE bit */
+
+    M48_ADDR[YEAR] = to_bcd(year % 100);
+    M48_ADDR[MONTH] = to_bcd(month);
+    M48_ADDR[DAY] = to_bcd(day);
+    M48_ADDR[DAY_OF_WEEK] = day_of_week(year, month, day) + 1;
+    M48_ADDR[HOUR] = to_bcd(hour);
+    M48_ADDR[MINUTE] = to_bcd(minute);
+    M48_ADDR[SECOND] = to_bcd(second);
+
+    M48_ADDR[CONTROL] &= ~0x80;        /* Clear WRITE bit */
+
+    SYS_TOD_PROTECT();
+
+    return 0;
+}
+
+/*
+ * Note: the TOD should store the current GMT
+ */
+
+int m48_tod_get(int *year,             /* 1980-2079 */
+               int *month,             /* 01-12 */
+               int *day,               /* 01-31 */
+               int *hour,              /* 00-23 */
+               int *minute,            /* 00-59 */
+               int *second)            /* 00-59 */
+{
+    int y;
+
+    SYS_TOD_UNPROTECT();
+
+    M48_ADDR[CONTROL] |= 0x40; /* Set READ bit */
+
+    y = from_bcd(M48_ADDR[YEAR]);
+    *year = y < 80 ? 2000 + y : 1900 + y;
+    *month = from_bcd(M48_ADDR[MONTH]);
+    *day = from_bcd(M48_ADDR[DAY]);
+    /* day_of_week = M48_ADDR[DAY_OF_WEEK] & 0xf; */
+    *hour = from_bcd(M48_ADDR[HOUR]);
+    *minute = from_bcd(M48_ADDR[MINUTE]);
+    *second = from_bcd(M48_ADDR[SECOND] & 0x7f);
+
+    M48_ADDR[CONTROL] &= ~0x40;        /* Clear READ bit */
+
+    SYS_TOD_PROTECT();
+
+    return 0;
+}
+
+int m48_tod_get_second(void)
+{
+    return from_bcd(M48_ADDR[SECOND] & 0x7f);
+}
+
+/*
+ * Watchdog function
+ *
+ *  If usec is 0, the watchdog timer is disarmed.
+ *
+ *  If usec is non-zero, the watchdog timer is armed (or re-armed) for
+ *    approximately usec microseconds (if the exact requested usec is
+ *    not supported by the chip, the next higher available value is used).
+ *
+ *  Minimum watchdog timeout = 62500 usec
+ *  Maximum watchdog timeout = 124 sec (124000000 usec)
+ */
+
+void m48_watchdog_arm(int usec)
+{
+    int                mpy, res;
+
+    SYS_TOD_UNPROTECT();
+
+    if (usec == 0) {
+       res = 0;
+       mpy = 0;
+    } else if (usec < 2000000) {       /* Resolution: 1/16s if below 2s */
+       res = 0;
+       mpy = (usec + 62499) / 62500;
+    } else if (usec < 8000000) {       /* Resolution: 1/4s if below 8s */
+       res = 1;
+       mpy = (usec + 249999) / 250000;
+    } else if (usec < 32000000) {      /* Resolution: 1s if below 32s */
+       res = 2;
+       mpy = (usec + 999999) / 1000000;
+    } else {                           /* Resolution: 4s up to 124s */
+       res = 3;
+       mpy = (usec + 3999999) / 4000000;
+       if (mpy > 31)
+           mpy = 31;
+    }
+
+    M48_ADDR[WATCH] = (0x80 |          /* Steer to RST signal (IRQ = N/C) */
+                      mpy << 2 |
+                      res);
+
+    SYS_TOD_PROTECT();
+}
+
+/*
+ * PPCBoot RTC support.
+ */
+void
+rtc_get( struct rtc_time *tmp )
+{
+       m48_tod_get(&tmp->tm_year,
+                   &tmp->tm_mon,
+                   &tmp->tm_mday,
+                   &tmp->tm_hour,
+                   &tmp->tm_min,
+                   &tmp->tm_sec);
+       tmp->tm_yday = 0;
+       tmp->tm_isdst= 0;
+
+#ifdef RTC_DEBUG
+       printf( "Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
+               tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+               tmp->tm_hour, tmp->tm_min, tmp->tm_sec );
+#endif
+}
+
+void
+rtc_set( struct rtc_time *tmp )
+{
+       m48_tod_set(tmp->tm_year,               /* 1980-2079 */
+                   tmp->tm_mon,                /* 01-12 */
+                   tmp->tm_mday,              /* 01-31 */
+                   tmp->tm_hour,               /* 00-23 */
+                   tmp->tm_min,                /* 00-59 */
+                   tmp->tm_sec);               /* 00-59 */
+
+#ifdef RTC_DEBUG
+       printf( "Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
+               tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+               tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+#endif
+
+}
+
+void
+rtc_reset (void)
+{
+  m48_tod_init();
+}
+
diff --git a/board/bmw/m48t59y.h b/board/bmw/m48t59y.h
new file mode 100644 (file)
index 0000000..717300d
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * SGS M48-T59Y TOD/NVRAM Driver
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 1999, by Curt McDowell, 08-06-99, Broadcom Corp.
+ *
+ * (C) Copyright 2001, James Dougherty, 07/18/01, Broadcom Corp.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __M48_T59_Y_H
+#define __M48_T59_Y_H
+
+/*
+ * M48 T59Y -Timekeeping Battery backed SRAM.
+ */
+
+int m48_tod_init(void);
+
+int m48_tod_set(int year,
+               int month,
+               int day,
+               int hour,
+               int minute,
+               int second);
+
+int m48_tod_get(int *year,
+               int *month,
+               int *day,
+               int *hour,
+               int *minute,
+               int *second);
+
+int m48_tod_get_second(void);
+
+void m48_watchdog_arm(int usec);
+
+#endif /*!__M48_T59_Y_H */
diff --git a/board/bmw/ns16550.c b/board/bmw/ns16550.c
new file mode 100644 (file)
index 0000000..b6b6f4c
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * COM1 NS16550 support
+ * originally from linux source (arch/ppc/boot/ns16550.c)
+ * modified to use CFG_ISA_MEM and new defines
+ */
+
+#include <config.h>
+#include "ns16550.h"
+
+typedef struct NS16550 *NS16550_t;
+
+const NS16550_t COM_PORTS[] = { (NS16550_t) ((CFG_EUMB_ADDR) + 0x4500), (NS16550_t) ((CFG_EUMB_ADDR) + 0x4600)};
+
+volatile struct NS16550 *
+NS16550_init(int chan, int baud_divisor)
+{
+ volatile struct NS16550 *com_port;
+ com_port = (struct NS16550 *) COM_PORTS[chan];
+ com_port->ier = 0x00;
+ com_port->lcr = LCR_BKSE;              /* Access baud rate */
+ com_port->dll = baud_divisor & 0xff;   /* 9600 baud */
+ com_port->dlm = (baud_divisor >> 8) & 0xff;
+ com_port->lcr = LCR_8N1;               /* 8 data, 1 stop, no parity */
+ com_port->mcr = MCR_RTS;     /* RTS/DTR */
+ com_port->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR;                  /* Clear & enable FIFOs */
+return (com_port);
+}
+
+void
+NS16550_reinit(volatile struct NS16550 *com_port, int baud_divisor)
+{
+ com_port->ier = 0x00;
+ com_port->lcr = LCR_BKSE;              /* Access baud rate */
+ com_port->dll = baud_divisor & 0xff;   /* 9600 baud */
+ com_port->dlm = (baud_divisor >> 8) & 0xff;
+ com_port->lcr = LCR_8N1;               /* 8 data, 1 stop, no parity */
+ com_port->mcr = MCR_RTS;     /* RTS/DTR */
+ com_port->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR;                  /* Clear & enable FIFOs */
+}
+
+void NS16550_putc(volatile struct NS16550 *com_port, unsigned char c)
+{
+ while ((com_port->lsr & LSR_THRE) == 0) ;
+ com_port->thr = c;
+}
+
+unsigned char
+NS16550_getc(volatile struct NS16550 *com_port)
+{
+ while ((com_port->lsr & LSR_DR) == 0) ;
+ return (com_port->rbr);
+}
+
+int NS16550_tstc(volatile struct NS16550 *com_port)
+{
+ return ((com_port->lsr & LSR_DR) != 0);
+}
+
+
+
diff --git a/board/bmw/ns16550.h b/board/bmw/ns16550.h
new file mode 100644 (file)
index 0000000..b80ac02
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * NS16550 Serial Port
+ * originally from linux source (arch/ppc/boot/ns16550.h)
+ * modified slightly to
+ * have addresses as offsets from CFG_ISA_BASE
+ * added a few more definitions
+ * added prototypes for ns16550.c
+ * reduced no of com ports to 2
+ * modifications (c) Rob Taylor, Flying Pig Systems. 2000.
+ * further modified to support the 8245 duart
+ * modifications (c) Paul Jimenez, Musenki, Inc. 2001.
+ */
+
+
+struct NS16550
+ {
+  unsigned char rbrthrdlb;  /* 0 */
+  unsigned char ierdmb;     /* 1 */
+  unsigned char iirfcrafr;  /* 2 */
+  unsigned char lcr;         /* 3 */
+  unsigned char mcr;         /* 4 */
+  unsigned char lsr;         /* 5 */
+  unsigned char msr;         /* 6 */
+  unsigned char scr;         /* 7 */
+  unsigned char reserved[2]; /* 8 & 9 */
+  unsigned char dsr;         /* 10 */
+  unsigned char dcr;         /* 11 */
+ };
+
+
+#define rbr rbrthrdlb
+#define thr rbrthrdlb
+#define dll rbrthrdlb
+#define ier ierdmb
+#define dlm ierdmb
+#define iir iirfcrafr
+#define fcr iirfcrafr
+#define afr iirfcrafr
+
+#define FCR_FIFO_EN     0x01    /*fifo enable*/
+#define FCR_RXSR        0x02    /*reciever soft reset*/
+#define FCR_TXSR        0x04    /*transmitter soft reset*/
+#define FCR_DMS                0x08    /* DMA Mode Select */
+
+#define MCR_RTS         0x02    /* Readyu to Send */
+#define MCR_LOOP       0x10    /* Local loopback mode enable */
+/* #define MCR_DTR         0x01    noton 8245 duart */
+/* #define MCR_DMA_EN      0x04    noton 8245 duart */
+/* #define MCR_TX_DFR      0x08    noton 8245 duart */
+
+#define LCR_WLS_MSK 0x03    /* character length slect mask*/
+#define LCR_WLS_5   0x00    /* 5 bit character length */
+#define LCR_WLS_6   0x01    /* 6 bit character length */
+#define LCR_WLS_7   0x02    /* 7 bit character length */
+#define LCR_WLS_8   0x03    /* 8 bit character length */
+#define LCR_STB     0x04    /* Number of stop Bits, off = 1, on = 1.5 or 2) */
+#define LCR_PEN     0x08    /* Parity eneble*/
+#define LCR_EPS     0x10    /* Even Parity Select*/
+#define LCR_STKP    0x20    /* Stick Parity*/
+#define LCR_SBRK    0x40    /* Set Break*/
+#define LCR_BKSE    0x80    /* Bank select enable - aka DLAB on 8245 */
+
+#define LSR_DR      0x01    /* Data ready */
+#define LSR_OE      0x02    /* Overrun */
+#define LSR_PE      0x04    /* Parity error */
+#define LSR_FE      0x08    /* Framing error */
+#define LSR_BI      0x10    /* Break */
+#define LSR_THRE    0x20    /* Xmit holding register empty */
+#define LSR_TEMT    0x40    /* Xmitter empty */
+#define LSR_ERR     0x80    /* Error */
+
+/* useful defaults for LCR*/
+#define LCR_8N1     0x03
+
+
+volatile struct NS16550 * NS16550_init(int chan, int baud_divisor);
+void NS16550_putc(volatile struct NS16550 *com_port, unsigned char c);
+unsigned char NS16550_getc(volatile struct NS16550 *com_port);
+int NS16550_tstc(volatile struct NS16550 *com_port);
+void NS16550_reinit(volatile struct NS16550 *com_port, int baud_divisor);
+
diff --git a/board/bmw/ppcboot.lds b/board/bmw/ppcboot.lds
new file mode 100644 (file)
index 0000000..0e6091c
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)          }
+  .dynsym        : { *(.dynsym)                }
+  .dynstr        : { *(.dynstr)                }
+  .rel.text      : { *(.rel.text)              }
+  .rela.text     : { *(.rela.text)     }
+  .rel.data      : { *(.rel.data)              }
+  .rela.data     : { *(.rela.data)     }
+  .rel.rodata    : { *(.rel.rodata)    }
+  .rela.rodata   : { *(.rela.rodata)   }
+  .rel.got       : { *(.rel.got)               }
+  .rela.got      : { *(.rela.got)              }
+  .rel.ctors     : { *(.rel.ctors)     }
+  .rela.ctors    : { *(.rela.ctors)    }
+  .rel.dtors     : { *(.rel.dtors)     }
+  .rela.dtors    : { *(.rela.dtors)    }
+  .rel.bss       : { *(.rel.bss)               }
+  .rela.bss      : { *(.rela.bss)              }
+  .rel.plt       : { *(.rel.plt)               }
+  .rela.plt      : { *(.rela.plt)              }
+  .init          : { *(.init)  }
+  .plt : { *(.plt) }
+  .text      :
+  {
+    cpu/mpc824x/start.o        (.text)
+    common/board.o     (.text)
+    lib_ppc/ppcstring.o        (.text)
+    lib_generic/vsprintf.o     (.text)
+    lib_generic/crc32.o        (.text)
+    lib_generic/zlib.o (.text)
+
+               . = DEFINED(env_offset) ? env_offset : .;
+    common/environment.o (.text)
+
+               *(.text)
+
+    *(.fixup)
+    *(.got1)
+    . = ALIGN(16);
+    *(.rodata)
+    *(.rodata1)
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x0FFF) & 0xFFFFF000;
+  _erotext = .;
+  PROVIDE (erotext = .);
+  .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  }
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+  __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(4096);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(4096);
+  __init_end = .;
+
+  __bss_start = .;
+  .bss       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  }
+
+  _end = . ;
+  PROVIDE (end = .);
+}
+
diff --git a/board/bmw/serial.c b/board/bmw/serial.c
new file mode 100644 (file)
index 0000000..0428770
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppcboot.h>
+#include "ns16550.h"
+
+#if CONFIG_CONS_INDEX == 1
+static struct NS16550 *console = (struct NS16550 *) (CFG_EUMB_ADDR + 0x4500);
+#elif CONFIG_CONS_INDEX == 2
+static struct NS16550 *console = (struct NS16550 *) (CFG_EUMB_ADDR + 0x4500);
+#else
+#error no valid console defined
+#endif
+
+extern ulong get_bus_freq(ulong);
+
+void
+serial_init (unsigned long dummy, int baudrate)
+{
+    int clock_divisor = get_bus_freq(0) / 16 / baudrate;
+    NS16550_init(CONFIG_CONS_INDEX - 1, clock_divisor);
+}
+
+void
+serial_putc(const char c)
+{
+    if (c == '\n'){
+        serial_putc ('\r');
+    }
+    NS16550_putc(console, c);
+}
+
+void
+serial_puts (const char *s)
+{
+    while (*s) {
+        serial_putc (*s++);
+      }
+}
+
+
+int
+serial_getc(void)
+{
+    return NS16550_getc(console);
+}
+
+int
+serial_tstc(void)
+{
+    return NS16550_tstc(console);
+}
+
+void
+serial_setbrg (unsigned long dummy, int baudrate)
+{
+    int clock_divisor = get_bus_freq(0) / 16 / baudrate;
+    NS16550_reinit(console, clock_divisor);
+}
index 43419f6131f47ad3c54ef387c0f2241a8c697b2a..83d89439a5c32e13e023e61ee05cdb0e89fa653f 100644 (file)
@@ -296,7 +296,8 @@ board_init_f (ulong bootflag)
 #endif /* CONFIG_HW_WATCHDOG */
     WATCHDOG_RESET();
 
-#if defined(CONFIG_COGENT)     || \
+#if defined(CONFIG_BMW)                || \
+    defined(CONFIG_COGENT)     || \
     defined(CONFIG_HYMOD)      || \
     defined(CONFIG_RSD_PROTO)  || \
     defined(CONFIG_W7O)
index 00d2b0caa527ab55f567a9536d0097b728b1d665..3abb6e6e26b0f7b3e4bd544094f5042c47dadd32 100644 (file)
@@ -120,8 +120,8 @@ typedef     struct environment_s {
 #ifdef CFG_NVRAM_ACCESS_ROUTINE
 
 static env_t *env_ptr = NULL;
-void *nvram_read(void *dest, const short src, size_t count);
-void nvram_write(short dest, const void *src, size_t count);
+void *nvram_read(void *dest, const long src, size_t count);
+void nvram_write(long dest, const void *src, size_t count);
 
 #else
 
@@ -328,6 +328,11 @@ void env_relocate (ulong offset)
                eeprom_read (CFG_DEF_EEPROM_ADDR, CFG_ENV_OFFSET+offsetof(env_t,data),
                             env_ptr->data,
                             ENV_SIZE);
+# elif defined(CFG_ENV_IS_IN_NVRAM) && defined(CFG_NVRAM_ACCESS_ROUTINE)
+               DEBUGF ("%s[%d] read ENV from NVRAM\n", __FUNCTION__,__LINE__);
+               nvram_read(env_ptr->data,
+                       CFG_ENV_ADDR + sizeof(long),
+                       ENV_SIZE);
 # elif !defined(CFG_ENV_IS_NOWHERE)
                DEBUGF ("%s[%d] read ENV from NVRAM/FLASH\n",__FUNCTION__,__LINE__);
                memcpy (env_ptr->data,
@@ -851,7 +856,7 @@ int saveenv(void)
        int rcode = 0;
 
 #ifdef CFG_NVRAM_ACCESS_ROUTINE
-       nvram_write((short)CFG_ENV_ADDR, env_ptr, CFG_ENV_SIZE);
+       nvram_write(CFG_ENV_ADDR, env_ptr, CFG_ENV_SIZE);
 #else
        if (memcpy ((char *)CFG_ENV_ADDR, env_ptr, CFG_ENV_SIZE) == NULL)
                    rcode = 1 ;
index 472bf601c6800373f935a9b0c540d1c20c14e007..adf9dd2f370b569d62b547dc73668200e5b22281 100644 (file)
@@ -63,7 +63,7 @@ void
 cpu_init_f (void)
 {
 /* MOUSSE board is initialized in asm */
-#if !defined(CONFIG_MOUSSE)
+#if !defined(CONFIG_MOUSSE) && !defined(CONFIG_BMW)
     register unsigned long val;
     CONFIG_WRITE_HALFWORD(PCICR, 0x06); /* Bus Master, respond to PCI memory space acesses*/
 /*    CONFIG_WRITE_HALFWORD(PCISR, 0xffff); */ /*reset PCISR*/
@@ -287,7 +287,7 @@ cpu_init_f (void)
    CONFIG_WRITE_WORD(MCCR1, val | MCCR1_MEMGO); /* set memory access going */
    __asm__ __volatile__("eieio");
 
-#endif /* CONFIG_MOUSSE */
+#endif /* !CONFIG_MOUSSE && !CONFIG_BMW */
 }
 
 
index f25bc4414d4fdfd00cd53640d0cf0282c3a0ecd0..c5ef38dfe829404c7e31c375b9fcfda537cb633e 100644 (file)
@@ -129,7 +129,9 @@ boot_warm:
 
 
 in_flash:
-
+#if defined(CONFIG_BMW)
+       bl early_init_f /* Must be ASM: no stack yet! */
+#endif 
        /*
         * Setup BATs - cannot be done in C since we don't have a stack yet
         */
@@ -140,7 +142,7 @@ in_flash:
        mfmsr   r3
        ori     r3, r3, (MSR_IR | MSR_DR)
        mtmsr   r3
-
+#if !defined(CONFIG_BMW)
        /* Enable and invalidate data cache.
         */
        mfspr   r3, HID0
@@ -172,7 +174,7 @@ in_flash:
        ori     r3, r3, 0x0080
        sync
        mtspr   1011, r3
-
+#endif /* !CONFIG_BMW */
        /*
         * Thisk the stack pointer *somewhere* sensible. Doesnt
         * matter much where as we'll move it when we relocate
diff --git a/drivers/5701rls.c b/drivers/5701rls.c
new file mode 100644 (file)
index 0000000..0f2c1a5
--- /dev/null
@@ -0,0 +1,46 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/*                                                                            */
+/******************************************************************************/
+
+#if INCLUDE_5701_AX_FIX
+
+#include "bcm570x_mm.h"
+#include "5701rls.h"
+
+LM_STATUS LM_LoadRlsFirmware(PLM_DEVICE_BLOCK pDevice)
+{
+  T3_FWIMG_INFO FwImgInfo;
+
+  FwImgInfo.StartAddress = t3FwStartAddr;
+  FwImgInfo.Text.Buffer = (PLM_UINT8)t3FwText;
+  FwImgInfo.Text.Offset  = t3FwTextAddr;
+  FwImgInfo.Text.Length  = t3FwTextLen;
+  FwImgInfo.ROnlyData.Buffer = (PLM_UINT8)t3FwRodata;
+  FwImgInfo.ROnlyData.Offset  = t3FwRodataAddr;
+  FwImgInfo.ROnlyData.Length  = t3FwRodataLen;
+  FwImgInfo.Data.Buffer = (PLM_UINT8)t3FwData;
+  FwImgInfo.Data.Offset  = t3FwDataAddr;
+  FwImgInfo.Data.Length  = t3FwDataLen;
+
+  if (LM_LoadFirmware(pDevice,
+                      &FwImgInfo,
+                      T3_RX_CPU_ID | T3_TX_CPU_ID,
+                      T3_RX_CPU_ID) != LM_STATUS_SUCCESS)
+    {
+      return LM_STATUS_FAILURE;
+    }
+  
+  return LM_STATUS_SUCCESS;
+}
+
+#endif /* INCLUDE_5701_AX_FIX */
diff --git a/drivers/5701rls.h b/drivers/5701rls.h
new file mode 100644 (file)
index 0000000..772974e
--- /dev/null
@@ -0,0 +1,198 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/******************************************************************************/
+
+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 };
index 7b724953d67d98e0d4d9e988851ded83e94a93b8..fff3b1917b5dcf90a70f6f006a86979c23ab9a35 100644 (file)
@@ -28,7 +28,8 @@ include $(TOPDIR)/config.mk
 LIB    = libdrivers.a
 
 OBJS   = ns87308.o ns16550.o serial.o pci_auto.o pci.o pci_indirect.o \
-               eepro100.o dc2114x.o w83c553f.o sym53c8xx.o pcnet.o
+               eepro100.o dc2114x.o w83c553f.o sym53c8xx.o pcnet.o \
+               tigon3.o bcm570x.o bcm570x_autoneg.o 5701rls.o
 all:   $(LIB)
 
 $(LIB):        $(OBJS)
diff --git a/drivers/bcm570x.c b/drivers/bcm570x.c
new file mode 100644 (file)
index 0000000..2de2810
--- /dev/null
@@ -0,0 +1,1709 @@
+/*
+ * Broadcom BCM570x Ethernet Driver for PPCBoot.
+ * Support 5701, 5702, 5703, and 5704. Single instance driver.
+ * Copyright (C) 2002 James F. Dougherty (jfd@broadcom.com)
+ */
+
+#include <ppcboot.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_NET) && (!defined(CONFIG_NET_MULTI)) && \
+       defined(CONFIG_BCM570x)
+
+#ifdef CONFIG_BMW
+#include <mpc824x.h>
+#endif
+#include <net.h>
+#include "bcm570x_mm.h"
+#include "bcm570x_autoneg.h"
+#include <pci.h>
+#include <malloc.h>
+
+
+
+/*
+ * PCI Registers and definitions.
+ */
+#define PCI_CMD_MASK   0xffff0000      /* mask to save status bits */
+#define PCI_ANY_ID (~0)
+
+/*
+ * PCI memory base for Ethernet device as well as device Interrupt.
+ */
+#define BCM570X_MBAR   0x80100000
+#define BCM570X_ILINE   1
+
+
+
+#define SECOND_USEC    1000000
+#define MAX_PACKET_SIZE 1600
+#define MAX_UNITS       4
+
+/* Globals to this module */
+int initialized = 0;
+unsigned int ioBase = 0;
+volatile PLM_DEVICE_BLOCK    pDevice = NULL;        /* 570x softc */
+volatile PUM_DEVICE_BLOCK    pUmDevice = NULL;
+
+/* Used to pass the full-duplex flag, etc. */
+int line_speed[MAX_UNITS] = {0,0,0,0};
+static int full_duplex[MAX_UNITS] = {1,1,1,1};
+static int rx_flow_control[MAX_UNITS] = {0,0,0,0};
+static int tx_flow_control[MAX_UNITS] = {0,0,0,0};
+static int auto_flow_control[MAX_UNITS] = {0,0,0,0};
+static int tx_checksum[MAX_UNITS] = {1,1,1,1};
+static int rx_checksum[MAX_UNITS] = {1,1,1,1};
+static int auto_speed[MAX_UNITS] = {1,1,1,1};
+
+#if JUMBO_FRAMES
+/* Jumbo MTU for interfaces. */
+static int mtu[MAX_UNITS] = {0,0,0,0};
+#endif
+
+/* Turn on Wake-on lan for a device unit */
+static int enable_wol[MAX_UNITS] = {0,0,0,0};
+
+#define TX_DESC_CNT DEFAULT_TX_PACKET_DESC_COUNT
+static unsigned int tx_pkt_desc_cnt[MAX_UNITS] =
+       {TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT, TX_DESC_CNT};
+
+#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};
+
+static unsigned int rx_adaptive_coalesce[MAX_UNITS] = {1,1,1,1};
+
+#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};
+#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};
+
+#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};
+
+#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};
+
+#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};
+
+#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};
+
+
+
+/*
+ * Legitimate values for BCM570x device types
+ */
+typedef enum {
+       BCM5700VIGIL = 0,
+       BCM5700A6,
+       BCM5700T6,
+       BCM5700A9,
+       BCM5700T9,
+       BCM5700,
+       BCM5701A5,
+       BCM5701T1,
+       BCM5701T8,
+       BCM5701A7,
+       BCM5701A10,
+       BCM5701A12,
+       BCM5701,
+       BCM5702,
+       BCM5703,
+       BCM5703A31,
+       TC996T,
+       TC996ST,
+       TC996SSX,
+       TC996SX,
+       TC996BT,
+       TC997T,
+       TC997SX,
+       TC1000T,
+       TC940BR01,
+       TC942BR01,
+       NC6770,
+       NC7760,
+       NC7770,
+       NC7780
+} board_t;
+
+/* Chip-Rev names for each device-type */
+static struct {
+    char* name;
+} chip_rev[] = {
+       {"BCM5700VIGIL"},
+       {"BCM5700A6"},
+       {"BCM5700T6"},
+       {"BCM5700A9"},
+       {"BCM5700T9"},
+       {"BCM5700"},
+       {"BCM5701A5"},
+       {"BCM5701T1"},
+       {"BCM5701T8"},
+       {"BCM5701A7"},
+       {"BCM5701A10"},
+       {"BCM5701A12"},
+       {"BCM5701"},
+       {"BCM5702"},
+       {"BCM5703"},
+       {"BCM5703A31"},
+       {"TC996T"},
+       {"TC996ST"},
+       {"TC996SSX"},
+       {"TC996SX"},
+       {"TC996BT"},
+       {"TC997T"},
+       {"TC997SX"},
+       {"TC1000T"},
+       {"TC940BR01"},
+       {"TC942BR01"},
+       {"NC6770"},
+       {"NC7760"},
+       {"NC7770"},
+       {"NC7780"},
+       {0}
+};
+
+
+/* indexed by board_t, above */
+static struct {
+    char *name;
+} board_info[] = {
+       { "Broadcom Vigil B5700 1000Base-T" },
+       { "Broadcom BCM5700 1000Base-T" },
+       { "Broadcom BCM5700 1000Base-SX" },
+       { "Broadcom BCM5700 1000Base-SX" },
+       { "Broadcom BCM5700 1000Base-T" },
+       { "Broadcom BCM5700" },
+       { "Broadcom BCM5701 1000Base-T" },
+       { "Broadcom BCM5701 1000Base-T" },
+       { "Broadcom BCM5701 1000Base-T" },
+       { "Broadcom BCM5701 1000Base-SX" },
+       { "Broadcom BCM5701 1000Base-T" },
+       { "Broadcom BCM5701 1000Base-T" },
+       { "Broadcom BCM5701" },
+       { "Broadcom BCM5702 1000Base-T" },
+       { "Broadcom BCM5703 1000Base-T" },
+       { "Broadcom BCM5703 1000Base-SX" },
+       { "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 3C940 Gigabit LOM (21X21)" },
+       { "3Com 3C942 Gigabit LOM (31X31)" },
+       { "Compaq NC6770 Gigabit Server Adapter" },
+       { "Compaq NC7760 Gigabit Server Adapter" },
+       { "Compaq NC7770 Gigabit Server Adapter" },
+       { "Compaq NC7780 Gigabit Server Adapter" },
+       { 0 },
+};
+
+/* PCI Devices which use the 570x chipset */
+struct pci_device_table {
+    unsigned short vendor_id, device_id; /* Vendor/DeviceID */
+    unsigned short subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
+    unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */
+    unsigned long board_id;        /* Data private to the driver */
+    int io_size, min_latency;
+} bcm570xDevices[] = {
+       {0x14e4, 0x1644, 0x1014, 0x0277, 0, 0, BCM5700VIGIL ,128,32},
+       {0x14e4, 0x1644, 0x14e4, 0x1644, 0, 0, BCM5700A6 ,128,32},
+       {0x14e4, 0x1644, 0x14e4, 0x2, 0, 0, BCM5700T6 ,128,32},
+       {0x14e4, 0x1644, 0x14e4, 0x3, 0, 0, BCM5700A9 ,128,32},
+       {0x14e4, 0x1644, 0x14e4, 0x4, 0, 0, BCM5700T9 ,128,32},
+       {0x14e4, 0x1644, 0x1028, 0xd1, 0, 0, BCM5700 ,128,32},
+       {0x14e4, 0x1644, 0x1028, 0x0106, 0, 0, BCM5700 ,128,32},
+       {0x14e4, 0x1644, 0x1028, 0x0109, 0, 0, BCM5700 ,128,32},
+       {0x14e4, 0x1644, 0x1028, 0x010a, 0, 0, BCM5700 ,128,32},
+       {0x14e4, 0x1644, 0x10b7, 0x1000, 0, 0, TC996T ,128,32},
+       {0x14e4, 0x1644, 0x10b7, 0x1001, 0, 0, TC996ST ,128,32},
+       {0x14e4, 0x1644, 0x10b7, 0x1002, 0, 0, TC996SSX ,128,32},
+       {0x14e4, 0x1644, 0x10b7, 0x1003, 0, 0, TC997T ,128,32},
+       {0x14e4, 0x1644, 0x10b7, 0x1005, 0, 0, TC997SX ,128,32},
+       {0x14e4, 0x1644, 0x10b7, 0x1008, 0, 0, TC942BR01 ,128,32},
+       {0x14e4, 0x1644, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5700 ,128,32},
+       {0x14e4, 0x1645, 0x14e4, 1, 0, 0, BCM5701A5 ,128,32},
+       {0x14e4, 0x1645, 0x14e4, 5, 0, 0, BCM5701T1 ,128,32},
+       {0x14e4, 0x1645, 0x14e4, 6, 0, 0, BCM5701T8 ,128,32},
+       {0x14e4, 0x1645, 0x14e4, 7, 0, 0, BCM5701A7 ,128,32},
+       {0x14e4, 0x1645, 0x14e4, 8, 0, 0, BCM5701A10 ,128,32},
+       {0x14e4, 0x1645, 0x14e4, 0x8008, 0, 0, BCM5701A12 ,128,32},
+       {0x14e4, 0x1645, 0x0e11, 0xc1, 0, 0, NC6770 ,128,32},
+       {0x14e4, 0x1645, 0x0e11, 0x7c, 0, 0, NC7770 ,128,32},
+       {0x14e4, 0x1645, 0x0e11, 0x85, 0, 0, NC7780 ,128,32},
+       {0x14e4, 0x1645, 0x1028, 0x0121, 0, 0, BCM5701 ,128,32},
+       {0x14e4, 0x1645, 0x10b7, 0x1004, 0, 0, TC996SX ,128,32},
+       {0x14e4, 0x1645, 0x10b7, 0x1006, 0, 0, TC996BT ,128,32},
+       {0x14e4, 0x1645, 0x10b7, 0x1007, 0, 0, TC1000T ,128,32},
+       {0x14e4, 0x1645, 0x10b7, 0x1008, 0, 0, TC940BR01 ,128,32},
+       {0x14e4, 0x1645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5701 ,128,32},
+       {0x14e4, 0x1646, 0x14e4, 0x8009, 0, 0, BCM5702 ,128,32},
+       {0x14e4, 0x1646, 0x0e11, 0xbb, 0, 0, NC7760 ,128,32},
+       {0x14e4, 0x1646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 ,128,32},
+       {0x14e4, 0x16a6, 0x14e4, 0x8009, 0, 0, BCM5702 ,128,32},
+       {0x14e4, 0x16a6, 0x0e11, 0xbb, 0, 0, NC7760 ,128,32},
+       {0x14e4, 0x16a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 ,128,32},
+       {0x14e4, 0x1647, 0x14e4, 0x0009, 0, 0, BCM5703 ,128,32},
+       {0x14e4, 0x1647, 0x14e4, 0x000a, 0, 0, BCM5703A31 ,128,32},
+       {0x14e4, 0x1647, 0x14e4, 0x000b, 0, 0, BCM5703 ,128,32},
+       {0x14e4, 0x1647, 0x14e4, 0x800a, 0, 0, BCM5703 ,128,32},
+       {0x14e4, 0x1647, 0x0e11, 0x9a, 0, 0, NC7770 ,128,32},
+       {0x14e4, 0x1647, 0x0e11, 0x99, 0, 0, NC7780 ,128,32},
+       {0x14e4, 0x1647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 ,128,32},
+       {0x14e4, 0x16a7, 0x14e4, 0x0009, 0, 0, BCM5703 ,128,32},
+       {0x14e4, 0x16a7, 0x14e4, 0x000a, 0, 0, BCM5703A31 ,128,32},
+       {0x14e4, 0x16a7, 0x14e4, 0x000b, 0, 0, BCM5703 ,128,32},
+       {0x14e4, 0x16a7, 0x14e4, 0x800a, 0, 0, BCM5703 ,128,32},
+       {0x14e4, 0x16a7, 0x0e11, 0x9a, 0, 0, NC7770 ,128,32},
+       {0x14e4, 0x16a7, 0x0e11, 0x99, 0, 0, NC7780 ,128,32},
+       {0x14e4, 0x16a7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 ,128,32}
+};
+
+#define n570xDevices   (sizeof(bcm570xDevices)/sizeof(bcm570xDevices[0]))
+
+
+
+/*
+ * Allocate a packet buffer from the bcm570x packet pool.
+ */
+void *
+bcm570xPktAlloc(int u, int pksize)
+{
+    return malloc(pksize);
+}
+
+/*
+ * Free a packet previously allocated from the bcm570x packet
+ * buffer pool.
+ */
+void
+bcm570xPktFree(int u, void *p)
+{
+    free(p);
+}
+
+int
+bcm570xReplenishRxBuffers(PUM_DEVICE_BLOCK pUmDevice)
+{
+    PLM_PACKET pPacket;
+    PUM_PACKET pUmPacket;
+    void *skb;
+    int queue_rx = 0;
+    int ret = 0;
+
+    while ((pUmPacket = (PUM_PACKET)
+           QQ_PopHead(&pUmDevice->rx_out_of_buf_q.Container)) != 0) {
+
+       pPacket = (PLM_PACKET) pUmPacket;
+
+       /* reuse an old skb */
+       if (pUmPacket->skbuff) {
+           QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+           queue_rx = 1;
+           continue;
+       }
+       if ( ( skb = bcm570xPktAlloc(pUmDevice->index,
+                                    pPacket->u.Rx.RxBufferSize + 2)) == 0) {
+           QQ_PushHead(&pUmDevice->rx_out_of_buf_q.Container,pPacket);
+           printf("NOTICE: Out of RX memory.\n");
+           ret = 1;
+           break;
+       }
+
+       pUmPacket->skbuff = skb;
+       QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+       queue_rx = 1;
+    }
+
+    if (queue_rx) {
+       LM_QueueRxPackets(pDevice);
+    }
+
+    return ret;
+}
+
+/*
+ * Probe, Map, and Init 570x device.
+ */
+int eth_init(bd_t *bis)
+{
+    int i, rv, devFound = FALSE;
+    pci_dev_t  devbusfn;
+    unsigned short status;
+
+    /* Find PCI device, if it exists, configure ...  */
+    for( i = 0; i < n570xDevices; i++){
+       devbusfn = pci_find_device(bcm570xDevices[i].vendor_id,
+                                  bcm570xDevices[i].device_id, 0);
+       if(devbusfn == -1) {
+           continue; /* No device of that vendor/device ID */
+       } else {
+
+           /* Set ILINE */
+           pci_write_config_byte(devbusfn,
+                                 PCI_INTERRUPT_LINE, BCM570X_ILINE);
+
+           /*
+            * 0x10 - 0x14 define one 64-bit MBAR.
+            * 0x14 is the higher-order address bits of the BAR.
+            */
+           pci_write_config_dword(devbusfn,
+                                  PCI_BASE_ADDRESS_1, 0);
+
+           ioBase = BCM570X_MBAR;
+
+           pci_write_config_dword(devbusfn,
+                                  PCI_BASE_ADDRESS_0, ioBase);
+
+           /*
+            * Enable PCI memory, IO, and Master -- don't
+            * reset any status bits in doing so.
+            */
+           pci_read_config_word(devbusfn,
+                                PCI_COMMAND, &status);
+
+           status |= PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER;
+
+           pci_write_config_word(devbusfn,
+                                 PCI_COMMAND, status);
+
+           printf("\n%s: bus %d, device %d, function %d: MBAR=0x%x\n",
+                  board_info[bcm570xDevices[i].board_id].name,
+                  PCI_BUS(devbusfn),
+                  PCI_DEV(devbusfn),
+                  PCI_FUNC(devbusfn),
+                  ioBase);
+
+           /* Allocate once, but always clear on init */
+           if (!pDevice) {
+               pDevice = malloc(sizeof(UM_DEVICE_BLOCK));
+               pUmDevice = (PUM_DEVICE_BLOCK)pDevice;
+               memset(pDevice, 0x0, sizeof(UM_DEVICE_BLOCK));
+           }
+
+           /* Configure pci dev structure */
+           pUmDevice->pdev = devbusfn;
+           pUmDevice->index = 0;
+           pUmDevice->tx_pkt = 0;
+           pUmDevice->rx_pkt = 0;
+           devFound = TRUE;
+           break;
+       }
+    }
+
+    if(!devFound){
+       printf("eth_init: FAILURE: no BCM570x Ethernet devices found.\n");
+       return -1;
+    }
+
+    /* Setup defaults for chip */
+    pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
+
+    if (pDevice->ChipRevId == T3_CHIP_ID_5700_B0) {
+       pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
+    } else {
+
+       if (rx_checksum[i]) {
+           pDevice->TaskToOffload |=
+               LM_TASK_OFFLOAD_RX_TCP_CHECKSUM |
+               LM_TASK_OFFLOAD_RX_UDP_CHECKSUM;
+       }
+
+       if (tx_checksum[i]) {
+           pDevice->TaskToOffload |=
+               LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
+               LM_TASK_OFFLOAD_TX_UDP_CHECKSUM;
+           pDevice->NoTxPseudoHdrChksum = TRUE;
+       }
+    }
+
+    /* Set Device PCI Memory base address */
+    pDevice->pMappedMemBase = (PLM_UINT8) ioBase;
+
+    /* Pull down adapter info */
+    if ((rv = LM_GetAdapterInfo(pDevice)) != LM_STATUS_SUCCESS) {
+       printf("bcm570xEnd: LM_GetAdapterInfo failed: rv=%d!\n", rv );
+       return -2;
+    }
+
+    /* Lock not needed */
+    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;
+    }
+
+    /* Setup timer delays */
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) {
+       pDevice->UseTaggedStatus = TRUE;
+       pUmDevice->timer_interval = CFG_HZ;
+    }
+    else {
+       pUmDevice->timer_interval = CFG_HZ / 50;
+    }
+
+    /* Grab name .... */
+    pUmDevice->name =
+       (char*)malloc(strlen(board_info[bcm570xDevices[i].board_id].name)+1);
+    strcpy(pUmDevice->name,board_info[bcm570xDevices[i].board_id].name);
+
+    memcpy(pDevice->NodeAddress, bis->bi_enetaddr, 6);
+    LM_SetMacAddress(pDevice, bis->bi_enetaddr);
+    /* Init queues  .. */
+    QQ_InitQueue(&pUmDevice->rx_out_of_buf_q.Container,
+                MAX_RX_PACKET_DESC_COUNT);
+    pUmDevice->rx_last_cnt = pUmDevice->tx_last_cnt = 0;
+
+    /* delay for 4 seconds */
+    pUmDevice->delayed_link_ind =
+       (4 * CFG_HZ) / pUmDevice->timer_interval;
+
+    pUmDevice->adaptive_expiry =
+       CFG_HZ / pUmDevice->timer_interval;
+
+    /* Sometimes we get spurious ints. after reset when link is down. */
+    /* This field tells the isr to service the int. even if there is */
+    /* no status block update. */
+    pUmDevice->adapter_just_inited =
+       (3 * CFG_HZ) / pUmDevice->timer_interval;
+
+    /* Initialize 570x */
+    if (LM_InitializeAdapter(pDevice) != LM_STATUS_SUCCESS) {
+       printf("ERROR: Adapter initialization failed.\n");
+       return ERROR;
+    }
+
+    /* Enable chip ISR */
+    LM_EnableInterrupt(pDevice);
+
+    /* Clear MC table */
+    LM_MulticastClear(pDevice);
+
+    /* Enable Multicast */
+    LM_SetReceiveMask(pDevice,
+                     pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST);
+
+    pUmDevice->opened = 1;
+    pUmDevice->tx_full = 0;
+    pUmDevice->tx_pkt = 0;
+    pUmDevice->rx_pkt = 0;
+    printf("eth%d: %s @0x%lx,",
+          pDevice->index, pUmDevice->name, (unsigned long)ioBase);
+    printf(    "node addr ");
+    for (i = 0; i < 6; i++) {
+       printf("%2.2x", pDevice->NodeAddress[i]);
+    }
+    printf("\n");
+
+    printf("eth%d: ", pDevice->index);
+    printf("%s with ",
+          chip_rev[bcm570xDevices[i].board_id].name);
+
+    if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5400_PHY_ID)
+       printf("Broadcom BCM5400 Copper ");
+    else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
+       printf("Broadcom BCM5401 Copper ");
+    else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5411_PHY_ID)
+       printf("Broadcom BCM5411 Copper ");
+    else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5701_PHY_ID)
+       printf("Broadcom BCM5701 Integrated Copper ");
+    else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5703_PHY_ID)
+        printf("Broadcom BCM5703 Integrated Copper ");
+    else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM8002_PHY_ID)
+       printf("Broadcom BCM8002 SerDes ");
+    else if (pDevice->EnableTbi)
+       printf("Agilent HDMP-1636 SerDes ");
+    else
+       printf("Unknown ");
+    printf("transceiver found\n");
+
+    printf("eth%d: %s, MTU: %d,",
+          pDevice->index, pDevice->BusSpeedStr, 1500);
+
+    if ((pDevice->ChipRevId != T3_CHIP_ID_5700_B0) &&
+       rx_checksum[i])
+       printf("Rx Checksum ON\n");
+    else
+       printf("Rx Checksum OFF\n");
+    initialized++;
+
+    return 0;
+}
+
+/* Ethernet Interrupt service routine */
+void
+eth_isr(void)
+{
+    LM_UINT32 oldtag, newtag;
+    int i;
+
+    pUmDevice->interrupt = 1;
+
+    if (pDevice->UseTaggedStatus) {
+       if ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) ||
+           pUmDevice->adapter_just_inited) {
+            MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1);
+            oldtag = pDevice->pStatusBlkVirt->StatusTag;
+
+            for (i = 0; ; i++) {
+                pDevice->pStatusBlkVirt->Status &= ~STATUS_BLOCK_UPDATED;
+                LM_ServiceInterrupts(pDevice);
+                newtag = pDevice->pStatusBlkVirt->StatusTag;
+                if ((newtag == oldtag) || (i > 50)) {
+                    MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, newtag << 24);
+                    if (pDevice->UndiFix) {
+                        REG_WR(pDevice, Grc.LocalCtrl,
+                              pDevice->GrcLocalCtrl | 0x2);
+                    }
+                    break;
+                 }
+               oldtag = newtag;
+           }
+       }
+    }
+    else {
+       while (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) {
+           unsigned int dummy;
+
+           pDevice->pMemView->Mailbox.Interrupt[0].Low = 1;
+           pDevice->pStatusBlkVirt->Status &= ~STATUS_BLOCK_UPDATED;
+           LM_ServiceInterrupts(pDevice);
+           pDevice->pMemView->Mailbox.Interrupt[0].Low = 0;
+           dummy = pDevice->pMemView->Mailbox.Interrupt[0].Low;
+       }
+    }
+
+    /* Allocate new RX buffers */
+    if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) {
+       bcm570xReplenishRxBuffers(pUmDevice);
+    }
+
+    /* Queue packets */
+    if (QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container)) {
+       LM_QueueRxPackets(pDevice);
+    }
+
+    if (pUmDevice->tx_queued) {
+       pUmDevice->tx_queued = 0;
+    }
+
+    if(pUmDevice->tx_full){
+       if(pDevice->LinkStatus != LM_STATUS_LINK_DOWN){
+           printf("NOTICE: tx was previously blocked, restarting MUX\n");
+           pUmDevice->tx_full = 0;
+       }
+    }
+
+    pUmDevice->interrupt = 0;
+
+}
+
+int
+eth_send(volatile void *packet, int length)
+{
+    int status = 0;
+#if ET_DEBUG
+    unsigned char* ptr = (unsigned char*)packet;
+#endif
+    PLM_PACKET pPacket;
+    PUM_PACKET pUmPacket;
+
+    /* Link down, return */
+    while(pDevice->LinkStatus == LM_STATUS_LINK_DOWN) {
+#if 0
+        printf("eth%d: link down - check cable or link partner.\n",
+               pUmDevice->index);
+#endif
+       eth_isr();
+
+       /* Wait to see link for one-half a second before sending ... */
+       udelay(1500000);
+
+    }
+
+    /* Clear sent flag */
+    pUmDevice->tx_pkt = 0;
+
+    /* Previously blocked */
+    if(pUmDevice->tx_full){
+       printf("eth%d: tx blocked.\n", pUmDevice->index);
+       return 0;
+    }
+
+    pPacket = (PLM_PACKET)
+       QQ_PopHead(&pDevice->TxPacketFreeQ.Container);
+
+    if (pPacket == 0) {
+       pUmDevice->tx_full = 1;
+       printf("bcm570xEndSend: TX full!\n");
+       return 0;
+    }
+
+    if (pDevice->SendBdLeft.counter == 0) {
+       pUmDevice->tx_full = 1;
+       printf("bcm570xEndSend: no more TX descriptors!\n");
+       QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket);
+       return 0;
+    }
+
+    if (length <= 0){
+       printf("eth: bad packet size: %d\n", length);
+       goto out;
+    }
+
+    /* Get packet buffers and fragment list */
+    pUmPacket = (PUM_PACKET) pPacket;
+    /* Single DMA Descriptor transmit.
+     * Fragments may be provided, but one DMA descriptor max is
+     * used to send the packet.
+     */
+    if (MM_CoalesceTxBuffer (pDevice, pPacket) != LM_STATUS_SUCCESS) {
+        if (pUmPacket->skbuff == NULL){
+           /* Packet was discarded */
+           printf("TX: failed (1)\n");
+           status = 1;
+       } else{
+           printf("TX: failed (2)\n");
+           status = 2;
+       }
+        QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket);
+        return status;
+    }
+
+    /* Copy packet to DMA buffer */
+    memset(pUmPacket->skbuff, 0x0, MAX_PACKET_SIZE);
+    memcpy((void*)pUmPacket->skbuff, (void*)packet, length);
+    pPacket->PacketSize = length;
+    pPacket->Flags |= SND_BD_FLAG_END|SND_BD_FLAG_COAL_NOW;
+    pPacket->u.Tx.FragCount = 1;
+    /* We've already provided a frame ready for transmission */
+    pPacket->Flags &= ~SND_BD_FLAG_TCP_UDP_CKSUM;
+
+    if ( LM_SendPacket(pDevice, pPacket) == LM_STATUS_FAILURE){
+        /*
+         *  A lower level send failure will push the packet descriptor back
+         *  in the free queue, so just deal with the VxWorks clusters.
+         */
+        if (pUmPacket->skbuff == NULL){
+           printf("TX failed (1)!\n");
+           /* Packet was discarded */
+           status = 3;
+       } else {
+           /* A resource problem ... */
+           printf("TX failed (2)!\n");
+           status = 4;
+       }
+
+       if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) == 0) {
+           printf("TX: emptyQ!\n");
+           pUmDevice->tx_full = 1;
+       }
+    }
+
+    while(pUmDevice->tx_pkt == 0){
+       /* Service TX */
+       eth_isr();
+    }
+#if ET_DEBUG
+    printf("eth_send: 0x%x, %d bytes\n"
+          "[%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x] ...\n",
+          (int)pPacket, length,
+          ptr[0],ptr[1],ptr[2],ptr[3],ptr[4],ptr[5],
+          ptr[6],ptr[7],ptr[8],ptr[9],ptr[10],ptr[11],ptr[12],
+          ptr[13],ptr[14],ptr[15]);
+#endif
+    pUmDevice->tx_pkt = 0;
+    QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket);
+
+    /* Done with send */
+ out:
+    return status;
+}
+
+
+/* Ethernet receive */
+int
+eth_rx(void)
+{
+    PLM_PACKET          pPacket = NULL;
+    PUM_PACKET          pUmPacket = NULL;
+    void *skb;
+    int size=0;
+
+    while(TRUE) {
+
+    bcm570x_service_isr:
+       /* Pull down packet if it is there */
+       eth_isr();
+
+       /* Indicate RX packets called */
+       if(pUmDevice->rx_pkt){
+           /* printf("eth_rx: got a packet...\n"); */
+           pUmDevice->rx_pkt = 0;
+       } else {
+           /* printf("eth_rx: waiting for packet...\n"); */
+           goto bcm570x_service_isr;
+       }
+
+       pPacket = (PLM_PACKET)
+           QQ_PopHead(&pDevice->RxPacketReceivedQ.Container);
+
+       if (pPacket == 0){
+           printf("eth_rx: empty packet!\n");
+           goto bcm570x_service_isr;
+       }
+
+       pUmPacket = (PUM_PACKET) pPacket;
+#if ET_DEBUG
+       printf("eth_rx: packet @0x%x\n",
+              (int)pPacket);
+#endif
+       /* If the packet generated an error, reuse buffer */
+       if ((pPacket->PacketStatus != LM_STATUS_SUCCESS) ||
+           ((size = pPacket->PacketSize) > pDevice->RxMtu)) {
+
+           /* reuse skb */
+           QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+           printf("eth_rx: error in packet dma!\n");
+           goto bcm570x_service_isr;
+       }
+
+       /* Set size and address */
+       skb = pUmPacket->skbuff;
+       size = pPacket->PacketSize;
+
+       /* Pass the packet up to the protocol
+        * layers.
+        */
+       NetReceive(skb, size);
+
+       /* Free packet buffer */
+       bcm570xPktFree (pUmDevice->index, skb);
+       pUmPacket->skbuff = NULL;
+
+       /* Reuse SKB */
+       QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+       return 0; /* Got a packet, bail ... */
+    }
+    return size;
+}
+
+
+
+/* Shut down device */
+void
+eth_halt(void)
+{
+    int i;
+    if ( initialized)
+    if (pDevice && pUmDevice && pUmDevice->opened){
+       printf("\neth%d:%s,", pUmDevice->index, pUmDevice->name);
+       printf("HALT,");
+        /* stop device */
+        LM_Halt(pDevice);
+       printf("POWER DOWN,");
+        LM_SetPowerState(pDevice, LM_POWER_STATE_D3);
+
+        /* Free the memory allocated by the device in tigon3 */
+        for (i = 0; i < pUmDevice->mem_list_num; i++)  {
+            if (pUmDevice->mem_list[i])  {
+               /* sanity check */
+                if (pUmDevice->dma_list[i]) {  /* cache-safe memory */
+                    free(pUmDevice->mem_list[i]);
+               } else {
+                    free(pUmDevice->mem_list[i]);  /* normal memory   */
+               }
+           }
+       }
+       pUmDevice->opened = 0;
+       free(pDevice);
+       pDevice = NULL;
+       pUmDevice = NULL;
+       initialized = 0;
+       printf("done - offline.\n");
+    }
+}
+
+
+
+
+/*
+ *
+ * Middle Module: Interface between the HW driver (tigon3 modules) and
+ * the native (SENS) driver.  These routines implement the system
+ * interface for tigon3 on VxWorks.
+ */
+
+/* Middle module dependency - size of a packet descriptor */
+int MM_Packet_Desc_Size = sizeof(UM_PACKET);
+
+
+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_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_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_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_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 = malloc(BlockSize);
+    mapping = (dma_addr_t)(pvirt);
+    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, (dma_addr_t) 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;
+
+    pvirt = malloc(BlockSize);
+
+    if (!pvirt)
+       return LM_STATUS_FAILURE;
+
+    pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
+    pUmDevice->dma_list[pUmDevice->mem_list_num] = 0;
+    pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
+    memset(pvirt, 0, BlockSize);
+    *pMemoryBlockVirt = pvirt;
+
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_MapMemBase(PLM_DEVICE_BLOCK pDevice)
+{
+    printf("BCM570x PCI Memory base address @0x%x\n",
+          (unsigned int)pDevice->pMappedMemBase);
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice)
+{
+    int i;
+    void* skb;
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    PUM_PACKET pUmPacket = NULL;
+    PLM_PACKET pPacket = NULL;
+
+    for (i = 0; i < pDevice->RxPacketDescCnt; i++) {
+       pPacket = QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+       pUmPacket = (PUM_PACKET) pPacket;
+
+       if (pPacket == 0) {
+           printf("MM_InitializeUmPackets: Bad RxPacketFreeQ\n");
+       }
+
+       skb = bcm570xPktAlloc(pUmDevice->index,
+                             pPacket->u.Rx.RxBufferSize + 2);
+
+       if (skb == 0) {
+           pUmPacket->skbuff = 0;
+           QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
+           printf("MM_InitializeUmPackets: out of buffer.\n");
+           continue;
+       }
+
+       pUmPacket->skbuff = skb;
+       QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+    }
+
+    pUmDevice->rx_low_buf_thresh = pDevice->RxPacketDescCnt / 8;
+
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_GetConfig(PLM_DEVICE_BLOCK pDevice)
+{
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    int index = pDevice->index;
+
+    if (auto_speed[index] == 0)
+       pDevice->DisableAutoNeg = TRUE;
+    else
+       pDevice->DisableAutoNeg = FALSE;
+
+    if (line_speed[index] == 0) {
+       pDevice->RequestedMediaType =
+           LM_REQUESTED_MEDIA_TYPE_AUTO;
+       pDevice->DisableAutoNeg = FALSE;
+    }
+    else {
+       if (line_speed[index] == 1000) {
+           if (pDevice->EnableTbi) {
+               pDevice->RequestedMediaType =
+                   LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX;
+           }
+           else if (full_duplex[index]) {
+               pDevice->RequestedMediaType =
+                   LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX;
+           }
+           else {
+               pDevice->RequestedMediaType =
+                   LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS;
+           }
+           if (!pDevice->EnableTbi)
+               pDevice->DisableAutoNeg = FALSE;
+       }
+       else if (line_speed[index] == 100) {
+           if (full_duplex[index]) {
+               pDevice->RequestedMediaType =
+                   LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX;
+           }
+           else {
+               pDevice->RequestedMediaType =
+                   LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS;
+           }
+       }
+       else if (line_speed[index] == 10) {
+           if (full_duplex[index]) {
+               pDevice->RequestedMediaType =
+                   LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX;
+           }
+           else {
+               pDevice->RequestedMediaType =
+                   LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS;
+           }
+       }
+       else {
+           pDevice->RequestedMediaType =
+               LM_REQUESTED_MEDIA_TYPE_AUTO;
+           pDevice->DisableAutoNeg = FALSE;
+       }
+
+    }
+    pDevice->FlowControlCap = 0;
+    if (rx_flow_control[index] != 0) {
+       pDevice->FlowControlCap |= LM_FLOW_CONTROL_RECEIVE_PAUSE;
+    }
+    if (tx_flow_control[index] != 0) {
+       pDevice->FlowControlCap |= LM_FLOW_CONTROL_TRANSMIT_PAUSE;
+    }
+    if ((auto_flow_control[index] != 0) &&
+       (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;
+       }
+    }
+
+    /* Default MTU for now */
+    pUmDevice->mtu = 1500;
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    if (pUmDevice->mtu > 1500) {
+       pDevice->RxMtu = pUmDevice->mtu;
+       pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT;
+    }
+    else {
+       pDevice->RxJumboDescCnt = 0;
+    }
+    pDevice->RxJumboDescCnt = rx_jumbo_desc_cnt[index];
+#else
+    pDevice->RxMtu = pUmDevice->mtu;
+#endif
+
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) {
+       pDevice->UseTaggedStatus = TRUE;
+       pUmDevice->timer_interval = CFG_HZ;
+    }
+    else {
+       pUmDevice->timer_interval = CFG_HZ/50;
+    }
+
+    pDevice->TxPacketDescCnt = tx_pkt_desc_cnt[index];
+    pDevice->RxStdDescCnt = rx_std_desc_cnt[index];
+    /* Note:  adaptive coalescence really isn't adaptive in this driver */
+    pUmDevice->rx_adaptive_coalesce = rx_adaptive_coalesce[index];
+    if (!pUmDevice->rx_adaptive_coalesce) {
+       pDevice->RxCoalescingTicks = rx_coalesce_ticks[index];
+       if (pDevice->RxCoalescingTicks > MAX_RX_COALESCING_TICKS)
+           pDevice->RxCoalescingTicks = MAX_RX_COALESCING_TICKS;
+       pUmDevice->rx_curr_coalesce_ticks =pDevice->RxCoalescingTicks;
+
+       pDevice->RxMaxCoalescedFrames = rx_max_coalesce_frames[index];
+       if (pDevice->RxMaxCoalescedFrames>MAX_RX_MAX_COALESCED_FRAMES)
+           pDevice->RxMaxCoalescedFrames =
+                               MAX_RX_MAX_COALESCED_FRAMES;
+       pUmDevice->rx_curr_coalesce_frames =
+           pDevice->RxMaxCoalescedFrames;
+       pDevice->StatsCoalescingTicks = stats_coalesce_ticks[index];
+       if (pDevice->StatsCoalescingTicks>MAX_STATS_COALESCING_TICKS)
+           pDevice->StatsCoalescingTicks=
+               MAX_STATS_COALESCING_TICKS;
+       }
+       else {
+           pUmDevice->rx_curr_coalesce_frames =
+               DEFAULT_RX_MAX_COALESCED_FRAMES;
+           pUmDevice->rx_curr_coalesce_ticks =
+               DEFAULT_RX_COALESCING_TICKS;
+       }
+    pDevice->TxCoalescingTicks = tx_coalesce_ticks[index];
+    if (pDevice->TxCoalescingTicks > MAX_TX_COALESCING_TICKS)
+       pDevice->TxCoalescingTicks = MAX_TX_COALESCING_TICKS;
+    pDevice->TxMaxCoalescedFrames = tx_max_coalesce_frames[index];
+    if (pDevice->TxMaxCoalescedFrames > MAX_TX_MAX_COALESCED_FRAMES)
+       pDevice->TxMaxCoalescedFrames = MAX_TX_MAX_COALESCED_FRAMES;
+
+    if (enable_wol[index]) {
+       pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET;
+       pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET;
+    }
+    pDevice->NicSendBd = TRUE;
+
+    /* Don't update status blocks during interrupt */
+    pDevice->RxCoalescingTicksDuringInt = 0;
+    pDevice->TxCoalescingTicksDuringInt = 0;
+
+    return LM_STATUS_SUCCESS;
+
+}
+
+
+LM_STATUS
+MM_StartTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    printf("Start TX DMA: dev=%d packet @0x%x\n",
+          (int)pUmDevice->index, (unsigned int)pPacket);
+
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_CompleteTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    printf("Complete TX DMA: dev=%d packet @0x%x\n",
+          (int)pUmDevice->index, (unsigned int)pPacket);
+    return LM_STATUS_SUCCESS;
+}
+
+
+LM_STATUS
+MM_IndicateStatus(PLM_DEVICE_BLOCK pDevice, LM_STATUS Status)
+{
+    char buf[128];
+    char lcd[4];
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    LM_FLOW_CONTROL flow_control;
+
+    pUmDevice->delayed_link_ind = 0;
+    memset(lcd, 0x0, 4);
+
+    if (Status == LM_STATUS_LINK_DOWN) {
+       sprintf(buf,"eth%d: %s: NIC Link is down\n",
+               pUmDevice->index,pUmDevice->name);
+        lcd[0] = 'L';lcd[1]='N';lcd[2]='K';lcd[3] = '?';
+    } else if (Status == LM_STATUS_LINK_ACTIVE) {
+       sprintf(buf,"eth%d:%s: ", pUmDevice->index, pUmDevice->name);
+
+       if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS){
+           strcat(buf,"1000 Mbps ");
+            lcd[0] = '1';lcd[1]='G';lcd[2]='B';
+       } else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS){
+           strcat(buf,"100 Mbps ");
+            lcd[0] = '1';lcd[1]='0';lcd[2]='0';
+       } else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS){
+           strcat(buf,"10 Mbps ");
+            lcd[0] = '1';lcd[1]='0';lcd[2]=' ';
+       }
+       if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL){
+           strcat(buf, "full duplex");
+            lcd[3] = 'F';
+       } else {
+           strcat(buf, "half duplex");
+            lcd[3] = 'H';
+       }
+       strcat(buf, " link up");
+
+       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) {
+               strcat(buf,", receive ");
+               if (flow_control & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
+                   strcat(buf," & transmit ");
+           }
+           else {
+               strcat(buf,", transmit ");
+           }
+           strcat(buf,"flow control ON");
+       } else {
+           strcat(buf, ", flow control OFF");
+       }
+        strcat(buf,"\n");
+       printf("%s",buf);
+    }
+#if 0
+    sysLedDsply(lcd[0],lcd[1],lcd[2],lcd[3]);
+#endif
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_FreeRxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    PUM_PACKET pUmPacket;
+    void *skb;
+
+    pUmPacket = (PUM_PACKET) pPacket;
+
+    if ((skb = pUmPacket->skbuff))
+       bcm570xPktFree(pUmDevice->index, skb);
+
+    pUmPacket->skbuff = 0;
+
+    return LM_STATUS_SUCCESS;
+}
+
+unsigned long
+MM_AnGetCurrentTime_us(PAN_STATE_INFO pAnInfo)
+{
+    return get_timer(0);
+}
+
+/*
+ *   Transform an MBUF chain into a single MBUF.
+ *   This routine will fail if the amount of data in the
+ *   chain overflows a transmit buffer.  In that case,
+ *   the incoming MBUF chain will be freed.  This routine can
+ *   also fail by not being able to allocate a new MBUF (including
+ *   cluster and mbuf headers).  In that case the failure is
+ *   non-fatal.  The incoming cluster chain is not freed, giving
+ *   the caller the choice of whether to try a retransmit later.
+ */
+LM_STATUS
+MM_CoalesceTxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+    PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    void *skbnew;
+    int len = 0;
+
+    if (len == 0)
+        return (LM_STATUS_SUCCESS);
+
+    if (len > MAX_PACKET_SIZE){
+        printf ("eth%d: xmit frame discarded, too big!, size = %d\n",
+               pUmDevice->index, len);
+        return (LM_STATUS_FAILURE);
+    }
+
+    skbnew = bcm570xPktAlloc(pUmDevice->index, MAX_PACKET_SIZE);
+
+    if (skbnew == NULL) {
+        pUmDevice->tx_full = 1;
+        printf ("eth%d: out of transmit buffers", pUmDevice->index);
+        return (LM_STATUS_FAILURE);
+    }
+
+    /* New packet values */
+    pUmPacket->skbuff = skbnew;
+    pUmPacket->lm_packet.u.Tx.FragCount = 1;
+
+    return (LM_STATUS_SUCCESS);
+}
+
+
+LM_STATUS
+MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice)
+{
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    pUmDevice->rx_pkt = 1;
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice)
+{
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    PLM_PACKET pPacket;
+    PUM_PACKET pUmPacket;
+    void *skb;
+    while ( TRUE ) {
+
+       pPacket = (PLM_PACKET)
+           QQ_PopHead(&pDevice->TxPacketXmittedQ.Container);
+
+       if (pPacket == 0)
+           break;
+
+       pUmPacket = (PUM_PACKET) pPacket;
+       skb = (void*)pUmPacket->skbuff;
+
+        /*
+        * Free MBLK if we transmitted a fragmented packet or a
+        * non-fragmented packet straight from the VxWorks
+        * buffer pool. If packet was copied to a local transmit
+        * buffer, then there's no MBUF to free, just free
+        * the transmit buffer back to the cluster pool.
+        */
+
+       if (skb)
+           bcm570xPktFree (pUmDevice->index, skb);
+
+       pUmPacket->skbuff = 0;
+       QQ_PushTail(&pDevice->TxPacketFreeQ.Container, pPacket);
+       pUmDevice->tx_pkt = 1;
+    }
+    if (pUmDevice->tx_full) {
+       if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) >=
+           (QQ_GetSize(&pDevice->TxPacketFreeQ.Container) >> 1))
+           pUmDevice->tx_full = 0;
+    }
+    return LM_STATUS_SUCCESS;
+}
+
+/*
+ *  Scan an MBUF chain until we reach fragment number "frag"
+ *  Return its length and physical address.
+ */
+void MM_MapTxDma
+    (
+    PLM_DEVICE_BLOCK pDevice,
+    struct _LM_PACKET *pPacket,
+    T3_64BIT_HOST_ADDR *paddr,
+    LM_UINT32 *len,
+    int frag)
+{
+    PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
+    *len = pPacket->PacketSize;
+    MM_SetT3Addr(paddr, (dma_addr_t) pUmPacket->skbuff);
+}
+
+/*
+ *  Convert an mbuf address, a CPU local virtual address,
+ *  to a physical address as seen from a PCI device.  Store the
+ *  result at paddr.
+ */
+void MM_MapRxDma(
+                PLM_DEVICE_BLOCK pDevice,
+                struct _LM_PACKET *pPacket,
+                T3_64BIT_HOST_ADDR *paddr)
+{
+    PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
+    MM_SetT3Addr(paddr, (dma_addr_t) pUmPacket->skbuff);
+}
+
+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
+}
+
+void
+MM_SetT3Addr(T3_64BIT_HOST_ADDR *paddr, dma_addr_t addr)
+{
+        unsigned long baddr = (unsigned long) addr;
+#if (BITS_PER_LONG == 64)
+        set_64bit_addr(paddr, baddr & 0xffffffff, baddr >> 32);
+#else
+        set_64bit_addr(paddr, baddr, 0);
+#endif
+}
+
+/*
+ * This combination of `inline' and `extern' has almost the effect of a
+ * macro.  The way to use it is to put a function definition in a header
+ * file with these keywords, and put another copy of the definition
+ * (lacking `inline' and `extern') in a library file.  The definition in
+ * the header file will cause most calls to the function to be inlined.
+ * If any uses of the function remain, they will refer to the single copy
+ * in the library.
+ */
+void
+atomic_set(atomic_t* entry, int val)
+{
+    entry->counter = val;
+}
+int
+atomic_read(atomic_t* entry)
+{
+    return entry->counter;
+}
+void
+atomic_inc(atomic_t* entry)
+{
+    if(entry)
+       entry->counter++;
+}
+
+void
+atomic_dec(atomic_t* entry)
+{
+    if(entry)
+       entry->counter--;
+}
+
+void
+atomic_sub(int a, atomic_t* entry)
+{
+    if(entry)
+       entry->counter -= a;
+}
+
+void
+atomic_add(int a, atomic_t* entry)
+{
+    if(entry)
+       entry->counter += a;
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+void
+QQ_InitQueue(
+PQQ_CONTAINER pQueue,
+unsigned int QueueSize) {
+    pQueue->Head = 0;
+    pQueue->Tail = 0;
+    pQueue->Size = QueueSize+1;
+    atomic_set(&pQueue->EntryCnt, 0);
+} /* QQ_InitQueue */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+char
+QQ_Full(
+PQQ_CONTAINER pQueue) {
+    unsigned int NewHead;
+
+    NewHead = (pQueue->Head + 1) % pQueue->Size;
+
+    return(NewHead == pQueue->Tail);
+} /* QQ_Full */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+char
+QQ_Empty(
+PQQ_CONTAINER pQueue) {
+    return(pQueue->Head == pQueue->Tail);
+} /* QQ_Empty */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+unsigned int
+QQ_GetSize(
+PQQ_CONTAINER pQueue) {
+    return pQueue->Size;
+} /* QQ_GetSize */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+unsigned int
+QQ_GetEntryCnt(
+PQQ_CONTAINER pQueue) {
+    return atomic_read(&pQueue->EntryCnt);
+} /* QQ_GetEntryCnt */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    TRUE entry was added successfully.                                      */
+/*    FALSE queue is full.                                                    */
+/******************************************************************************/
+char
+QQ_PushHead(
+PQQ_CONTAINER pQueue,
+PQQ_ENTRY pEntry) {
+    unsigned int Head;
+
+    Head = (pQueue->Head + 1) % pQueue->Size;
+
+#if !defined(QQ_NO_OVERFLOW_CHECK)
+    if(Head == pQueue->Tail) {
+        return 0;
+    } /* if */
+#endif /* QQ_NO_OVERFLOW_CHECK */
+
+    pQueue->Array[pQueue->Head] = pEntry;
+    wmb();
+    pQueue->Head = Head;
+    atomic_inc(&pQueue->EntryCnt);
+
+    return -1;
+} /* QQ_PushHead */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    TRUE entry was added successfully.                                      */
+/*    FALSE queue is full.                                                    */
+/******************************************************************************/
+char
+QQ_PushTail(
+PQQ_CONTAINER pQueue,
+PQQ_ENTRY pEntry) {
+    unsigned int Tail;
+
+    Tail = pQueue->Tail;
+    if(Tail == 0) {
+        Tail = pQueue->Size;
+    } /* if */
+    Tail--;
+
+#if !defined(QQ_NO_OVERFLOW_CHECK)
+    if(Tail == pQueue->Head) {
+        return 0;
+    } /* if */
+#endif /* QQ_NO_OVERFLOW_CHECK */
+
+    pQueue->Array[Tail] = pEntry;
+    wmb();
+    pQueue->Tail = Tail;
+    atomic_inc(&pQueue->EntryCnt);
+
+    return -1;
+} /* QQ_PushTail */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+PQQ_ENTRY
+QQ_PopHead(
+PQQ_CONTAINER pQueue) {
+    unsigned int Head;
+    PQQ_ENTRY Entry;
+
+    Head = pQueue->Head;
+
+#if !defined(QQ_NO_UNDERFLOW_CHECK)
+    if(Head == pQueue->Tail) {
+        return (PQQ_ENTRY) 0;
+    } /* if */
+#endif /* QQ_NO_UNDERFLOW_CHECK */
+
+    if(Head == 0) {
+        Head = pQueue->Size;
+    } /* if */
+    Head--;
+
+    Entry = pQueue->Array[Head];
+    membar();
+
+    pQueue->Head = Head;
+    atomic_dec(&pQueue->EntryCnt);
+
+    return Entry;
+} /* QQ_PopHead */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+PQQ_ENTRY
+QQ_PopTail(
+PQQ_CONTAINER pQueue) {
+    unsigned int Tail;
+    PQQ_ENTRY Entry;
+
+    Tail = pQueue->Tail;
+
+#if !defined(QQ_NO_UNDERFLOW_CHECK)
+    if(Tail == pQueue->Head) {
+        return (PQQ_ENTRY) 0;
+    } /* if */
+#endif /* QQ_NO_UNDERFLOW_CHECK */
+
+    Entry = pQueue->Array[Tail];
+    membar();
+    pQueue->Tail = (Tail + 1) % pQueue->Size;
+    atomic_dec(&pQueue->EntryCnt);
+
+    return Entry;
+} /* QQ_PopTail */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+PQQ_ENTRY
+QQ_GetHead(
+    PQQ_CONTAINER pQueue,
+    unsigned int Idx)
+{
+    if(Idx >= atomic_read(&pQueue->EntryCnt))
+    {
+        return (PQQ_ENTRY) 0;
+    }
+
+    if(pQueue->Head > Idx)
+    {
+        Idx = pQueue->Head - Idx;
+    }
+    else
+    {
+        Idx = pQueue->Size - (Idx - pQueue->Head);
+    }
+    Idx--;
+
+    return pQueue->Array[Idx];
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+PQQ_ENTRY
+QQ_GetTail(
+    PQQ_CONTAINER pQueue,
+    unsigned int Idx)
+{
+    if(Idx >= atomic_read(&pQueue->EntryCnt))
+    {
+        return (PQQ_ENTRY) 0;
+    }
+
+    Idx += pQueue->Tail;
+    if(Idx >= pQueue->Size)
+    {
+        Idx = Idx - pQueue->Size;
+    }
+
+    return pQueue->Array[Idx];
+}
+
+#endif /* CFG_CMD_NET, !CONFIG_NET_MULTI, CONFIG_BCM570x */
diff --git a/drivers/bcm570x_autoneg.c b/drivers/bcm570x_autoneg.c
new file mode 100644 (file)
index 0000000..bd6b7f6
--- /dev/null
@@ -0,0 +1,444 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2001 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/******************************************************************************/
+#if !defined(CONFIG_NET_MULTI)
+#if INCLUDE_TBI_SUPPORT
+#include "bcm570x_autoneg.h"
+#include "bcm570x_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 0
+//                if(pAnInfo->IdleMatch == AN_TRUE)
+//                {
+#endif
+                    pAnInfo->State = AN_STATE_LINK_OK;
+#if 0
+//                }
+//                else
+//                {
+//                    AnRet = AUTONEG_STATUS_FAILED;
+//                    break;
+//                }
+#endif
+            }
+
+            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 */
+
+#endif /* !defined(CONFIG_NET_MULTI) */
diff --git a/drivers/bcm570x_autoneg.h b/drivers/bcm570x_autoneg.h
new file mode 100644 (file)
index 0000000..7bf929f
--- /dev/null
@@ -0,0 +1,415 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2001 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           9000       /* 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
+{
+    /* 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;
+
+    /* Need these values for consistency check. */
+    unsigned short AbilityMatchCfg;
+
+    /* Ability, idle, and ack match functions. */
+    unsigned long AbilityMatchCnt;
+    char AbilityMatch;
+    char IdleMatch;
+    char AckMatch;
+
+    /* 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 int D7:1;        /* PS1 */
+            unsigned int D6:1;        /* HD */
+            unsigned int D5:1;        /* FD */
+            unsigned int D4:1;
+            unsigned int D3:1;
+            unsigned int D2:1;
+            unsigned int D1:1;
+            unsigned int D0:1;
+            unsigned int D15:1;       /* NP */
+            unsigned int D14:1;       /* ACK */
+            unsigned int D13:1;       /* RF2 */
+            unsigned int D12:1;       /* RF1 */
+            unsigned int D11:1;
+            unsigned int D10:1;
+            unsigned int D9:1;
+            unsigned int 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 int D7:1;        /* PS1 */
+            unsigned int D6:1;        /* HD */
+           unsigned int D5:1;        /* FD */
+            unsigned int D4:1;
+            unsigned int D3:1;
+            unsigned int D2:1;
+            unsigned int D1:1;
+            unsigned int D0:1;
+           unsigned int D15:1;       /* NP */
+            unsigned int D14:1;       /* ACK */
+            unsigned int D13:1;       /* RF2 */    
+            unsigned int D12:1;       /* RF1 */
+            unsigned int D11:1;
+            unsigned int D10:1;
+            unsigned int D9:1;
+            unsigned int 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;
+
+
+    /* Implement specifics */
+
+    /* Pointer to the operating system specific data structure. */
+    void *pContext;
+} 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           = 0xfffffff
+} AUTONEG_STATUS, *PAUTONEG_STATUS;
+
+
+
+/******************************************************************************/
+/* Function prototypes. */
+/******************************************************************************/
+
+AUTONEG_STATUS Autoneg8023z(PAN_STATE_INFO pAnInfo);
+void AutonegInit(PAN_STATE_INFO pAnInfo);
+
+
+
+/******************************************************************************/
+/* The following functions are defined in the os-dependent module. */
+/******************************************************************************/
+
+void MM_AnTxConfig(PAN_STATE_INFO pAnInfo);
+void MM_AnTxIdle(PAN_STATE_INFO pAnInfo);
+char MM_AnRxConfig(PAN_STATE_INFO pAnInfo, unsigned short *pRxConfig);
+
+
+
+#endif /* AUTONEG_H */
+
diff --git a/drivers/bcm570x_bits.h b/drivers/bcm570x_bits.h
new file mode 100644 (file)
index 0000000..79b1052
--- /dev/null
@@ -0,0 +1,59 @@
+
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/*    02/25/00 Hav Khauv        Initial version.                              */
+/******************************************************************************/
+
+#ifndef BITS_H
+#define BITS_H
+
+
+
+/******************************************************************************/
+/* Bit Mask definitions */
+/******************************************************************************/
+#define BIT_NONE            0x00
+#define BIT_0               0x01
+#define BIT_1               0x02
+#define BIT_2               0x04
+#define BIT_3               0x08
+#define BIT_4               0x10
+#define BIT_5               0x20
+#define BIT_6               0x40
+#define BIT_7               0x80
+#define BIT_8               0x0100
+#define BIT_9               0x0200
+#define BIT_10              0x0400
+#define BIT_11              0x0800
+#define BIT_12              0x1000
+#define BIT_13              0x2000
+#define BIT_14              0x4000
+#define BIT_15              0x8000
+#define BIT_16              0x010000
+#define BIT_17              0x020000
+#define BIT_18              0x040000
+#define BIT_19              0x080000
+#define BIT_20              0x100000
+#define BIT_21              0x200000
+#define BIT_22              0x400000
+#define BIT_23              0x800000
+#define BIT_24              0x01000000
+#define BIT_25              0x02000000
+#define BIT_26              0x04000000
+#define BIT_27              0x08000000
+#define BIT_28              0x10000000
+#define BIT_29              0x20000000
+#define BIT_30              0x40000000
+#define BIT_31              0x80000000
+
+#endif /* BITS_H */
+
diff --git a/drivers/bcm570x_debug.h b/drivers/bcm570x_debug.h
new file mode 100644 (file)
index 0000000..2263879
--- /dev/null
@@ -0,0 +1,111 @@
+
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/*    02/25/00 Hav Khauv        Initial version.                              */
+/******************************************************************************/
+
+#ifndef DEBUG_H 
+#define DEBUG_H 
+
+#ifdef VXWORKS
+#include <vxWorks.h>
+#endif
+
+/******************************************************************************/
+/* Debug macros                                                               */
+/******************************************************************************/
+
+/* Code path for controlling output debug messages. */
+/* Define your code path here. */
+#define CP_INIT                     0x010000
+#define CP_SEND                     0x020000
+#define CP_RCV                      0x040000
+#define CP_INT                      0x080000
+#define CP_UINIT                    0x100000
+#define CP_RESET                    0x200000
+
+#define CP_ALL                      (CP_INIT | CP_SEND | CP_RCV | CP_INT | \
+                                    CP_RESET | CP_UINIT)
+
+#define CP_MASK                     0xffff0000
+
+
+/* Debug message levels. */
+#define LV_VERBOSE                  0x03
+#define LV_INFORM                   0x02
+#define LV_WARN                     0x01
+#define LV_FATAL                    0x00
+
+#define LV_MASK                     0xffff
+
+
+/* Code path and messsage level combined.  These are the first argument of */
+/* the DbgMessage macro. */
+#define INIT_V                      (CP_INIT | LV_VERBOSE)
+#define INIT_I                      (CP_INIT | LV_INFORM)
+#define INIT_W                      (CP_INIT | LV_WARN)
+#define SEND_V                      (CP_SEND | LV_VERBOSE)
+#define SEND_I                      (CP_SEND | LV_INFORM)
+#define SEND_W                      (CP_SEND | LV_WARN)
+#define RCV_V                       (CP_RCV | LV_VERBOSE)
+#define RCV_I                       (CP_RCV | LV_INFORM)
+#define RCV_W                       (CP_RCV | LV_WARN)
+#define INT_V                       (CP_INT | LV_VERBOSE)
+#define INT_I                       (CP_INT | LV_INFORM)
+#define INT_W                       (CP_INT | LV_WARN)
+#define UINIT_V                     (CP_UINIT | LV_VERBOSE)
+#define UINIT_I                     (CP_UINIT | LV_INFORM)
+#define UINIT_W                     (CP_UINIT | LV_WARN)
+#define RESET_V                     (CP_RESET | LV_VERBOSE)
+#define RESET_I                     (CP_RESET | LV_INFORM)
+#define RESET_W                     (CP_RESET | LV_WARN)
+#define CPALL_V                     (CP_ALL | LV_VERBOSE)
+#define CPALL_I                     (CP_ALL | LV_INFORM)
+#define CPALL_W                     (CP_ALL | LV_WARN)
+
+
+/* All code path message levels. */
+#define FATAL                       (CP_ALL | LV_FATAL)
+#define WARN                        (CP_ALL | LV_WARN)
+#define INFORM                      (CP_ALL | LV_INFORM)
+#define VERBOSE                     (CP_ALL | LV_VERBOSE)
+
+
+/* These constants control the message output. */
+/* Set your debug message output level and code path here. */
+#ifndef DBG_MSG_CP
+#define DBG_MSG_CP                  CP_ALL      /* Where to output messages. */
+#endif
+
+#ifndef DBG_MSG_LV
+#define DBG_MSG_LV                  LV_VERBOSE  /* Level of message output. */
+#endif
+
+/* DbgMessage macro. */
+#if DBG
+#define DbgMessage(CNTRL, MESSAGE)  \
+    if((CNTRL & DBG_MSG_CP) && ((CNTRL & LV_MASK) <= DBG_MSG_LV)) \
+        printf MESSAGE
+#define DbgBreak()                 DbgBreakPoint() 
+#undef STATIC
+#define STATIC
+#else
+#define DbgMessage(CNTRL, MESSAGE)
+#define DbgBreak()
+#undef STATIC
+#define STATIC static
+#endif /* DBG */
+
+
+
+#endif /* DEBUG_H */
+
diff --git a/drivers/bcm570x_lm.h b/drivers/bcm570x_lm.h
new file mode 100644 (file)
index 0000000..77cad57
--- /dev/null
@@ -0,0 +1,469 @@
+
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/*    02/25/00 Hav Khauv        Initial version.                              */
+/******************************************************************************/
+
+#ifndef LM_H
+#define LM_H
+
+#include "bcm570x_queue.h"
+#include "bcm570x_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 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. */
+
+#ifndef LM_MAX_MC_TABLE_SIZE
+#define LM_MAX_MC_TABLE_SIZE            32
+#endif /* LM_MAX_MC_TABLE_SIZE */
+#define LM_MC_ENTRY_SIZE                (ETHERNET_ADDRESS_SIZE+1)
+#define LM_MC_INSTANCE_COUNT_INDEX      (LM_MC_ENTRY_SIZE-1)
+
+
+/* Receive filter masks. */
+#define LM_ACCEPT_UNICAST               0x0001
+#define LM_ACCEPT_MULTICAST             0x0002
+#define LM_ACCEPT_ALL_MULTICAST         0x0004
+#define LM_ACCEPT_BROADCAST             0x0008
+#define LM_ACCEPT_ERROR_PACKET          0x0010
+
+#define LM_PROMISCUOUS_MODE             0x10000
+
+
+
+/******************************************************************************/
+/* PCI registers. */
+/******************************************************************************/
+
+#define PCI_VENDOR_ID_REG               0x00
+#define PCI_DEVICE_ID_REG               0x02
+
+#define PCI_COMMAND_REG                 0x04
+#define PCI_IO_SPACE_ENABLE             0x0001
+#define PCI_MEM_SPACE_ENABLE            0x0002
+#define PCI_BUSMASTER_ENABLE            0x0004
+#define PCI_MEMORY_WRITE_INVALIDATE     0x0010
+#define PCI_PARITY_ERROR_ENABLE         0x0040
+#define PCI_SYSTEM_ERROR_ENABLE         0x0100
+#define PCI_FAST_BACK_TO_BACK_ENABLE    0x0200
+
+#define PCI_STATUS_REG                  0x06
+#define PCI_REV_ID_REG                  0x08
+
+#define PCI_CACHE_LINE_SIZE_REG         0x0c
+
+#define PCI_IO_BASE_ADDR_REG            0x10
+#define PCI_IO_BASE_ADDR_MASK           0xfffffff0
+
+#define PCI_MEM_BASE_ADDR_LOW           0x10
+#define PCI_MEM_BASE_ADDR_HIGH          0x14
+
+#define PCI_SUBSYSTEM_VENDOR_ID_REG     0x2c
+#define PCI_SUBSYSTEM_ID_REG            0x2e
+#define PCI_INT_LINE_REG                0x3c
+
+#define PCIX_CAP_REG                    0x40
+#define PCIX_ENABLE_RELAXED_ORDERING    BIT_17
+
+/******************************************************************************/
+/* Fragment structure. */
+/******************************************************************************/
+
+typedef struct {
+    LM_UINT32 FragSize;
+    LM_PHYSICAL_ADDRESS FragBuf;
+} LM_FRAG, *PLM_FRAG;
+
+typedef struct {
+    /* FragCount is initialized for the caller to the maximum array size, on */
+    /* return FragCount is the number of the actual fragments in the array. */
+    LM_UINT32 FragCount;
+
+    /* Total buffer size. */
+    LM_UINT32 TotalSize;
+
+    /* Fragment array buffer. */
+    LM_FRAG Fragments[1];
+} LM_FRAG_LIST, *PLM_FRAG_LIST;
+
+#define DECLARE_FRAG_LIST_BUFFER_TYPE(_FRAG_LIST_TYPE_NAME, _MAX_FRAG_COUNT) \
+    typedef struct {                                                         \
+        LM_FRAG_LIST FragList;                                               \
+        LM_FRAG FragListBuffer[_MAX_FRAG_COUNT-1];                           \
+    } _FRAG_LIST_TYPE_NAME, *P##_FRAG_LIST_TYPE_NAME
+
+
+
+/******************************************************************************/
+/* Status codes. */
+/******************************************************************************/
+
+#define LM_STATUS_SUCCESS                                       0
+#define LM_STATUS_FAILURE                                       1
+
+#define LM_STATUS_INTERRUPT_ACTIVE                              2
+#define LM_STATUS_INTERRUPT_NOT_ACTIVE                          3
+
+#define LM_STATUS_LINK_ACTIVE                                   4
+#define LM_STATUS_LINK_DOWN                                     5
+#define LM_STATUS_LINK_SETTING_MISMATCH                         6
+
+#define LM_STATUS_TOO_MANY_FRAGMENTS                            7
+#define LM_STATUS_TRANSMIT_ABORTED                              8
+#define LM_STATUS_TRANSMIT_ERROR                                9
+#define LM_STATUS_RECEIVE_ABORTED                               10
+#define LM_STATUS_RECEIVE_ERROR                                 11
+#define LM_STATUS_INVALID_PACKET_SIZE                           12
+#define LM_STATUS_OUT_OF_MAP_REGISTERS                          13
+#define LM_STATUS_UNKNOWN_ADAPTER                               14
+
+typedef LM_UINT LM_STATUS, *PLM_STATUS;
+
+
+
+/******************************************************************************/
+/* Requested media type. */
+/******************************************************************************/
+
+#define LM_REQUESTED_MEDIA_TYPE_AUTO                            0
+#define LM_REQUESTED_MEDIA_TYPE_BNC                             1
+#define LM_REQUESTED_MEDIA_TYPE_UTP_AUTO                        2
+#define LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS                      3
+#define LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX          4
+#define LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS                     5
+#define LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX         6
+#define LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS                    7
+#define LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX        8
+#define LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS                   9
+#define LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS_FULL_DUPLEX       10
+#define LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS                  11
+#define LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX      12
+#define LM_REQUESTED_MEDIA_TYPE_MAC_LOOPBACK                    0xfffe
+#define LM_REQUESTED_MEDIA_TYPE_PHY_LOOPBACK                    0xffff
+
+typedef LM_UINT32 LM_REQUESTED_MEDIA_TYPE, *PLM_REQUESTED_MEDIA_TYPE;
+
+
+
+/******************************************************************************/
+/* Media type. */
+/******************************************************************************/
+
+#define LM_MEDIA_TYPE_UNKNOWN                                   -1
+#define LM_MEDIA_TYPE_AUTO                                      0
+#define LM_MEDIA_TYPE_UTP                                       1
+#define LM_MEDIA_TYPE_BNC                                       2
+#define LM_MEDIA_TYPE_AUI                                       3
+#define LM_MEDIA_TYPE_FIBER                                     4
+
+typedef LM_UINT32 LM_MEDIA_TYPE, *PLM_MEDIA_TYPE;
+
+
+
+/******************************************************************************/
+/* Line speed. */
+/******************************************************************************/
+
+#define LM_LINE_SPEED_UNKNOWN                                   0
+#define LM_LINE_SPEED_10MBPS                                    1
+#define LM_LINE_SPEED_100MBPS                                   2
+#define LM_LINE_SPEED_1000MBPS                                  3
+
+typedef LM_UINT32 LM_LINE_SPEED, *PLM_LINE_SPEED;
+
+
+
+/******************************************************************************/
+/* Duplex mode. */
+/******************************************************************************/
+
+#define LM_DUPLEX_MODE_UNKNOWN                                  0
+#define LM_DUPLEX_MODE_HALF                                     1
+#define LM_DUPLEX_MODE_FULL                                     2
+
+typedef LM_UINT32 LM_DUPLEX_MODE, *PLM_DUPLEX_MODE;
+
+
+
+/******************************************************************************/
+/* Power state. */
+/******************************************************************************/
+
+#define LM_POWER_STATE_D0       0
+#define LM_POWER_STATE_D1       1
+#define LM_POWER_STATE_D2       2
+#define LM_POWER_STATE_D3       3
+
+typedef LM_UINT32 LM_POWER_STATE, *PLM_POWER_STATE;
+
+
+
+/******************************************************************************/
+/* Task offloading. */
+/******************************************************************************/
+
+#define LM_TASK_OFFLOAD_NONE                    0x0000
+#define LM_TASK_OFFLOAD_TX_IP_CHECKSUM          0x0001
+#define LM_TASK_OFFLOAD_RX_IP_CHECKSUM          0x0002
+#define LM_TASK_OFFLOAD_TX_TCP_CHECKSUM         0x0004
+#define LM_TASK_OFFLOAD_RX_TCP_CHECKSUM         0x0008
+#define LM_TASK_OFFLOAD_TX_UDP_CHECKSUM         0x0010
+#define LM_TASK_OFFLOAD_RX_UDP_CHECKSUM         0x0020
+#define LM_TASK_OFFLOAD_TCP_SEGMENTATION        0x0040
+
+typedef LM_UINT32 LM_TASK_OFFLOAD, *PLM_TASK_OFFLOAD;
+
+
+
+/******************************************************************************/
+/* Flow control. */
+/******************************************************************************/
+
+#define LM_FLOW_CONTROL_NONE                    0x00
+#define LM_FLOW_CONTROL_RECEIVE_PAUSE           0x01
+#define LM_FLOW_CONTROL_TRANSMIT_PAUSE          0x02
+#define LM_FLOW_CONTROL_RX_TX_PAUSE (LM_FLOW_CONTROL_RECEIVE_PAUSE | \
+    LM_FLOW_CONTROL_TRANSMIT_PAUSE)
+
+/* This value can be or-ed with RECEIVE_PAUSE and TRANSMIT_PAUSE.  If the */
+/* auto-negotiation is disabled and the RECEIVE_PAUSE and TRANSMIT_PAUSE */
+/* bits are set, then flow control is enabled regardless of link partner's */
+/* flow control capability. */
+#define LM_FLOW_CONTROL_AUTO_PAUSE              0x80000000
+
+typedef LM_UINT32 LM_FLOW_CONTROL, *PLM_FLOW_CONTROL;
+
+
+
+/******************************************************************************/
+/* Wake up mode. */
+/******************************************************************************/
+
+#define LM_WAKE_UP_MODE_NONE                    0
+#define LM_WAKE_UP_MODE_MAGIC_PACKET            1
+#define LM_WAKE_UP_MODE_NWUF                    2
+#define LM_WAKE_UP_MODE_LINK_CHANGE             4
+
+typedef LM_UINT32 LM_WAKE_UP_MODE, *PLM_WAKE_UP_MODE;
+
+
+
+/******************************************************************************/
+/* Counters. */
+/******************************************************************************/
+
+#define LM_COUNTER_FRAMES_XMITTED_OK                            0
+#define LM_COUNTER_FRAMES_RECEIVED_OK                           1
+#define LM_COUNTER_ERRORED_TRANSMIT_COUNT                       2
+#define LM_COUNTER_ERRORED_RECEIVE_COUNT                        3
+#define LM_COUNTER_RCV_CRC_ERROR                                4
+#define LM_COUNTER_ALIGNMENT_ERROR                              5
+#define LM_COUNTER_SINGLE_COLLISION_FRAMES                      6
+#define LM_COUNTER_MULTIPLE_COLLISION_FRAMES                    7
+#define LM_COUNTER_FRAMES_DEFERRED                              8
+#define LM_COUNTER_MAX_COLLISIONS                               9
+#define LM_COUNTER_RCV_OVERRUN                                  10
+#define LM_COUNTER_XMIT_UNDERRUN                                11
+#define LM_COUNTER_UNICAST_FRAMES_XMIT                          12
+#define LM_COUNTER_MULTICAST_FRAMES_XMIT                        13
+#define LM_COUNTER_BROADCAST_FRAMES_XMIT                        14
+#define LM_COUNTER_UNICAST_FRAMES_RCV                           15
+#define LM_COUNTER_MULTICAST_FRAMES_RCV                         16
+#define LM_COUNTER_BROADCAST_FRAMES_RCV                         17
+
+typedef LM_UINT32 LM_COUNTER_TYPE, *PLM_COUNTER_TYPE;
+
+
+
+/******************************************************************************/
+/* Forward definition. */
+/******************************************************************************/
+
+typedef struct _LM_DEVICE_BLOCK *PLM_DEVICE_BLOCK;
+typedef struct _LM_PACKET *PLM_PACKET;
+
+
+
+/******************************************************************************/
+/* Function prototypes. */
+/******************************************************************************/
+
+LM_STATUS LM_GetAdapterInfo(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_InitializeAdapter(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_ResetAdapter(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_DisableInterrupt(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_EnableInterrupt(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+LM_STATUS LM_ServiceInterrupts(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_QueueRxPackets(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_SetReceiveMask(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Mask);
+LM_STATUS LM_Halt(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_Abort(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_MulticastAdd(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress);
+LM_STATUS LM_MulticastDel(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress);
+LM_STATUS LM_MulticastClear(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_SetMacAddress(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMacAddress);
+LM_STATUS LM_LoopbackAddress(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pAddress);
+
+LM_UINT32 LM_GetCrcCounter(PLM_DEVICE_BLOCK pDevice);
+
+LM_WAKE_UP_MODE LM_PMCapabilities(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_NwufAdd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 ByteMaskSize,
+    LM_UINT8 *pByteMask, LM_UINT8 *pPattern);
+LM_STATUS LM_NwufRemove(PLM_DEVICE_BLOCK pDevice, LM_UINT32 ByteMaskSize,
+    LM_UINT8 *pByteMask, LM_UINT8 *pPattern);
+LM_STATUS LM_SetPowerState(PLM_DEVICE_BLOCK pDevice, LM_POWER_STATE PowerLevel);
+
+LM_VOID LM_ReadPhy(PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg,
+    PLM_UINT32 pData32);
+LM_VOID LM_WritePhy(PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg,
+    LM_UINT32 Data32);
+
+LM_STATUS LM_ControlLoopBack(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Control);
+LM_STATUS LM_SetupPhy(PLM_DEVICE_BLOCK pDevice);
+int LM_BlinkLED(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDuration);
+
+
+
+/******************************************************************************/
+/* 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);
+LM_STATUS LM_MbufWorkAround(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_SetLinkSpeed(PLM_DEVICE_BLOCK pDevice,
+                         LM_REQUESTED_MEDIA_TYPE RequestedMediaType);
+
+#if INCLUDE_5703_A0_FIX
+LM_STATUS LM_Load5703DmaWFirmware(PLM_DEVICE_BLOCK pDevice);
+#endif
+
+
+#endif /* LM_H */
+
diff --git a/drivers/bcm570x_mm.h b/drivers/bcm570x_mm.h
new file mode 100644 (file)
index 0000000..68e4e6b
--- /dev/null
@@ -0,0 +1,160 @@
+
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/******************************************************************************/
+
+#ifndef MM_H
+#define MM_H
+
+#define __raw_readl readl
+#define __raw_writel writel
+
+#define BIG_ENDIAN_HOST 1
+#define readl(addr) (*(volatile unsigned int*)(addr))
+#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b))
+
+/* Define memory barrier function here if needed */
+#define wmb()
+#define membar()
+#include <ppcboot.h>
+#include <asm/types.h>
+#include "bcm570x_lm.h"
+#include "bcm570x_queue.h"
+#include "tigon3.h"
+#include <pci.h>
+
+#define FALSE 0
+#define TRUE  1
+#define ERROR -1
+
+#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
+
+/* Synch */
+typedef int mutex_t;
+typedef int spinlock_t;
+
+/* Embedded device control */
+typedef struct _UM_DEVICE_BLOCK {
+       LM_DEVICE_BLOCK lm_dev;
+        pci_dev_t pdev;
+       char *name;
+       void *mem_list[MAX_MEM];
+       dma_addr_t dma_list[MAX_MEM];
+       int mem_size_list[MAX_MEM];
+       int mem_list_num;
+        int mtu;
+        int index;
+       int opened;
+       int delayed_link_ind; /* Delay link status during initial load */
+       int adapter_just_inited; /* the first few seconds after init. */
+       int spurious_int;            /* new -- unsupported */
+       int timer_interval;  
+       int adaptive_expiry;
+       int crc_counter_expiry;         /* new -- unsupported */
+       int poll_tib_expiry;         /* new -- unsupported */
+        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_low_buf_thresh; /* changed to rx_buf_repl_thresh */
+       int rx_buf_repl_panic_thresh;
+       int rx_buf_align;            /* new -- unsupported */
+       int do_global_lock;
+        mutex_t global_lock;
+        mutex_t undi_lock;
+       long undi_flags;
+       volatile int interrupt;
+       int tasklet_pending;
+       int tasklet_busy;            /* new -- unsupported */
+        int rx_pkt;
+        int tx_pkt; 
+#ifdef NICE_SUPPORT   /* unsupported, this is a linux ioctl */
+       void (*nice_rx)(void*, void* );
+       void* nice_ctx;
+#endif /* NICE_SUPPORT */
+       int rx_adaptive_coalesce;
+       unsigned int rx_last_cnt;
+       unsigned int tx_last_cnt;
+       unsigned int rx_curr_coalesce_frames;
+       unsigned int rx_curr_coalesce_ticks;
+       unsigned int tx_curr_coalesce_frames;  /* new -- unsupported */
+#if TIGON3_DEBUG          /* new -- unsupported */
+        uint tx_zc_count;
+        uint tx_chksum_count;
+        uint tx_himem_count;
+        uint rx_good_chksum_count;
+#endif
+        unsigned int rx_bad_chksum_count;   /* new -- unsupported */
+        unsigned int rx_misc_errors;        /* new -- unsupported */
+} UM_DEVICE_BLOCK, *PUM_DEVICE_BLOCK;
+
+
+/* Physical/PCI DMA address */
+typedef union {
+        dma_addr_t dma_map;
+} dma_map_t;
+
+/* Packet */
+typedef struct
+_UM_PACKET {
+    LM_PACKET lm_packet;
+    void* skbuff;      /* Address of packet buffer */
+} UM_PACKET, *PUM_PACKET;
+
+#define MM_ACQUIRE_UNDI_LOCK(_pDevice)
+#define MM_RELEASE_UNDI_LOCK(_pDevice)
+#define MM_ACQUIRE_INT_LOCK(_pDevice)
+#define MM_RELEASE_INT_LOCK(_pDevice)
+#define MM_UINT_PTR(_ptr)   ((unsigned long) (_ptr))
+
+/* Macro for setting 64bit address struct */
+#define set_64bit_addr(paddr, low, high) \
+        (paddr)->Low = low;             \
+        (paddr)->High = high;
+
+/* Assume that PCI controller's view of host memory is same as host */
+
+#define MEM_TO_PCI_PHYS(addr) (addr)
+
+extern void MM_SetAddr (LM_PHYSICAL_ADDRESS *paddr, dma_addr_t addr);
+extern void MM_SetT3Addr(T3_64BIT_HOST_ADDR *paddr, dma_addr_t addr);
+extern void MM_MapTxDma (PLM_DEVICE_BLOCK pDevice,
+                        struct _LM_PACKET *pPacket, T3_64BIT_HOST_ADDR *paddr,
+                        LM_UINT32 *len, int frag);
+extern void MM_MapRxDma ( PLM_DEVICE_BLOCK pDevice,
+                         struct _LM_PACKET *pPacket,
+                         T3_64BIT_HOST_ADDR *paddr);
+
+
+/* BSP needs to provide sysUsecDelay and sysSerialPrintString */
+extern void sysSerialPrintString (char *s);
+#define MM_Wait(usec) udelay(usec)
+
+/* Define memory barrier function here if needed */
+#define wmb() 
+
+#if 0
+#define cpu_to_le32(val) LONGSWAP(val)
+#endif
+#endif /* MM_H */
diff --git a/drivers/bcm570x_queue.h b/drivers/bcm570x_queue.h
new file mode 100644 (file)
index 0000000..c20b162
--- /dev/null
@@ -0,0 +1,399 @@
+
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* 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
+#ifndef EMBEDDED 
+#define EMBEDDED 1
+#endif
+
+/******************************************************************************/
+/* Queue definitions. */
+/******************************************************************************/
+
+/* Entry for queueing. */
+typedef void *PQQ_ENTRY;
+
+/* Linux Atomic Ops support */
+typedef struct { int counter; } atomic_t;
+
+
+/*
+ * This combination of `inline' and `extern' has almost the effect of a
+ * macro.  The way to use it is to put a function definition in a header
+ * file with these keywords, and put another copy of the definition
+ * (lacking `inline' and `extern') in a library file.  The definition in
+ * the header file will cause most calls to the function to be inlined.
+ * If any uses of the function remain, they will refer to the single copy
+ * in the library.
+ */
+extern __inline void
+atomic_set(atomic_t* entry, int val)
+{
+    entry->counter = val;
+}
+extern __inline int
+atomic_read(atomic_t* entry)
+{
+    return entry->counter;
+}
+extern __inline void
+atomic_inc(atomic_t* entry)
+{
+    if(entry)
+       entry->counter++;
+}
+
+extern __inline void
+atomic_dec(atomic_t* entry)
+{
+    if(entry)
+       entry->counter--;
+}
+
+extern __inline void
+atomic_sub(int a, atomic_t* entry)
+{
+    if(entry)
+       entry->counter -= a;
+}
+extern __inline void
+atomic_add(int a, atomic_t* entry)
+{
+    if(entry)
+       entry->counter += a;
+}
+
+
+/* Queue header -- base type. */
+typedef struct {
+    unsigned int Head;
+    unsigned int Tail;
+    unsigned int Size;
+    atomic_t EntryCnt;
+    PQQ_ENTRY Array[1];
+} QQ_CONTAINER, *PQQ_CONTAINER;
+
+
+/* Declare queue type macro. */
+#define DECLARE_QUEUE_TYPE(_QUEUE_TYPE, _QUEUE_SIZE)            \
+                                                                \
+    typedef struct {                                            \
+        QQ_CONTAINER Container;                                 \
+        PQQ_ENTRY EntryBuffer[_QUEUE_SIZE];                     \
+    } _QUEUE_TYPE, *P##_QUEUE_TYPE
+
+
+
+/******************************************************************************/
+/* Compilation switches. */
+/******************************************************************************/
+
+#if DBG
+#undef QQ_NO_OVERFLOW_CHECK
+#undef QQ_NO_UNDERFLOW_CHECK
+#endif /* DBG */
+
+#ifdef QQ_USE_MACROS
+/* notdone */
+#else
+
+#ifdef QQ_NO_INLINE
+#define __inline
+#endif /* QQ_NO_INLINE */
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+extern __inline void 
+QQ_InitQueue(
+PQQ_CONTAINER pQueue,
+unsigned int QueueSize) {
+    pQueue->Head = 0;
+    pQueue->Tail = 0;
+    pQueue->Size = QueueSize+1;
+    atomic_set(&pQueue->EntryCnt, 0);
+} /* QQ_InitQueue */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+extern __inline char 
+QQ_Full(
+PQQ_CONTAINER pQueue) {
+    unsigned int NewHead;
+
+    NewHead = (pQueue->Head + 1) % pQueue->Size;
+
+    return(NewHead == pQueue->Tail);
+} /* QQ_Full */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+extern __inline char 
+QQ_Empty(
+PQQ_CONTAINER pQueue) {
+    return(pQueue->Head == pQueue->Tail);
+} /* QQ_Empty */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+extern __inline unsigned int 
+QQ_GetSize(
+PQQ_CONTAINER pQueue) {
+    return pQueue->Size;
+} /* QQ_GetSize */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+extern __inline unsigned int 
+QQ_GetEntryCnt(
+PQQ_CONTAINER pQueue) {
+    return atomic_read(&pQueue->EntryCnt);
+} /* QQ_GetEntryCnt */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    TRUE entry was added successfully.                                      */
+/*    FALSE queue is full.                                                    */
+/******************************************************************************/
+extern __inline char 
+QQ_PushHead(
+PQQ_CONTAINER pQueue, 
+PQQ_ENTRY pEntry) {
+    unsigned int Head;
+
+    Head = (pQueue->Head + 1) % pQueue->Size;
+
+#if !defined(QQ_NO_OVERFLOW_CHECK)
+    if(Head == pQueue->Tail) {
+        return 0;
+    } /* if */
+#endif /* QQ_NO_OVERFLOW_CHECK */
+
+    pQueue->Array[pQueue->Head] = pEntry;
+    wmb();
+    pQueue->Head = Head;
+    atomic_inc(&pQueue->EntryCnt);
+
+    return -1;
+} /* QQ_PushHead */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    TRUE entry was added successfully.                                      */
+/*    FALSE queue is full.                                                    */
+/******************************************************************************/
+extern __inline char 
+QQ_PushTail(
+PQQ_CONTAINER pQueue,
+PQQ_ENTRY pEntry) {
+    unsigned int Tail;
+
+    Tail = pQueue->Tail;
+    if(Tail == 0) {
+        Tail = pQueue->Size;
+    } /* if */
+    Tail--;
+
+#if !defined(QQ_NO_OVERFLOW_CHECK)
+    if(Tail == pQueue->Head) {
+        return 0;
+    } /* if */
+#endif /* QQ_NO_OVERFLOW_CHECK */
+
+    pQueue->Array[Tail] = pEntry;
+    wmb();
+    pQueue->Tail = Tail;
+    atomic_inc(&pQueue->EntryCnt);
+
+    return -1;
+} /* QQ_PushTail */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+extern __inline PQQ_ENTRY
+QQ_PopHead(
+PQQ_CONTAINER pQueue) {
+    unsigned int Head;
+    PQQ_ENTRY Entry;
+
+    Head = pQueue->Head;
+
+#if !defined(QQ_NO_UNDERFLOW_CHECK)
+    if(Head == pQueue->Tail) {
+        return (PQQ_ENTRY) 0;
+    } /* if */
+#endif /* QQ_NO_UNDERFLOW_CHECK */
+
+    if(Head == 0) {
+        Head = pQueue->Size;
+    } /* if */
+    Head--;
+
+    Entry = pQueue->Array[Head];
+#ifdef EMBEDDED
+    membar();
+#else
+    mb();
+#endif
+    pQueue->Head = Head;
+    atomic_dec(&pQueue->EntryCnt);
+
+    return Entry;
+} /* QQ_PopHead */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+extern __inline PQQ_ENTRY
+QQ_PopTail(
+PQQ_CONTAINER pQueue) {
+    unsigned int Tail;
+    PQQ_ENTRY Entry;
+
+    Tail = pQueue->Tail;
+
+#if !defined(QQ_NO_UNDERFLOW_CHECK)
+    if(Tail == pQueue->Head) {
+        return (PQQ_ENTRY) 0;
+    } /* if */
+#endif /* QQ_NO_UNDERFLOW_CHECK */
+
+    Entry = pQueue->Array[Tail];
+#ifdef EMBEDDED
+    membar();
+#else
+    mb();
+#endif
+    pQueue->Tail = (Tail + 1) % pQueue->Size;
+    atomic_dec(&pQueue->EntryCnt);
+
+    return Entry;
+} /* QQ_PopTail */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+extern __inline PQQ_ENTRY
+QQ_GetHead(
+    PQQ_CONTAINER pQueue,
+    unsigned int Idx)
+{
+    if(Idx >= atomic_read(&pQueue->EntryCnt))
+    {
+        return (PQQ_ENTRY) 0;
+    }
+
+    if(pQueue->Head > Idx)
+    {
+        Idx = pQueue->Head - Idx;
+    }
+    else
+    {
+        Idx = pQueue->Size - (Idx - pQueue->Head);
+    }
+    Idx--;
+
+    return pQueue->Array[Idx];
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+extern __inline PQQ_ENTRY
+QQ_GetTail(
+    PQQ_CONTAINER pQueue,
+    unsigned int Idx)
+{
+    if(Idx >= atomic_read(&pQueue->EntryCnt))
+    {
+        return (PQQ_ENTRY) 0;
+    }
+
+    Idx += pQueue->Tail;
+    if(Idx >= pQueue->Size)
+    {
+        Idx = Idx - pQueue->Size;
+    }
+
+    return pQueue->Array[Idx];
+}
+
+#endif /* QQ_USE_MACROS */
+
+
+
+#endif /* QUEUE_H */
diff --git a/drivers/nicext.h b/drivers/nicext.h
new file mode 100644 (file)
index 0000000..5f2ec40
--- /dev/null
@@ -0,0 +1,110 @@
+/****************************************************************************
+ * Copyright(c) 2000-2001 Broadcom Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.          
+ *
+ * Name:        nicext.h
+ *
+ * Description: Broadcom Network Interface Card Extension (NICE) is an 
+ *              extension to Linux NET device kernel mode drivers. 
+ *              NICE is designed to provide additional functionalities, 
+ *              such as receive packet intercept. To support Broadcom NICE, 
+ *              the network device driver can be modified by adding an 
+ *              device ioctl handler and by indicating receiving packets 
+ *              to the NICE receive handler. Broadcom NICE will only be 
+ *              enabled by a NICE-aware intermediate driver, such as 
+ *              Broadcom Advanced Server Program Driver (BASP). When NICE 
+ *              is not enabled, the modified network device drivers 
+ *              functions exactly as other non-NICE aware drivers.
+ *
+ * Author:      Frankie Fan
+ *
+ * Created:     September 17, 2000
+ *
+ ****************************************************************************/
+#ifndef _nicext_h_
+#define _nicext_h_
+
+/*
+ * ioctl for NICE
+ */
+#define SIOCNICE                       SIOCDEVPRIVATE+7
+
+/*
+ * SIOCNICE: 
+ *
+ * The following structure needs to be less than IFNAMSIZ (16 bytes) because
+ * we're overloading ifreq.ifr_ifru.
+ *
+ * If 16 bytes is not enough, we should consider relaxing this because
+ * this is no field after ifr_ifru in the ifreq structure. But we may
+ * run into future compatiability problem in case of changing struct ifreq.
+ */
+struct nice_req
+{
+    __u32 cmd;
+    
+    union
+    {
+#ifdef __KERNEL__
+        /* cmd = NICE_CMD_SET_RX or NICE_CMD_GET_RX */
+        struct
+        {
+            void (*nrqus1_rx)( struct sk_buff*, void* );
+            void* nrqus1_ctx;
+        } nrqu_nrqus1;
+
+        /* cmd = NICE_CMD_QUERY_SUPPORT */
+        struct
+        {
+            __u32 nrqus2_magic;
+            __u32 nrqus2_support_rx:1;
+            __u32 nrqus2_support_vlan:1;
+            __u32 nrqus2_support_get_speed:1;
+        } nrqu_nrqus2;
+#endif
+
+        /* cmd = NICE_CMD_GET_SPEED */
+        struct
+        {
+            unsigned int nrqus3_speed; /* 0 if link is down, */
+                                       /* otherwise speed in Mbps */
+        } nrqu_nrqus3;
+
+        /* cmd = NICE_CMD_BLINK_LED */
+        struct
+        {
+            unsigned int nrqus4_blink_time; /* blink duration in seconds */
+        } nrqu_nrqus4;
+
+    } nrq_nrqu;
+};
+
+#define nrq_rx           nrq_nrqu.nrqu_nrqus1.nrqus1_rx
+#define nrq_ctx          nrq_nrqu.nrqu_nrqus1.nrqus1_ctx
+#define nrq_support_rx   nrq_nrqu.nrqu_nrqus2.nrqus2_support_rx
+#define nrq_magic        nrq_nrqu.nrqu_nrqus2.nrqus2_magic
+#define nrq_support_vlan nrq_nrqu.nrqu_nrqus2.nrqus2_support_vlan
+#define nrq_support_get_speed nrq_nrqu.nrqu_nrqus2.nrqus2_support_get_speed
+#define nrq_speed        nrq_nrqu.nrqu_nrqus3.nrqus3_speed
+#define nrq_blink_time   nrq_nrqu.nrqu_nrqus4.nrqus4_blink_time
+
+/*
+ * magic constants
+ */
+#define NICE_REQUESTOR_MAGIC            0x4543494E // NICE in ascii
+#define NICE_DEVICE_MAGIC               0x4E494345 // ECIN in ascii
+
+/*
+ * command field
+ */
+#define NICE_CMD_QUERY_SUPPORT          0x00000001
+#define NICE_CMD_SET_RX                 0x00000002
+#define NICE_CMD_GET_RX                 0x00000003
+#define NICE_CMD_GET_SPEED              0x00000004
+#define NICE_CMD_BLINK_LED              0x00000005
+
+#endif  // _nicext_h_ 
+
index 1a3babf337e8fe4a70a5cb613fd87cfc4a5fb06c..e2618a8ee79898d32cfd82ec16374a32a968dd5b 100644 (file)
@@ -39,9 +39,9 @@
 #include <pci.h>
 
 #ifdef DEBUG
-#define DBG(x...) printf(x)
+#define DEBUGF(x...) printf(x)
 #else
-#define DBG(x...)
+#define DEBUGF(x...)
 #endif /* DEBUG */
 
 /*
@@ -307,7 +307,7 @@ int pci_hose_config_device(struct pci_controller *hose,
        unsigned char pin;
        int bar, found_mem64;
 
-       DBG("PCI Config: I/O=0x%lx, Memory=0x%lx, Command=0x%lx\n", io, mem, command);
+       DEBUGF("PCI Config: I/O=0x%lx, Memory=0x%lx, Command=0x%lx\n", io, mem, command);
 
        pci_hose_write_config_dword(hose, dev, PCI_COMMAND, 0);
 
@@ -453,7 +453,7 @@ int pci_hose_scan_bus(struct pci_controller *hose, int bus)
                        if (!PCI_FUNC(dev))
                                found_multi = header_type & 0x80;
 
-                       DBG("PCI Scan: Found Bus %d, Device %d, Function %d\n",
+                       DEBUGF("PCI Scan: Found Bus %d, Device %d, Function %d\n",
                            PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev) );
 
                        pci_hose_read_config_word(hose, dev, PCI_DEVICE_ID, &device);
index 3112460ff43c9387213fc86fe0b3e33e2c36d485..d48d8d1af8ccb507558e9f58edf6eda9d8499aef 100644 (file)
@@ -21,9 +21,9 @@
 
 #undef DEBUG
 #ifdef DEBUG
-#define DBG(x...) printf(x)
+#define DEBUGF(x...) printf(x)
 #else
-#define DBG(x...)
+#define DEBUGF(x...)
 #endif /* DEBUG */
 
 #define        PCIAUTO_IDE_MODE_MASK           0x05
@@ -48,7 +48,7 @@ int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned
 
        if (!res)
        {
-               DBG("No resource");
+               DEBUGF("No resource");
                goto error;
        }
 
@@ -56,13 +56,13 @@ int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned
 
        if (addr - res->bus_start + size > res->size)
        {
-               DBG("No room in resource");
+               DEBUGF("No room in resource");
                goto error;
        }
 
        res->bus_lower = addr + size;
 
-       DBG("address=0x%lx", addr);
+       DEBUGF("address=0x%lx", addr);
 
        *bar = addr;
        return 0;
@@ -108,7 +108,7 @@ void pciauto_setup_device(struct pci_controller *hose,
                        bar_size = ~(bar_response & PCI_BASE_ADDRESS_IO_MASK) + 1;
                        bar_res = io;
 
-                       DBG("PCI Autoconfig: BAR %d, I/O, size=0x%x, ", bar_nr, bar_size);
+                       DEBUGF("PCI Autoconfig: BAR %d, I/O, size=0x%x, ", bar_nr, bar_size);
                }
                else
                {
@@ -119,7 +119,7 @@ void pciauto_setup_device(struct pci_controller *hose,
                        bar_size = ~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1;
                        bar_res = mem;
 
-                       DBG("PCI Autoconfig: BAR %d, Mem, size=0x%x, ", bar_nr, bar_size);
+                       DEBUGF("PCI Autoconfig: BAR %d, Mem, size=0x%x, ", bar_nr, bar_size);
                }
 
                if (pciauto_region_allocate(bar_res, bar_size, &bar_value) == 0)
@@ -142,7 +142,7 @@ void pciauto_setup_device(struct pci_controller *hose,
                                PCI_COMMAND_IO : PCI_COMMAND_MEMORY;
                }
 
-               DBG("\n");
+               DEBUGF("\n");
 
                bar_nr++;
        }
@@ -262,7 +262,7 @@ void pciauto_config_init(struct pci_controller *hose)
        {
                pciauto_region_init(hose->pci_mem);
 
-               DBG("PCI Autoconfig: Memory region: [%lx-%lx]\n", 
+               DEBUGF("PCI Autoconfig: Memory region: [%lx-%lx]\n", 
                    hose->pci_mem->bus_start, 
                    hose->pci_mem->bus_start + hose->pci_mem->size - 1);
        }
@@ -271,7 +271,7 @@ void pciauto_config_init(struct pci_controller *hose)
        {
                pciauto_region_init(hose->pci_io);
 
-               DBG("PCI Autoconfig: I/O region: [%lx-%lx]\n", 
+               DEBUGF("PCI Autoconfig: I/O region: [%lx-%lx]\n", 
                    hose->pci_io->bus_start, 
                    hose->pci_io->bus_start + hose->pci_io->size - 1);
        }
@@ -290,7 +290,7 @@ void pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)
        case PCI_CLASS_BRIDGE_PCI:
                pciauto_setup_device(hose, dev, 2, hose->pci_mem, hose->pci_io);
 
-               DBG("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_DEV(dev));
+               DEBUGF("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_DEV(dev));
 
                pciauto_prescan_setup_bridge(hose, dev, PCI_BUS(dev));
 
@@ -303,7 +303,7 @@ void pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)
                pci_hose_read_config_byte(hose, dev, PCI_CLASS_PROG, &prg_iface);
                if (!(prg_iface & PCIAUTO_IDE_MODE_MASK))
                        {
-                               DBG("PCI Autoconfig: Skipping legacy mode IDE controller\n");
+                               DEBUGF("PCI Autoconfig: Skipping legacy mode IDE controller\n");
                                return;
                        }
 
diff --git a/drivers/tigon3.c b/drivers/tigon3.c
new file mode 100644 (file)
index 0000000..7e1376e
--- /dev/null
@@ -0,0 +1,6221 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/******************************************************************************/
+#if !defined(CONFIG_NET_MULTI)
+#include <ppcboot.h>
+#include "bcm570x_mm.h"
+#include <asm/types.h>
+#ifdef CONFIG_BMW
+#include <mpc824x.h>
+#endif
+#include <malloc.h>
+#include <linux/byteorder/big_endian.h>
+
+#define EMBEDDED 1
+/******************************************************************************/
+/* Local functions. */
+/******************************************************************************/
+
+LM_STATUS LM_Abort(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_QueueRxPackets(PLM_DEVICE_BLOCK pDevice);
+
+static LM_STATUS LM_TranslateRequestedMediaType(
+    LM_REQUESTED_MEDIA_TYPE RequestedMediaType,
+    PLM_MEDIA_TYPE pMediaType, PLM_LINE_SPEED pLineSpeed,
+    PLM_DUPLEX_MODE pDuplexMode);
+
+static LM_STATUS LM_InitBcm540xPhy(PLM_DEVICE_BLOCK pDevice);
+
+__inline static LM_VOID LM_ServiceRxInterrupt(PLM_DEVICE_BLOCK pDevice);
+__inline static LM_VOID LM_ServiceTxInterrupt(PLM_DEVICE_BLOCK pDevice);
+
+static LM_STATUS LM_ForceAutoNegBcm540xPhy(PLM_DEVICE_BLOCK pDevice, 
+    LM_REQUESTED_MEDIA_TYPE RequestedMediaType);
+static LM_STATUS LM_ForceAutoNeg(PLM_DEVICE_BLOCK pDevice, 
+    LM_REQUESTED_MEDIA_TYPE RequestedMediaType);
+static LM_UINT32 GetPhyAdFlowCntrlSettings(PLM_DEVICE_BLOCK pDevice);
+STATIC LM_STATUS LM_SetFlowControl(PLM_DEVICE_BLOCK pDevice,
+    LM_UINT32 LocalPhyAd, LM_UINT32 RemotePhyAd);
+#if 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 PLM_ADAPTER_INFO LM_GetAdapterInfoBySsid(LM_UINT16 Svid, LM_UINT16 Ssid);
+STATIC LM_STATUS LM_DmaTest(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pBufferVirt,
+           LM_PHYSICAL_ADDRESS BufferPhy, LM_UINT32 BufferSize);
+STATIC LM_STATUS LM_HaltCpu(PLM_DEVICE_BLOCK pDevice,LM_UINT32 cpu_number);
+STATIC LM_STATUS LM_ResetChip(PLM_DEVICE_BLOCK pDevice);
+STATIC LM_STATUS LM_Test4GBoundary(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket,
+    PT3_SND_BD pSendBd);
+
+/******************************************************************************/
+/* External functions. */
+/******************************************************************************/
+
+LM_STATUS LM_LoadRlsFirmware(PLM_DEVICE_BLOCK pDevice);
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_UINT32
+LM_RegRdInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 Register) {
+    LM_UINT32 Value32;
+
+#if PCIX_TARGET_WORKAROUND
+    MM_ACQUIRE_UNDI_LOCK(pDevice);
+#endif
+    MM_WriteConfig32(pDevice, T3_PCI_REG_ADDR_REG, Register);
+    MM_ReadConfig32(pDevice, T3_PCI_REG_DATA_REG, &Value32);
+#if PCIX_TARGET_WORKAROUND
+    MM_RELEASE_UNDI_LOCK(pDevice);
+#endif
+
+    return Value32;
+} /* LM_RegRdInd */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_VOID
+LM_RegWrInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 Register,
+LM_UINT32 Value32) {
+
+#if PCIX_TARGET_WORKAROUND
+    MM_ACQUIRE_UNDI_LOCK(pDevice);
+#endif
+    MM_WriteConfig32(pDevice, T3_PCI_REG_ADDR_REG, Register);
+    MM_WriteConfig32(pDevice, T3_PCI_REG_DATA_REG, Value32);
+#if PCIX_TARGET_WORKAROUND
+    MM_RELEASE_UNDI_LOCK(pDevice);
+#endif
+} /* LM_RegWrInd */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_UINT32
+LM_MemRdInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 MemAddr) {
+    LM_UINT32 Value32;
+
+    MM_ACQUIRE_UNDI_LOCK(pDevice);
+#ifdef BIG_ENDIAN_HOST
+    MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr);
+    Value32 = REG_RD(pDevice, PciCfg.MemWindowData);
+    /*    Value32 = REG_RD(pDevice,uIntMem.Mbuf[(MemAddr & 0x7fff)/4]); */
+#else
+    MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr);
+    MM_ReadConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, &Value32);
+#endif
+    MM_RELEASE_UNDI_LOCK(pDevice);
+
+    return Value32;
+} /* LM_MemRdInd */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_VOID
+LM_MemWrInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 MemAddr,
+LM_UINT32 Value32) {
+    MM_ACQUIRE_UNDI_LOCK(pDevice);
+#ifdef BIG_ENDIAN_HOST
+    REG_WR(pDevice,PciCfg.MemWindowBaseAddr,MemAddr);
+    REG_WR(pDevice,uIntMem.Mbuf[(MemAddr & 0x7fff)/4],Value32);
+#else
+    MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr);
+    MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, Value32);
+#endif
+    MM_RELEASE_UNDI_LOCK(pDevice);
+} /* LM_MemWrInd */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_QueueRxPackets(
+PLM_DEVICE_BLOCK pDevice) {
+    LM_STATUS Lmstatus;
+    PLM_PACKET pPacket;
+    PT3_RCV_BD pRcvBd;
+    LM_UINT32 StdBdAdded = 0;
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    LM_UINT32 JumboBdAdded = 0;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    Lmstatus = LM_STATUS_SUCCESS;
+
+    pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+    while(pPacket) {
+        switch(pPacket->u.Rx.RcvProdRing) {
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+            case T3_JUMBO_RCV_PROD_RING:        /* Jumbo Receive Ring. */
+                /* Initialize the buffer descriptor. */
+                pRcvBd = 
+                    &pDevice->pRxJumboBdVirt[pDevice->RxJumboProdIdx];
+                pRcvBd->Flags = RCV_BD_FLAG_END | RCV_BD_FLAG_JUMBO_RING;
+                pRcvBd->Len = (LM_UINT16) pDevice->RxJumboBufferSize;
+
+                /* Initialize the receive buffer pointer */
+#if 0 /* Jimmy, deleted in new */
+                pRcvBd->HostAddr.Low = pPacket->u.Rx.RxBufferPhy.Low;
+                pRcvBd->HostAddr.High = pPacket->u.Rx.RxBufferPhy.High;
+#endif
+                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));
+
+                /* Update the producer index. */
+                pDevice->RxJumboProdIdx = (pDevice->RxJumboProdIdx + 1) & 
+                    T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK;
+
+                JumboBdAdded++;
+                break;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+            case T3_STD_RCV_PROD_RING:      /* Standard Receive Ring. */
+                /* Initialize the buffer descriptor. */
+                pRcvBd = &pDevice->pRxStdBdVirt[pDevice->RxStdProdIdx];
+                pRcvBd->Flags = RCV_BD_FLAG_END;
+                pRcvBd->Len = MAX_STD_RCV_BUFFER_SIZE;
+
+                /* Initialize the receive buffer pointer */
+#if 0  /* Jimmy, deleted in new replaced with MM_MapRxDma */
+                pRcvBd->HostAddr.Low = pPacket->u.Rx.RxBufferPhy.Low;
+                pRcvBd->HostAddr.High = pPacket->u.Rx.RxBufferPhy.High;
+#endif
+                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));
+
+                /* Update the producer index. */
+                pDevice->RxStdProdIdx = (pDevice->RxStdProdIdx + 1) & 
+                    T3_STD_RCV_RCB_ENTRY_COUNT_MASK;
+
+                StdBdAdded++;
+                break;
+
+            case T3_UNKNOWN_RCV_PROD_RING:
+            default:
+                Lmstatus = LM_STATUS_FAILURE;
+                break;
+        } /* switch */
+
+        /* Bail out if there is any error. */
+        if(Lmstatus != LM_STATUS_SUCCESS)
+        {
+            break;
+        }
+
+        pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+    } /* while */
+
+    wmb();
+    /* Update the procedure index. */
+    if(StdBdAdded)
+    {
+        MB_REG_WR(pDevice, Mailbox.RcvStdProdIdx.Low, pDevice->RxStdProdIdx);
+    }
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    if(JumboBdAdded)
+    {
+        MB_REG_WR(pDevice, Mailbox.RcvJumboProdIdx.Low,
+            pDevice->RxJumboProdIdx);
+    }
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    return Lmstatus;
+} /* LM_QueueRxPackets */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_VOID
+LM_NvramInit(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32;
+    LM_UINT32 j;
+
+    /* Intialize clock period and state machine. */
+    Value32 = SEEPROM_ADDR_CLK_PERD(SEEPROM_CLOCK_PERIOD) |
+        SEEPROM_ADDR_FSM_RESET;
+    REG_WR(pDevice, Grc.EepromAddr, Value32);
+
+    for(j = 0; j < 100; j++)
+    {
+        MM_Wait(10);
+    }
+
+    /* Serial eeprom access using the Grc.EepromAddr/EepromData registers. */
+    Value32 = REG_RD(pDevice, Grc.LocalCtrl);
+    REG_WR(pDevice, Grc.LocalCtrl, Value32 | GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM);
+
+    /* Set the 5701 compatibility mode if we are using EEPROM. */
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 &&
+        T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701)
+    {
+        Value32 = REG_RD(pDevice, Nvram.Config1);
+        if((Value32 & FLASH_INTERFACE_ENABLE) == 0)
+        {
+            /* Use the new interface to read EEPROM. */
+            Value32 &= ~FLASH_COMPAT_BYPASS;
+
+            REG_WR(pDevice, Nvram.Config1, Value32);
+        }
+    }
+} /* LM_NvRamInit */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_EepromRead(
+    PLM_DEVICE_BLOCK pDevice,
+    LM_UINT32 Offset,
+    LM_UINT32 *pData)
+{
+    LM_UINT32 Value32;
+    LM_UINT32 Addr;
+    LM_UINT32 Dev;
+    LM_UINT32 j;
+
+    if(Offset > SEEPROM_CHIP_SIZE)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    Dev = Offset / SEEPROM_CHIP_SIZE;
+    Addr = Offset % SEEPROM_CHIP_SIZE;
+    
+    Value32 = REG_RD(pDevice, Grc.EepromAddr);
+    Value32 &= ~(SEEPROM_ADDR_ADDRESS_MASK | SEEPROM_ADDR_DEV_ID_MASK |
+        SEEPROM_ADDR_RW_MASK);
+    REG_WR(pDevice, Grc.EepromAddr, Value32 | SEEPROM_ADDR_DEV_ID(Dev) |
+        SEEPROM_ADDR_ADDRESS(Addr) | SEEPROM_ADDR_START | SEEPROM_ADDR_READ);
+
+    for(j = 0; j < 1000; j++)
+    {
+        Value32 = REG_RD(pDevice, Grc.EepromAddr);
+        if(Value32 & SEEPROM_ADDR_COMPLETE)
+        {
+            break;
+        }
+        MM_Wait(10);
+    }
+
+    if(Value32 & SEEPROM_ADDR_COMPLETE)
+    {
+        Value32 = REG_RD(pDevice, Grc.EepromData);
+        *pData = Value32;
+
+        return LM_STATUS_SUCCESS;
+    }
+
+    return LM_STATUS_FAILURE;
+} /* LM_EepromRead */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_NvramRead(
+    PLM_DEVICE_BLOCK pDevice,
+    LM_UINT32 Offset,
+    LM_UINT32 *pData)
+{
+    LM_UINT32 Value32;
+    LM_STATUS Status;
+    LM_UINT32 j;
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+        T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+    {
+        Status = LM_EepromRead(pDevice, Offset, pData);
+    }
+    else
+    {
+        /* Determine if we have flash or EEPROM. */
+        Value32 = REG_RD(pDevice, Nvram.Config1);
+        if(Value32 & FLASH_INTERFACE_ENABLE)
+        {
+            if(Value32 & FLASH_SSRAM_BUFFERRED_MODE)
+            {
+                Offset = ((Offset/BUFFERED_FLASH_PAGE_SIZE) <<
+                    BUFFERED_FLASH_PAGE_POS) +
+                    (Offset % BUFFERED_FLASH_PAGE_SIZE);
+            }
+        }
+
+        REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_SET1);
+        for (j = 0; j < 1000; j++)
+        {
+            if (REG_RD(pDevice, Nvram.SwArb) & SW_ARB_GNT1)
+            {
+                break;
+            }
+            MM_Wait(20);
+        }
+        if (j == 1000)
+        {
+            return LM_STATUS_FAILURE;
+        }
+
+        /* Read from flash or EEPROM with the new 5703/02 interface. */
+        REG_WR(pDevice, Nvram.Addr, Offset & NVRAM_ADDRESS_MASK);
+
+        REG_WR(pDevice, Nvram.Cmd, NVRAM_CMD_RD | NVRAM_CMD_DO_IT |
+            NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE);
+
+        /* Wait for the done bit to clear. */
+        for(j = 0; j < 500; j++)
+        {
+            MM_Wait(10);
+
+            Value32 = REG_RD(pDevice, Nvram.Cmd);
+            if(!(Value32 & NVRAM_CMD_DONE))
+            {
+                break;
+            }
+        }
+        
+        /* Wait for the done bit. */
+        if(!(Value32 & NVRAM_CMD_DONE))
+        {
+            for(j = 0; j < 500; j++)
+            {
+                MM_Wait(10);
+
+                Value32 = REG_RD(pDevice, Nvram.Cmd);
+                if(Value32 & NVRAM_CMD_DONE)
+                {
+                    MM_Wait(10);
+
+                    *pData = REG_RD(pDevice, Nvram.ReadData);
+
+                    /* Change the endianess. */
+                    *pData = ((*pData & 0xff) << 24)| ((*pData & 0xff00) << 8)|
+                        ((*pData & 0xff0000) >> 8) | ((*pData >> 24) & 0xff);
+
+                    break;
+                }
+            }
+        }
+
+        REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_CLR1);
+        if(Value32 & NVRAM_CMD_DONE)
+        {
+            Status = LM_STATUS_SUCCESS;
+        }
+        else
+        {
+            Status = LM_STATUS_FAILURE;
+        }
+    }
+
+    return Status;
+} /* LM_NvramRead */
+
+
+STATIC void
+LM_ReadVPD(PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Vpd_arr[256/4];
+    LM_UINT8 *Vpd = (LM_UINT8 *) &Vpd_arr[0];
+    LM_UINT32 *Vpd_dptr = &Vpd_arr[0];
+    LM_UINT32 Value32;
+    unsigned int j;
+
+    /* Read PN from VPD */
+    for (j = 0; j < 256; j += 4, Vpd_dptr++ )
+    {
+        if (LM_NvramRead(pDevice, 0x100 + j, &Value32) != LM_STATUS_SUCCESS) {
+            printf("BCM570x: LM_ReadVPD: VPD read failed"
+                  " (no EEPROM onboard)\n");
+            return;
+        }
+        *Vpd_dptr = cpu_to_le32(Value32);
+    }
+    for (j = 0; j < 256; )
+    {
+        unsigned int Vpd_r_len;
+        unsigned int Vpd_r_end;
+
+        if ((Vpd[j] == 0x82) || (Vpd[j] == 0x91))
+        {
+            j = j + 3 + Vpd[j + 1] + (Vpd[j + 2] << 8);
+        }
+        else if (Vpd[j] == 0x90)
+        {
+            Vpd_r_len =  Vpd[j + 1] + (Vpd[j + 2] << 8);
+            j += 3;
+            Vpd_r_end = Vpd_r_len + j;
+            while (j < Vpd_r_end)
+            {
+                if ((Vpd[j] == 'P') && (Vpd[j + 1] == 'N'))
+                {
+                    unsigned int len = Vpd[j + 2];
+
+                    if (len <= 24)
+                    {
+                        memcpy(pDevice->PartNo, &Vpd[j + 3], len);
+                    }
+                    break;
+                }
+                else
+                {
+                    if (Vpd[j + 2] == 0)
+                    {
+                        break;
+                    }
+                    j = j + Vpd[j + 2];
+                }
+            }
+            break;
+        }
+        else {
+            break;
+        }
+    }
+}
+
+STATIC void
+LM_ReadBootCodeVersion(PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32, offset, ver_offset;
+    int i;
+
+    if (LM_NvramRead(pDevice, 0x0, &Value32) != LM_STATUS_SUCCESS)
+        return;
+    if (Value32 != 0xaa559966)
+        return;
+    if (LM_NvramRead(pDevice, 0xc, &offset) != LM_STATUS_SUCCESS)
+        return;
+
+    offset = ((offset & 0xff) << 24)| ((offset & 0xff00) << 8)|
+        ((offset & 0xff0000) >> 8) | ((offset >> 24) & 0xff);
+    if (LM_NvramRead(pDevice, offset, &Value32) != LM_STATUS_SUCCESS)
+        return;
+    if ((Value32 == 0x0300000e) &&
+        (LM_NvramRead(pDevice, offset + 4, &Value32) == LM_STATUS_SUCCESS) &&
+        (Value32 == 0)) {
+
+        if (LM_NvramRead(pDevice, offset + 8, &ver_offset) != LM_STATUS_SUCCESS)
+            return;
+        ver_offset = ((ver_offset & 0xff0000) >> 8) |
+            ((ver_offset >> 24) & 0xff);
+        for (i = 0; i < 16; i += 4) {
+            if (LM_NvramRead(pDevice, offset + ver_offset + i, &Value32) !=
+                LM_STATUS_SUCCESS)
+            {
+                return;
+            }
+            *((LM_UINT32 *) &pDevice->BootCodeVer[i]) = cpu_to_le32(Value32);
+        }
+    }
+    else {
+        char c;
+
+        if (LM_NvramRead(pDevice, 0x94, &Value32) != LM_STATUS_SUCCESS)
+            return;
+
+        i = 0;
+        c = ((Value32 & 0xff0000) >> 16);
+
+        if (c < 10) {
+            pDevice->BootCodeVer[i++] = c + '0';
+        }
+        else {
+            pDevice->BootCodeVer[i++] = (c / 10) + '0';
+            pDevice->BootCodeVer[i++] = (c % 10) + '0';
+        }
+        pDevice->BootCodeVer[i++] = '.';
+        c = (Value32 & 0xff000000) >> 24;
+        if (c < 10) {
+            pDevice->BootCodeVer[i++] = c + '0';
+        }
+        else {
+            pDevice->BootCodeVer[i++] = (c / 10) + '0';
+            pDevice->BootCodeVer[i++] = (c % 10) + '0';
+        }
+        pDevice->BootCodeVer[i] = 0;
+    }
+}
+
+STATIC void
+LM_GetBusSpeed(PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 PciState = pDevice->PciState;
+    LM_UINT32 ClockCtrl;
+    char *SpeedStr = "";
+
+    if (PciState & T3_PCI_STATE_32BIT_PCI_BUS)
+    {
+        strcpy(pDevice->BusSpeedStr, "32-bit ");
+    }
+    else
+    {
+        strcpy(pDevice->BusSpeedStr, "64-bit ");
+    }
+    if (PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)
+    {
+        strcat(pDevice->BusSpeedStr, "PCI ");
+        if (PciState & T3_PCI_STATE_HIGH_BUS_SPEED) 
+        {
+            SpeedStr = "66MHz";
+        }
+        else
+        {
+            SpeedStr = "33MHz";
+        }
+    }
+    else
+    {
+        strcat(pDevice->BusSpeedStr, "PCIX ");
+        if (pDevice->BondId == GRC_MISC_BD_ID_5704CIOBE)
+        {
+            SpeedStr = "133MHz";
+        }
+        else
+        {
+            ClockCtrl = REG_RD(pDevice, PciCfg.ClockCtrl) & 0x1f;
+            switch (ClockCtrl)
+            {
+            case 0:
+                SpeedStr = "33MHz";
+                break;
+
+            case 2:
+                SpeedStr = "50MHz";
+                break;
+
+            case 4:
+                SpeedStr = "66MHz";
+                break;
+
+            case 6:
+                SpeedStr = "100MHz";
+                break;
+
+            case 7:
+                SpeedStr = "133MHz";
+                break;
+            }
+        }
+    }
+    strcat(pDevice->BusSpeedStr, SpeedStr);
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine initializes default parameters and reads the PCI           */
+/*    configurations.                                                         */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_GetAdapterInfo(
+PLM_DEVICE_BLOCK pDevice)
+{
+    PLM_ADAPTER_INFO pAdapterInfo;
+    LM_UINT32 Value32;
+    LM_STATUS Status;
+    LM_UINT32 j;
+    LM_UINT32 EeSigFound;
+    LM_UINT32 EePhyTypeSerdes = 0;
+    LM_UINT32 EePhyLedMode = 0;
+    LM_UINT32 EePhyId = 0;
+
+    /* Get Device Id and Vendor Id */
+    Status = MM_ReadConfig32(pDevice, PCI_VENDOR_ID_REG, &Value32);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    pDevice->PciVendorId = (LM_UINT16) Value32;
+    pDevice->PciDeviceId = (LM_UINT16) (Value32 >> 16);
+
+    /* If we are not getting the write adapter, exit. */
+    if((Value32 != T3_PCI_ID_BCM5700) && 
+       (Value32 != T3_PCI_ID_BCM5701) &&
+       (Value32 != T3_PCI_ID_BCM5702) &&
+       (Value32 != T3_PCI_ID_BCM5702x) &&
+       (Value32 != T3_PCI_ID_BCM5702FE) &&
+       (Value32 != T3_PCI_ID_BCM5703) &&
+       (Value32 != T3_PCI_ID_BCM5703x) &&
+       (Value32 != T3_PCI_ID_BCM5704))
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    Status = MM_ReadConfig32(pDevice, PCI_REV_ID_REG, &Value32);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    pDevice->PciRevId = (LM_UINT8) Value32;
+
+    /* Get IRQ. */
+    Status = MM_ReadConfig32(pDevice, PCI_INT_LINE_REG, &Value32);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    pDevice->Irq = (LM_UINT8) Value32;
+
+    /* Get interrupt pin. */
+    pDevice->IntPin = (LM_UINT8) (Value32 >> 8);
+
+    /* Get chip revision id. */
+    Status = MM_ReadConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, &Value32);
+    pDevice->ChipRevId = Value32 >> 16;
+
+    /* Get subsystem vendor. */
+    Status = MM_ReadConfig32(pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, &Value32);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    pDevice->SubsystemVendorId = (LM_UINT16) Value32;
+
+    /* Get PCI subsystem id. */
+    pDevice->SubsystemId = (LM_UINT16) (Value32 >> 16);
+
+    /* Get the cache line size. */
+    MM_ReadConfig32(pDevice, PCI_CACHE_LINE_SIZE_REG, &Value32);
+    pDevice->CacheLineSize = (LM_UINT8) Value32;
+    pDevice->SavedCacheLineReg = Value32;
+
+    if(pDevice->ChipRevId != T3_CHIP_ID_5703_A1 &&
+        pDevice->ChipRevId != T3_CHIP_ID_5703_A2 &&
+        pDevice->ChipRevId != T3_CHIP_ID_5704_A0)
+    {
+        pDevice->UndiFix = FALSE;
+    }
+#if !PCIX_TARGET_WORKAROUND
+    pDevice->UndiFix = FALSE;
+#endif
+    /* Map the memory base to system address space. */
+    if (!pDevice->UndiFix)
+    {
+        Status = MM_MapMemBase(pDevice);
+        if(Status != LM_STATUS_SUCCESS)
+        {
+            return Status;
+        }
+        /* Initialize the memory view pointer. */
+        pDevice->pMemView = (PT3_STD_MEM_MAP) pDevice->pMappedMemBase;
+    }
+
+#if PCIX_TARGET_WORKAROUND
+    /* store whether we are in PCI are PCI-X mode */
+    pDevice->EnablePciXFix = FALSE;
+
+    MM_ReadConfig32(pDevice, T3_PCI_STATE_REG, &Value32);
+    if((Value32 & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) == 0)
+    {
+        /* Enable PCI-X workaround only if we are running on 5700 BX. */
+        if(T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_BX)
+        {
+            pDevice->EnablePciXFix = TRUE;
+        }
+    }
+    if (pDevice->UndiFix)
+    {
+        pDevice->EnablePciXFix = TRUE;
+    }
+#endif
+    /* Bx bug: due to the "byte_enable bug" in PCI-X mode, the power */
+    /* management register may be clobbered which may cause the */
+    /* BCM5700 to go into D3 state.  While in this state, we will */
+    /* not have memory mapped register access.  As a workaround, we */
+    /* need to restore the device to D0 state. */
+    MM_ReadConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, &Value32);
+    Value32 |= T3_PM_PME_ASSERTED;
+    Value32 &= ~T3_PM_POWER_STATE_MASK;
+    Value32 |= T3_PM_POWER_STATE_D0;
+    MM_WriteConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, Value32);
+
+    /* read the current PCI command word */
+    MM_ReadConfig32(pDevice, PCI_COMMAND_REG, &Value32);
+
+    /* Make sure bus-mastering is enabled. */
+    Value32 |= PCI_BUSMASTER_ENABLE;
+
+#if PCIX_TARGET_WORKAROUND
+    /* if we are in PCI-X mode, also make sure mem-mapping and SERR#/PERR#
+        are enabled */
+    if (pDevice->EnablePciXFix == TRUE) {
+        Value32 |= (PCI_MEM_SPACE_ENABLE | PCI_SYSTEM_ERROR_ENABLE | 
+                    PCI_PARITY_ERROR_ENABLE);
+    }
+    if (pDevice->UndiFix)
+    {
+        Value32 &= ~PCI_MEM_SPACE_ENABLE;
+    }
+
+#endif
+
+    if(pDevice->EnableMWI)
+    {
+        Value32 |= PCI_MEMORY_WRITE_INVALIDATE;
+    }
+    else {
+        Value32 &= (~PCI_MEMORY_WRITE_INVALIDATE);
+    }
+
+    /* Error out if mem-mapping is NOT enabled for PCI systems */
+    if (!(Value32 | PCI_MEM_SPACE_ENABLE))
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    /* save the value we are going to write into the PCI command word */       
+    pDevice->PciCommandStatusWords = Value32;  
+
+    Status = MM_WriteConfig32(pDevice, PCI_COMMAND_REG, Value32);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+
+    /* Set power state to D0. */
+    LM_SetPowerState(pDevice, LM_POWER_STATE_D0);
+
+#ifdef BIG_ENDIAN_PCI
+    pDevice->MiscHostCtrl = 
+        MISC_HOST_CTRL_MASK_PCI_INT | 
+        MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS |
+        MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP |
+        MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW;
+#else /* No CPU Swap modes for PCI IO */
+    
+    /* 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;
+#endif /* !BIG_ENDIAN_PCI */
+
+    /* write to PCI misc host ctr first in order to enable indirect accesses */
+    MM_WriteConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, pDevice->MiscHostCtrl);
+
+    REG_WR(pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl);
+
+#ifdef BIG_ENDIAN_PCI
+    Value32 = GRC_MODE_WORD_SWAP_DATA|
+             GRC_MODE_WORD_SWAP_NON_FRAME_DATA;
+#else
+/* No CPU Swap modes for PCI IO */    
+#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
+#endif /* !BIG_ENDIAN_PCI */
+    
+    REG_WR(pDevice, Grc.Mode, Value32);
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+    {
+        REG_WR(pDevice, Grc.LocalCtrl, GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 |
+            GRC_MISC_LOCAL_CTRL_GPIO_OE1);
+    }
+    MM_Wait(40);
+
+    /* Enable indirect memory access */
+    REG_WR(pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE);
+
+    if (REG_RD(pDevice, PciCfg.ClockCtrl) & T3_PCI_44MHZ_CORE_CLOCK)
+    {
+        REG_WR(pDevice, PciCfg.ClockCtrl, T3_PCI_44MHZ_CORE_CLOCK |
+                T3_PCI_SELECT_ALTERNATE_CLOCK);
+        REG_WR(pDevice, PciCfg.ClockCtrl, T3_PCI_SELECT_ALTERNATE_CLOCK);
+        MM_Wait(40);  /* required delay is 27usec */
+    }
+    REG_WR(pDevice, PciCfg.ClockCtrl, 0);
+    REG_WR(pDevice, PciCfg.MemWindowBaseAddr, 0);
+
+#if PCIX_TARGET_WORKAROUND
+    MM_ReadConfig32(pDevice, T3_PCI_STATE_REG, &Value32);
+    if ((pDevice->EnablePciXFix == FALSE) &&
+        ((Value32 & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) == 0))
+    {
+        if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+            pDevice->ChipRevId == T3_CHIP_ID_5701_B0 ||
+            pDevice->ChipRevId == T3_CHIP_ID_5701_B2 ||
+            pDevice->ChipRevId == T3_CHIP_ID_5701_B5)
+        {
+            __raw_writel(0, &(pDevice->pMemView->uIntMem.MemBlock32K[0x300]));
+            __raw_writel(0, &(pDevice->pMemView->uIntMem.MemBlock32K[0x301]));
+            __raw_writel(0xffffffff, &(pDevice->pMemView->uIntMem.MemBlock32K[0x301]));
+            if (__raw_readl(&(pDevice->pMemView->uIntMem.MemBlock32K[0x300])))
+            {
+                pDevice->EnablePciXFix = TRUE;
+            }
+        }
+    }
+#endif
+#if 1
+    /* 
+    *  This code was at the beginning of else block below, but that's
+    *  a bug if node address in shared memory.
+    */
+    MM_Wait(50);
+    LM_NvramInit(pDevice);
+#endif
+    /* Get the node address.  First try to get in from the shared memory. */
+    /* If the signature is not present, then get it from the NVRAM. */
+    Value32 = MEM_RD_OFFSET(pDevice, T3_MAC_ADDR_HIGH_MAILBOX);
+    if((Value32 >> 16) == 0x484b)
+    {
+
+        pDevice->NodeAddress[0] = (LM_UINT8) (Value32 >> 8);
+        pDevice->NodeAddress[1] = (LM_UINT8) Value32;
+
+        Value32 = MEM_RD_OFFSET(pDevice, T3_MAC_ADDR_LOW_MAILBOX);
+
+        pDevice->NodeAddress[2] = (LM_UINT8) (Value32 >> 24);
+        pDevice->NodeAddress[3] = (LM_UINT8) (Value32 >> 16);
+        pDevice->NodeAddress[4] = (LM_UINT8) (Value32 >> 8);
+        pDevice->NodeAddress[5] = (LM_UINT8) Value32;
+
+        Status = LM_STATUS_SUCCESS;
+    }
+    else
+    {
+        Status = LM_NvramRead(pDevice, 0x7c, &Value32);
+        if(Status == LM_STATUS_SUCCESS)
+        {
+            pDevice->NodeAddress[0] = (LM_UINT8) (Value32 >> 16);
+            pDevice->NodeAddress[1] = (LM_UINT8) (Value32 >> 24);
+
+            Status = LM_NvramRead(pDevice, 0x80, &Value32);
+
+            pDevice->NodeAddress[2] = (LM_UINT8) Value32;
+            pDevice->NodeAddress[3] = (LM_UINT8) (Value32 >> 8);
+            pDevice->NodeAddress[4] = (LM_UINT8) (Value32 >> 16);
+            pDevice->NodeAddress[5] = (LM_UINT8) (Value32 >> 24);
+        }
+    }
+
+    /* Assign a default address. */
+    if(Status != LM_STATUS_SUCCESS)
+    {
+#ifndef EMBEDDED
+        printk(KERN_ERR "Cannot get MAC addr from NVRAM. Using default.\n");
+#endif
+        pDevice->NodeAddress[0] = 0x00; pDevice->NodeAddress[1] = 0x10;
+        pDevice->NodeAddress[2] = 0x18; pDevice->NodeAddress[3] = 0x68;
+        pDevice->NodeAddress[4] = 0x61; pDevice->NodeAddress[5] = 0x76;
+    }
+
+    pDevice->PermanentNodeAddress[0] = pDevice->NodeAddress[0];
+    pDevice->PermanentNodeAddress[1] = pDevice->NodeAddress[1];
+    pDevice->PermanentNodeAddress[2] = pDevice->NodeAddress[2];
+    pDevice->PermanentNodeAddress[3] = pDevice->NodeAddress[3];
+    pDevice->PermanentNodeAddress[4] = pDevice->NodeAddress[4];
+    pDevice->PermanentNodeAddress[5] = pDevice->NodeAddress[5];
+
+    /* Initialize the default values. */
+    pDevice->NoTxPseudoHdrChksum = FALSE;
+    pDevice->NoRxPseudoHdrChksum = FALSE;
+    pDevice->NicSendBd = FALSE;
+    pDevice->TxPacketDescCnt = DEFAULT_TX_PACKET_DESC_COUNT;
+    pDevice->RxStdDescCnt = DEFAULT_STD_RCV_DESC_COUNT;
+    pDevice->RxCoalescingTicks = DEFAULT_RX_COALESCING_TICKS;
+    pDevice->TxCoalescingTicks = DEFAULT_TX_COALESCING_TICKS;
+    pDevice->RxMaxCoalescedFrames = DEFAULT_RX_MAX_COALESCED_FRAMES;
+    pDevice->TxMaxCoalescedFrames = DEFAULT_TX_MAX_COALESCED_FRAMES;
+    pDevice->RxCoalescingTicksDuringInt = BAD_DEFAULT_VALUE;
+    pDevice->TxCoalescingTicksDuringInt = BAD_DEFAULT_VALUE;
+    pDevice->RxMaxCoalescedFramesDuringInt = BAD_DEFAULT_VALUE;
+    pDevice->TxMaxCoalescedFramesDuringInt = BAD_DEFAULT_VALUE;
+    pDevice->StatsCoalescingTicks = DEFAULT_STATS_COALESCING_TICKS;
+    pDevice->EnableMWI = FALSE;
+    pDevice->TxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+    pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+    pDevice->DisableAutoNeg = FALSE;
+    pDevice->PhyIntMode = T3_PHY_INT_MODE_AUTO;
+    pDevice->LinkChngMode = T3_LINK_CHNG_MODE_AUTO;
+    pDevice->LedMode = LED_MODE_AUTO;
+    pDevice->ResetPhyOnInit = TRUE;
+    pDevice->DelayPciGrant = TRUE;
+    pDevice->UseTaggedStatus = FALSE;
+    pDevice->OneDmaAtOnce = BAD_DEFAULT_VALUE;
+
+    pDevice->DmaMbufLowMark = T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO;
+    pDevice->RxMacMbufLowMark = T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO;
+    pDevice->MbufHighMark = T3_DEF_MBUF_HIGH_WMARK_JUMBO;
+
+    pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_AUTO;
+    pDevice->TaskOffloadCap = LM_TASK_OFFLOAD_NONE;
+    pDevice->FlowControlCap = LM_FLOW_CONTROL_AUTO_PAUSE;
+    pDevice->EnableTbi = FALSE;
+#if INCLUDE_TBI_SUPPORT
+    pDevice->PollTbiLink = BAD_DEFAULT_VALUE;
+#endif
+
+    switch (T3_ASIC_REV(pDevice->ChipRevId))
+    {
+    case T3_ASIC_REV_5704:
+        pDevice->MbufBase = T3_NIC_MBUF_POOL_ADDR;
+        pDevice->MbufSize = T3_NIC_MBUF_POOL_SIZE64;
+        break;
+    default:
+        pDevice->MbufBase = T3_NIC_MBUF_POOL_ADDR;
+        pDevice->MbufSize = T3_NIC_MBUF_POOL_SIZE96;
+        break;
+    }
+
+    pDevice->LinkStatus = LM_STATUS_LINK_DOWN;
+    pDevice->QueueRxPackets = TRUE;
+
+    pDevice->EnableWireSpeed = TRUE;
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    /* Make this is a known adapter. */
+    pAdapterInfo = LM_GetAdapterInfoBySsid(pDevice->SubsystemVendorId,
+        pDevice->SubsystemId);
+
+    pDevice->BondId = REG_RD(pDevice, Grc.MiscCfg) & GRC_MISC_BD_ID_MASK;
+    if (pDevice->BondId != GRC_MISC_BD_ID_5700 &&
+        pDevice->BondId != GRC_MISC_BD_ID_5701 &&
+        pDevice->BondId != GRC_MISC_BD_ID_5702FE &&
+        pDevice->BondId != GRC_MISC_BD_ID_5703 &&
+        pDevice->BondId != GRC_MISC_BD_ID_5703S &&
+        pDevice->BondId != GRC_MISC_BD_ID_5704 &&
+        pDevice->BondId != GRC_MISC_BD_ID_5704CIOBE)
+    {
+        return LM_STATUS_UNKNOWN_ADAPTER;
+    }
+
+    pDevice->SplitModeEnable = SPLIT_MODE_DISABLE;
+    if ((pDevice->ChipRevId == T3_CHIP_ID_5704_A0) &&
+        (pDevice->BondId == GRC_MISC_BD_ID_5704CIOBE))
+    {
+        pDevice->SplitModeEnable = SPLIT_MODE_ENABLE;
+        pDevice->SplitModeMaxReq = SPLIT_MODE_5704_MAX_REQ;
+    }
+
+    /* Get Eeprom info. */
+    Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_SIG_ADDR);
+    if (Value32 == T3_NIC_DATA_SIG)
+    {
+        EeSigFound = TRUE;
+        Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_NIC_CFG_ADDR);
+
+        /* Determine PHY type. */
+        switch (Value32 & T3_NIC_CFG_PHY_TYPE_MASK)
+        {
+            case T3_NIC_CFG_PHY_TYPE_COPPER:
+                EePhyTypeSerdes = FALSE;
+                break;
+
+            case T3_NIC_CFG_PHY_TYPE_FIBER:
+                EePhyTypeSerdes = TRUE;
+                break;
+
+            default:
+                EePhyTypeSerdes = FALSE;
+                break;
+        }
+
+        /* Determine PHY led mode. */
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            switch(Value32 & T3_NIC_CFG_LED_MODE_MASK)
+            {
+                case T3_NIC_CFG_LED_MODE_TRIPLE_SPEED:
+                    EePhyLedMode = LED_MODE_THREE_LINK;
+                    break;
+
+                case T3_NIC_CFG_LED_MODE_LINK_SPEED:
+                    EePhyLedMode = LED_MODE_LINK10;
+                    break;
+
+                default:
+                    EePhyLedMode = LED_MODE_AUTO;
+                    break;
+            }
+        }
+        else
+        {
+            switch(Value32 & T3_NIC_CFG_LED_MODE_MASK)
+            {
+                case T3_NIC_CFG_LED_MODE_OPEN_DRAIN:
+                    EePhyLedMode = LED_MODE_OPEN_DRAIN;
+                    break;
+
+                case T3_NIC_CFG_LED_MODE_OUTPUT:
+                    EePhyLedMode = LED_MODE_OUTPUT;
+                    break;
+
+                default:
+                    EePhyLedMode = LED_MODE_AUTO;
+                    break;
+            }
+        }
+        if(pDevice->ChipRevId == T3_CHIP_ID_5703_A1 ||
+            pDevice->ChipRevId == T3_CHIP_ID_5703_A2)
+        {
+            /* Enable EEPROM write protection. */
+            if(Value32 & T3_NIC_EEPROM_WP)
+            {
+                pDevice->EepromWp = TRUE;
+            }
+        }
+
+        /* Get the PHY Id. */
+        Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_PHY_ID_ADDR);
+        if (Value32)
+        {
+            EePhyId = (((Value32 & T3_NIC_PHY_ID1_MASK) >> 16) &
+                PHY_ID1_OUI_MASK) << 10;
+
+            Value32 = Value32 & T3_NIC_PHY_ID2_MASK;
+
+            EePhyId |= ((Value32 & PHY_ID2_OUI_MASK) << 16) |
+              (Value32 & PHY_ID2_MODEL_MASK) | (Value32 & PHY_ID2_REV_MASK);
+        }
+        else
+        {
+            EePhyId = 0;
+        }
+    }
+    else
+    {
+        EeSigFound = FALSE;
+    }
+
+    /* Set the PHY address. */
+    pDevice->PhyAddr = PHY_DEVICE_ID;
+
+    /* Disable auto polling. */
+    pDevice->MiMode = 0xc0000;
+    REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+    MM_Wait(40);
+
+    /* Get the PHY id. */
+    LM_ReadPhy(pDevice, PHY_ID1_REG, &Value32);
+    pDevice->PhyId = (Value32 & PHY_ID1_OUI_MASK) << 10;
+
+    LM_ReadPhy(pDevice, PHY_ID2_REG, &Value32);
+    pDevice->PhyId |= ((Value32 & PHY_ID2_OUI_MASK) << 16) |
+      (Value32 & PHY_ID2_MODEL_MASK) | (Value32 & PHY_ID2_REV_MASK);
+
+    /* Set the EnableTbi flag to false if we have a copper PHY. */
+    switch(pDevice->PhyId & PHY_ID_MASK)
+    {
+        case PHY_BCM5400_PHY_ID:
+            pDevice->EnableTbi = FALSE;
+            break;
+
+        case PHY_BCM5401_PHY_ID:
+            pDevice->EnableTbi = FALSE;
+            break;
+
+        case PHY_BCM5411_PHY_ID:
+            pDevice->EnableTbi = FALSE;
+            break;
+
+        case PHY_BCM5701_PHY_ID:
+            pDevice->EnableTbi = FALSE;
+            break;
+
+        case PHY_BCM5703_PHY_ID:
+            pDevice->EnableTbi = FALSE;
+            break;
+
+        case PHY_BCM5704_PHY_ID:
+            pDevice->EnableTbi = FALSE;
+            break;
+
+        case PHY_BCM8002_PHY_ID:
+            pDevice->EnableTbi = TRUE;
+            break;
+
+        default:
+
+            if (pAdapterInfo)
+            {
+                pDevice->PhyId = pAdapterInfo->PhyId;
+                pDevice->EnableTbi = pAdapterInfo->Serdes;
+            }
+            else if (EeSigFound)
+            {
+                pDevice->PhyId = EePhyId;
+                pDevice->EnableTbi = EePhyTypeSerdes;
+            }
+            break;
+    }
+
+    /* Bail out if we don't know the copper PHY id. */
+    if(UNKNOWN_PHY_ID(pDevice->PhyId) && !pDevice->EnableTbi)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703)
+    {
+        if((pDevice->SavedCacheLineReg & 0xff00) < 0x4000)
+        {
+            pDevice->SavedCacheLineReg &= 0xffff00ff;
+            pDevice->SavedCacheLineReg |= 0x4000;
+        }
+    }
+    /* Change driver parameters. */
+    Status = MM_GetConfig(pDevice);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+
+#if INCLUDE_5701_AX_FIX
+    if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+        pDevice->ChipRevId == T3_CHIP_ID_5701_B0)
+    {
+        pDevice->ResetPhyOnInit = TRUE;
+    }
+#endif
+
+    /* Save the current phy link status. */
+    if(!pDevice->EnableTbi)
+    {
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+
+        /* If we don't have link reset the PHY. */
+        if(!(Value32 & PHY_STATUS_LINK_PASS) || pDevice->ResetPhyOnInit)
+        {
+
+            LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_PHY_RESET);
+
+            for(j = 0; j < 100; j++)
+            {
+                MM_Wait(10);
+
+                LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+                if(Value32 && !(Value32 & PHY_CTRL_PHY_RESET))
+                {
+                    MM_Wait(40);
+                    break;
+                }
+            }
+
+
+#if INCLUDE_5701_AX_FIX
+            /* 5701_AX_BX bug:  only advertises 10mb speed. */
+            if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+                pDevice->ChipRevId == T3_CHIP_ID_5701_B0)
+            {
+
+                Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD |
+                    PHY_AN_AD_10BASET_HALF | PHY_AN_AD_10BASET_FULL |
+                    PHY_AN_AD_100BASETX_FULL | PHY_AN_AD_100BASETX_HALF;
+                Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+                LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+                pDevice->advertising = Value32;
+
+                Value32 = BCM540X_AN_AD_1000BASET_HALF | 
+                    BCM540X_AN_AD_1000BASET_FULL | BCM540X_CONFIG_AS_MASTER |
+                    BCM540X_ENABLE_CONFIG_AS_MASTER;
+                LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, Value32);
+                pDevice->advertising1000 = Value32;
+
+                LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_AUTO_NEG_ENABLE |
+                    PHY_CTRL_RESTART_AUTO_NEG);
+            }
+#endif
+            if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703)
+            {
+                LM_WritePhy(pDevice, 0x18, 0x0c00);
+                LM_WritePhy(pDevice, 0x17, 0x201f);
+                LM_WritePhy(pDevice, 0x15, 0x2aaa);
+            }
+            if(pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+            {
+                LM_WritePhy(pDevice, 0x1c, 0x8d68);
+                LM_WritePhy(pDevice, 0x1c, 0x8d68);
+            }
+            /* Enable Ethernet@WireSpeed. */
+            if(pDevice->EnableWireSpeed)
+            {
+                LM_WritePhy(pDevice, 0x18, 0x7007);
+                LM_ReadPhy(pDevice, 0x18, &Value32);
+                LM_WritePhy(pDevice, 0x18, Value32 | BIT_15 | BIT_4);
+            }
+        }
+    }
+
+    /* Turn off tap power management. */
+    if((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
+    {
+        LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x0c20);
+        LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012);
+        LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1804);
+        LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013);
+        LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1204);
+        LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+        LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0132);
+        LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+        LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0232);
+        LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f);
+        LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0a20);
+
+        MM_Wait(40);
+    }
+
+#if INCLUDE_TBI_SUPPORT
+    pDevice->IgnoreTbiLinkChange = FALSE;
+
+    if(pDevice->EnableTbi)
+    {
+        pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_NONE;
+        pDevice->PhyIntMode = T3_PHY_INT_MODE_LINK_READY;
+        if ((pDevice->PollTbiLink == BAD_DEFAULT_VALUE) ||
+            pDevice->DisableAutoNeg)
+        {
+            pDevice->PollTbiLink = FALSE;
+        }
+    }
+    else
+    {
+        pDevice->PollTbiLink = FALSE;
+    }
+#endif /* INCLUDE_TBI_SUPPORT */
+
+    /* UseTaggedStatus is only valid for 5701 and later. */
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+    {
+        pDevice->UseTaggedStatus = FALSE;
+
+        pDevice->CoalesceMode = 0;
+    }
+    else
+    {
+        pDevice->CoalesceMode = HOST_COALESCE_CLEAR_TICKS_ON_RX_BD_EVENT |
+            HOST_COALESCE_CLEAR_TICKS_ON_TX_BD_EVENT;
+    }
+
+    /* Set the status block size. */
+    if(T3_CHIP_REV(pDevice->ChipRevId) != T3_CHIP_REV_5700_AX &&
+        T3_CHIP_REV(pDevice->ChipRevId) != T3_CHIP_REV_5700_BX)
+    {
+        pDevice->CoalesceMode |= HOST_COALESCE_32_BYTE_STATUS_MODE;
+    }
+
+    /* Check the DURING_INT coalescing ticks parameters. */
+    if(pDevice->UseTaggedStatus)
+    {
+        if(pDevice->RxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->RxCoalescingTicksDuringInt =
+                DEFAULT_RX_COALESCING_TICKS_DURING_INT;
+        }
+
+        if(pDevice->TxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->TxCoalescingTicksDuringInt =
+                DEFAULT_TX_COALESCING_TICKS_DURING_INT;
+        }
+
+        if(pDevice->RxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->RxMaxCoalescedFramesDuringInt =
+                DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT;
+        }
+
+        if(pDevice->TxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->TxMaxCoalescedFramesDuringInt =
+                DEFAULT_TX_MAX_COALESCED_FRAMES_DURING_INT;
+        }
+    }
+    else
+    {
+        if(pDevice->RxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->RxCoalescingTicksDuringInt = 0;
+        }
+
+        if(pDevice->TxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->TxCoalescingTicksDuringInt = 0;
+        }
+
+        if(pDevice->RxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->RxMaxCoalescedFramesDuringInt = 0;
+        }
+
+        if(pDevice->TxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->TxMaxCoalescedFramesDuringInt = 0;
+        }
+    }
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    if(pDevice->RxMtu <= (MAX_STD_RCV_BUFFER_SIZE - 8 /* CRC */))
+    {
+        pDevice->RxJumboDescCnt = 0;
+        if(pDevice->RxMtu <= MAX_ETHERNET_PACKET_SIZE_NO_CRC)
+        {
+            pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+        }
+    }
+    else
+    {
+        pDevice->RxJumboBufferSize = (pDevice->RxMtu + 8 /* CRC + VLAN */ +
+            COMMON_CACHE_LINE_SIZE-1) & ~COMMON_CACHE_LINE_MASK;
+
+        if(pDevice->RxJumboBufferSize > MAX_JUMBO_RCV_BUFFER_SIZE)
+        {
+            pDevice->RxJumboBufferSize = DEFAULT_JUMBO_RCV_BUFFER_SIZE;
+            pDevice->RxMtu = pDevice->RxJumboBufferSize - 8 /* CRC + VLAN */;
+        }
+        pDevice->TxMtu = pDevice->RxMtu;
+
+    }
+#else
+    pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    pDevice->RxPacketDescCnt = 
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+        pDevice->RxJumboDescCnt +
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+        pDevice->RxStdDescCnt;
+
+    if(pDevice->TxMtu < MAX_ETHERNET_PACKET_SIZE_NO_CRC)
+    {
+        pDevice->TxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+    }
+
+    if(pDevice->TxMtu > MAX_JUMBO_TX_BUFFER_SIZE)
+    {
+        pDevice->TxMtu = MAX_JUMBO_TX_BUFFER_SIZE;
+    }
+
+    /* Configure the proper ways to get link change interrupt. */
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO)
+    {
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+        {
+            pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT;
+        }
+        else
+        {
+            pDevice->PhyIntMode = T3_PHY_INT_MODE_LINK_READY;
+        }
+    }
+    else if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+    {
+        /* Auto-polling does not work on 5700_AX and 5700_BX. */
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+        {
+            pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT;
+        }
+    }
+
+    /* Determine the method to get link change status. */
+    if(pDevice->LinkChngMode == T3_LINK_CHNG_MODE_AUTO)
+    {
+        /* The link status bit in the status block does not work on 5700_AX */
+        /* and 5700_BX chips. */
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+        {
+            pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG;
+        }
+        else
+        {
+            pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_BLOCK;
+        }
+    }
+
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT ||
+        T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+    {
+        pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG;
+    }
+
+    /* Configure PHY led mode. */
+    if(pDevice->LedMode == LED_MODE_AUTO)
+    {
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            if(pDevice->SubsystemVendorId == T3_SVID_DELL)
+            {
+                pDevice->LedMode = LED_MODE_LINK10;
+            }
+            else
+            {
+                pDevice->LedMode = LED_MODE_THREE_LINK;
+
+                if(EeSigFound && EePhyLedMode != LED_MODE_AUTO)
+                {
+                    pDevice->LedMode = EePhyLedMode;
+                }
+            }
+
+            /* bug? 5701 in LINK10 mode does not seem to work when */
+            /* PhyIntMode is LINK_READY. */
+            if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 &&
+#if INCLUDE_TBI_SUPPORT
+                pDevice->EnableTbi == FALSE &&
+#endif
+                pDevice->LedMode == LED_MODE_LINK10)
+            {
+                pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT;
+                pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG;
+            }
+
+            if(pDevice->EnableTbi)
+            {
+                pDevice->LedMode = LED_MODE_THREE_LINK;
+            }
+        }
+        else
+        {
+            if(EeSigFound && EePhyLedMode != LED_MODE_AUTO)
+            {
+                pDevice->LedMode = EePhyLedMode;
+            }
+            else
+            {
+                pDevice->LedMode = LED_MODE_OPEN_DRAIN;
+            }
+        }
+    }
+
+    /* Enable OneDmaAtOnce. */
+    if(pDevice->OneDmaAtOnce == BAD_DEFAULT_VALUE)
+    {
+        pDevice->OneDmaAtOnce = FALSE;
+    }
+
+    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
+    {
+        pDevice->WolSpeed = WOL_SPEED_100MB;
+    }
+
+    /* Offloadings. */
+    pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
+
+    /* Turn off task offloading on Ax. */
+    if(pDevice->ChipRevId == T3_CHIP_ID_5700_B0)
+    {
+        pDevice->TaskOffloadCap &= ~(LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
+            LM_TASK_OFFLOAD_TX_UDP_CHECKSUM);
+    }
+    pDevice->PciState = REG_RD(pDevice, PciCfg.PciState);
+    LM_ReadVPD(pDevice);
+    LM_ReadBootCodeVersion(pDevice);
+    LM_GetBusSpeed(pDevice);
+
+    return LM_STATUS_SUCCESS;
+} /* LM_GetAdapterInfo */
+
+STATIC PLM_ADAPTER_INFO
+LM_GetAdapterInfoBySsid(
+    LM_UINT16 Svid,
+    LM_UINT16 Ssid)
+{
+    static LM_ADAPTER_INFO AdapterArr[] =
+    {
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700A6, PHY_BCM5401_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A5, PHY_BCM5701_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700T6, PHY_BCM8002_PHY_ID, 1},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700A9, 0, 1 },
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701T1, PHY_BCM5701_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701T8, PHY_BCM5701_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A7, 0, 1},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A10, PHY_BCM5701_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A12, PHY_BCM5701_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95703Ax1, PHY_BCM5701_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95703Ax2, PHY_BCM5701_PHY_ID, 0},
+
+        { T3_SVID_3COM, T3_SSID_3COM_3C996T, PHY_BCM5401_PHY_ID, 0 },
+        { T3_SVID_3COM, T3_SSID_3COM_3C996BT, PHY_BCM5701_PHY_ID, 0 },
+        { T3_SVID_3COM, T3_SSID_3COM_3C996SX, 0, 1 },
+        { T3_SVID_3COM, T3_SSID_3COM_3C1000T, PHY_BCM5701_PHY_ID, 0 },
+        { T3_SVID_3COM, T3_SSID_3COM_3C940BR01, PHY_BCM5701_PHY_ID, 0 },
+
+        { T3_SVID_DELL, T3_SSID_DELL_VIPER, PHY_BCM5401_PHY_ID, 0 },
+        { T3_SVID_DELL, T3_SSID_DELL_JAGUAR, PHY_BCM5401_PHY_ID, 0 },
+        { T3_SVID_DELL, T3_SSID_DELL_MERLOT, PHY_BCM5411_PHY_ID, 0 },
+        { T3_SVID_DELL, T3_SSID_DELL_SLIM_MERLOT, PHY_BCM5411_PHY_ID, 0 },
+
+        { T3_SVID_COMPAQ, T3_SSID_COMPAQ_BANSHEE, PHY_BCM5701_PHY_ID, 0 },
+        { T3_SVID_COMPAQ, T3_SSID_COMPAQ_BANSHEE_2, PHY_BCM5701_PHY_ID, 0 },
+        { T3_SVID_COMPAQ, T3_SSID_COMPAQ_CHANGELING, 0, 1 },
+        { T3_SVID_COMPAQ, T3_SSID_COMPAQ_NC7780, PHY_BCM5701_PHY_ID, 0 },
+        { T3_SVID_COMPAQ, T3_SSID_COMPAQ_NC7780_2, PHY_BCM5701_PHY_ID, 0 },
+
+    };
+    LM_UINT32 j;
+
+    for(j = 0; j < sizeof(AdapterArr)/sizeof(LM_ADAPTER_INFO); j++)
+    {
+        if(AdapterArr[j].Svid == Svid && AdapterArr[j].Ssid == Ssid)
+        {
+            return &AdapterArr[j];
+        }
+    }
+
+    return NULL;
+}
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine sets up receive/transmit buffer descriptions queues.       */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_InitializeAdapter(
+PLM_DEVICE_BLOCK pDevice)
+{
+    LM_PHYSICAL_ADDRESS MemPhy;
+    PLM_UINT8 pMemVirt;
+    PLM_PACKET pPacket;
+    LM_STATUS Status;
+    LM_UINT32 Size;
+    LM_UINT32 j;
+
+    /* Set power state to D0. */
+    LM_SetPowerState(pDevice, LM_POWER_STATE_D0);
+
+    /* Intialize the queues. */
+    QQ_InitQueue(&pDevice->RxPacketReceivedQ.Container, 
+        MAX_RX_PACKET_DESC_COUNT);
+    QQ_InitQueue(&pDevice->RxPacketFreeQ.Container,
+        MAX_RX_PACKET_DESC_COUNT);
+
+    QQ_InitQueue(&pDevice->TxPacketFreeQ.Container,MAX_TX_PACKET_DESC_COUNT);
+    QQ_InitQueue(&pDevice->TxPacketActiveQ.Container,MAX_TX_PACKET_DESC_COUNT);
+    QQ_InitQueue(&pDevice->TxPacketXmittedQ.Container,MAX_TX_PACKET_DESC_COUNT);
+
+    /* 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 */
+        T3_RCV_RETURN_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD);
+
+    /* Memory for host based Send BD. */
+    if(pDevice->NicSendBd == FALSE)
+    {
+        Size += sizeof(T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT;
+    }
+
+    /* Allocate the memory block. */
+    Status = MM_AllocateSharedMemory(pDevice, Size, (PLM_VOID) &pMemVirt, &MemPhy, FALSE);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+
+    /* Program DMA Read/Write */
+    if (pDevice->PciState & T3_PCI_STATE_NOT_PCI_X_BUS)
+    {
+        pDevice->DmaReadWriteCtrl = 0x763f000f;    
+    }
+    else
+    {
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704)
+        {
+            pDevice->DmaReadWriteCtrl = 0x761f0000; 
+        }
+        else
+        {
+            pDevice->DmaReadWriteCtrl = 0x761b000f;    
+        }
+        if(pDevice->ChipRevId == T3_CHIP_ID_5703_A1 ||
+            pDevice->ChipRevId == T3_CHIP_ID_5703_A2)
+        {
+            pDevice->OneDmaAtOnce = TRUE;
+        }
+    }
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703)
+    {
+        pDevice->DmaReadWriteCtrl &= 0xfffffff0;
+    }
+
+    if(pDevice->OneDmaAtOnce)
+    {
+        pDevice->DmaReadWriteCtrl |= DMA_CTRL_WRITE_ONE_DMA_AT_ONCE;
+    }
+    REG_WR(pDevice, PciCfg.DmaReadWriteCtrl, pDevice->DmaReadWriteCtrl);
+
+    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 += T3_RCV_RETURN_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD);
+    LM_INC_PHYSICAL_ADDRESS(&MemPhy, 
+        T3_RCV_RETURN_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD));
+
+    /* Set up Send BD. */
+    if(pDevice->NicSendBd == FALSE)
+    {
+        pDevice->pSendBdVirt = (PT3_SND_BD) pMemVirt;
+        pDevice->SendBdPhy = MemPhy;
+
+        pMemVirt += sizeof(T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT;
+        LM_INC_PHYSICAL_ADDRESS(&MemPhy, 
+            sizeof(T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT);
+    }
+    else
+    {
+        pDevice->pSendBdVirt = (PT3_SND_BD)
+            pDevice->pMemView->uIntMem.First32k.BufferDesc;
+        pDevice->SendBdPhy.High = 0;
+        pDevice->SendBdPhy.Low = T3_NIC_SND_BUFFER_DESC_ADDR;
+    }
+
+    /* Allocate memory for packet descriptors. */
+    Size = (pDevice->RxPacketDescCnt + 
+        pDevice->TxPacketDescCnt) * MM_PACKET_DESC_SIZE;
+    Status = MM_AllocateMemory(pDevice, Size, (PLM_VOID *) &pPacket);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    pDevice->pPacketDescBase = (PLM_VOID) pPacket;
+
+    /* Create transmit packet descriptors from the memory block and add them */
+    /* to the TxPacketFreeQ for each send ring. */
+    for(j = 0; j < pDevice->TxPacketDescCnt; j++)
+    {
+        /* Ring index. */
+        pPacket->Flags = 0;
+
+        /* Queue the descriptor in the TxPacketFreeQ of the 'k' ring. */
+        QQ_PushTail(&pDevice->TxPacketFreeQ.Container, pPacket);
+
+        /* Get the pointer to the next descriptor.  MM_PACKET_DESC_SIZE */
+        /* is the total size of the packet descriptor including the */
+        /* os-specific extensions in the UM_PACKET structure. */
+        pPacket = (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE);
+    } /* for(j.. */
+
+    /* Create receive packet descriptors from the memory block and add them */
+    /* to the RxPacketFreeQ.  Create the Standard packet descriptors. */
+    for(j = 0; j < pDevice->RxStdDescCnt; j++)
+    {
+        /* Receive producer ring. */
+        pPacket->u.Rx.RcvProdRing = T3_STD_RCV_PROD_RING;
+
+        /* Receive buffer size. */
+        pPacket->u.Rx.RxBufferSize = MAX_STD_RCV_BUFFER_SIZE;
+
+        /* Add the descriptor to RxPacketFreeQ. */
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+        /* Get the pointer to the next descriptor.  MM_PACKET_DESC_SIZE */
+        /* is the total size of the packet descriptor including the */
+        /* os-specific extensions in the UM_PACKET structure. */
+        pPacket = (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE);
+    } /* for */
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    /* Create the Jumbo packet descriptors. */
+    for(j = 0; j < pDevice->RxJumboDescCnt; j++)
+    {
+        /* Receive producer ring. */
+        pPacket->u.Rx.RcvProdRing = T3_JUMBO_RCV_PROD_RING;
+
+        /* Receive buffer size. */
+        pPacket->u.Rx.RxBufferSize = pDevice->RxJumboBufferSize;
+
+        /* Add the descriptor to RxPacketFreeQ. */
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+        /* Get the pointer to the next descriptor.  MM_PACKET_DESC_SIZE */
+        /* is the total size of the packet descriptor including the */
+        /* os-specific extensions in the UM_PACKET structure. */
+        pPacket = (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE);
+    } /* for */
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    /* Initialize the rest of the packet descriptors. */
+    Status = MM_InitializeUmPackets(pDevice);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    } /* if */
+
+    /* Default receive mask. */
+    pDevice->ReceiveMask = LM_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 */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This function Enables/Disables a given block.                          */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_CntrlBlock(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 mask,LM_UINT32 cntrl)
+{
+    LM_UINT32 j,i,data;
+    LM_UINT32 MaxWaitCnt;
+
+    MaxWaitCnt = 2;
+    j = 0;
+
+    for(i = 0 ; i < 32; i++) 
+    {
+        if(!(mask & (1 << i)))
+            continue;     
+        switch (1 << i) 
+        {
+            case T3_BLOCK_DMA_RD:
+                data = REG_RD(pDevice, DmaRead.Mode);
+                if (cntrl == LM_DISABLE) 
+                {
+                    data &= ~DMA_READ_MODE_ENABLE;
+                    REG_WR(pDevice, DmaRead.Mode, data);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, DmaRead.Mode) & DMA_READ_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else 
+                    REG_WR(pDevice, DmaRead.Mode, data | DMA_READ_MODE_ENABLE);
+                break;
+  
+            case T3_BLOCK_DMA_COMP:
+                data = REG_RD(pDevice,DmaComp.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~DMA_COMP_MODE_ENABLE;
+                    REG_WR(pDevice, DmaComp.Mode, data);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, DmaComp.Mode) & DMA_COMP_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, DmaComp.Mode, data | DMA_COMP_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_RX_BD_INITIATOR:
+                data = REG_RD(pDevice, RcvBdIn.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~RCV_BD_IN_MODE_ENABLE;
+                    REG_WR(pDevice, RcvBdIn.Mode,data);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, RcvBdIn.Mode) & RCV_BD_IN_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }              
+                }
+                else
+                    REG_WR(pDevice, RcvBdIn.Mode,data | RCV_BD_IN_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_RX_BD_COMP:
+                data = REG_RD(pDevice, RcvBdComp.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~RCV_BD_COMP_MODE_ENABLE;
+                    REG_WR(pDevice, RcvBdComp.Mode,data);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, RcvBdComp.Mode) & RCV_BD_COMP_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }     
+                }
+                else
+                    REG_WR(pDevice, RcvBdComp.Mode,data | RCV_BD_COMP_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_DMA_WR:
+                data = REG_RD(pDevice, DmaWrite.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~DMA_WRITE_MODE_ENABLE;
+                    REG_WR(pDevice, DmaWrite.Mode,data);
+
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, DmaWrite.Mode) & DMA_WRITE_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, DmaWrite.Mode,data | DMA_WRITE_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_MSI_HANDLER:
+                data = REG_RD(pDevice, Msi.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~MSI_MODE_ENABLE;
+                    REG_WR(pDevice, Msi.Mode, data);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, Msi.Mode) & MSI_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, Msi.Mode, data |MSI_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_RX_LIST_PLMT:
+                data = REG_RD(pDevice, RcvListPlmt.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~RCV_LIST_PLMT_MODE_ENABLE;
+                    REG_WR(pDevice, RcvListPlmt.Mode,data);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, RcvListPlmt.Mode) & RCV_LIST_PLMT_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, RcvListPlmt.Mode,data | RCV_LIST_PLMT_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_RX_LIST_SELECTOR:
+                data = REG_RD(pDevice, RcvListSel.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~RCV_LIST_SEL_MODE_ENABLE;
+                    REG_WR(pDevice, RcvListSel.Mode,data);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, RcvListSel.Mode) & RCV_LIST_SEL_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }     
+                }
+                else
+                    REG_WR(pDevice, RcvListSel.Mode,data |RCV_LIST_SEL_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_RX_DATA_INITIATOR:
+                data = REG_RD(pDevice, RcvDataBdIn.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~RCV_DATA_BD_IN_MODE_ENABLE;
+                    REG_WR(pDevice, RcvDataBdIn.Mode,data);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, RcvDataBdIn.Mode) & RCV_DATA_BD_IN_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }      
+                }
+                else
+                    REG_WR(pDevice, RcvDataBdIn.Mode, data | RCV_DATA_BD_IN_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_RX_DATA_COMP:
+                data = REG_RD(pDevice, RcvDataComp.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~RCV_DATA_COMP_MODE_ENABLE;
+                    REG_WR(pDevice, RcvDataComp.Mode,data);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, RcvDataBdIn.Mode) & RCV_DATA_COMP_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }        
+                }
+                else
+                    REG_WR(pDevice, RcvDataComp.Mode,data | RCV_DATA_COMP_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_HOST_COALESING:
+                data = REG_RD(pDevice, HostCoalesce.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~HOST_COALESCE_ENABLE;
+                    REG_WR(pDevice, HostCoalesce.Mode, data);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, SndBdIn.Mode) & HOST_COALESCE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, HostCoalesce.Mode, data | HOST_COALESCE_ENABLE);
+                break;
+
+            case T3_BLOCK_MAC_RX_ENGINE:
+                if(cntrl == LM_DISABLE)
+                {
+                    pDevice->RxMode &= ~RX_MODE_ENABLE;
+                    REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, MacCtrl.RxMode) & RX_MODE_ENABLE))
+                        {
+                            break;
+                        }
+                        MM_Wait(10);
+                    }
+                }
+                else
+                {
+                    pDevice->RxMode |= RX_MODE_ENABLE;
+                    REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+                }
+                break;
+
+            case T3_BLOCK_MBUF_CLUSTER_FREE:
+                data = REG_RD(pDevice, MbufClusterFree.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~MBUF_CLUSTER_FREE_MODE_ENABLE;
+                    REG_WR(pDevice, MbufClusterFree.Mode,data);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, MbufClusterFree.Mode) & MBUF_CLUSTER_FREE_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }     
+                }
+                else
+                    REG_WR(pDevice, MbufClusterFree.Mode, data | MBUF_CLUSTER_FREE_MODE_ENABLE);         
+                break;
+
+            case T3_BLOCK_SEND_BD_INITIATOR:
+                data = REG_RD(pDevice, SndBdIn.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~SND_BD_IN_MODE_ENABLE;
+                    REG_WR(pDevice, SndBdIn.Mode, data);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, SndBdIn.Mode) & SND_BD_IN_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, SndBdIn.Mode, data  | SND_BD_IN_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_SEND_BD_COMP:
+                data = REG_RD(pDevice, SndBdComp.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~SND_BD_COMP_MODE_ENABLE;
+                    REG_WR(pDevice, SndBdComp.Mode, data);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, SndBdComp.Mode) & SND_BD_COMP_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, SndBdComp.Mode, data | SND_BD_COMP_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_SEND_BD_SELECTOR:
+                data = REG_RD(pDevice, SndBdSel.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~SND_BD_SEL_MODE_ENABLE;
+                    REG_WR(pDevice, SndBdSel.Mode, data);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, SndBdSel.Mode) & SND_BD_SEL_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, SndBdSel.Mode, data | SND_BD_SEL_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_SEND_DATA_INITIATOR:
+                data = REG_RD(pDevice, SndDataIn.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~T3_SND_DATA_IN_MODE_ENABLE;
+                    REG_WR(pDevice, SndDataIn.Mode,data);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, SndDataIn.Mode) & T3_SND_DATA_IN_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, SndDataIn.Mode,data | T3_SND_DATA_IN_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_SEND_DATA_COMP:
+                data = REG_RD(pDevice, SndDataComp.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~SND_DATA_COMP_MODE_ENABLE;
+                    REG_WR(pDevice, SndDataComp.Mode, data);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, SndDataComp.Mode) & SND_DATA_COMP_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, SndDataComp.Mode,data | SND_DATA_COMP_MODE_ENABLE);
+                break;
+               
+            case T3_BLOCK_MAC_TX_ENGINE:
+                if(cntrl == LM_DISABLE)
+                {
+                    pDevice->TxMode &= ~TX_MODE_ENABLE;
+                    REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, MacCtrl.TxMode) & TX_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else  
+                {
+                    pDevice->TxMode |= TX_MODE_ENABLE;
+                    REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode);
+                }
+                break;
+
+            case T3_BLOCK_MEM_ARBITOR:
+                data = REG_RD(pDevice, MemArbiter.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~T3_MEM_ARBITER_MODE_ENABLE;
+                    REG_WR(pDevice, MemArbiter.Mode, data);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, MemArbiter.Mode) & T3_MEM_ARBITER_MODE_ENABLE)) 
+                            break;
+                        MM_Wait(10);
+                    }       
+                }
+                else
+                    REG_WR(pDevice, MemArbiter.Mode,data|T3_MEM_ARBITER_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_MBUF_MANAGER:
+                data = REG_RD(pDevice, BufMgr.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~BUFMGR_MODE_ENABLE;
+                    REG_WR(pDevice, BufMgr.Mode,data);
+                    for(j = 0; j < MaxWaitCnt; j++) 
+                    {
+                        if(!(REG_RD(pDevice, BufMgr.Mode) & BUFMGR_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, BufMgr.Mode,data |  BUFMGR_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_MAC_GLOBAL:
+                if(cntrl == LM_DISABLE)
+                {
+                    pDevice->MacMode &= ~(MAC_MODE_ENABLE_TDE |
+                        MAC_MODE_ENABLE_RDE |
+                        MAC_MODE_ENABLE_FHDE);
+                }
+                else
+                {
+                    pDevice->MacMode |= (MAC_MODE_ENABLE_TDE |
+                        MAC_MODE_ENABLE_RDE |
+                        MAC_MODE_ENABLE_FHDE);
+                }
+                REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+                break;
+
+            default:
+                return LM_STATUS_FAILURE;
+        } /* switch */
+
+        if(j >= MaxWaitCnt) 
+        {
+            return LM_STATUS_FAILURE;
+        }
+    } 
+
+    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_UINT16 Value16;
+    LM_UINT32 j, k;
+
+    /* Disable interrupt. */
+    LM_DisableInterrupt(pDevice);
+
+    /* May get a spurious interrupt */
+    pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED;
+
+    /* Disable transmit and receive DMA engines.  Abort all pending requests. */
+    if(pDevice->InitDone)
+    {
+        LM_Abort(pDevice);
+    }
+
+    pDevice->ShuttingDown = FALSE;
+
+    LM_ResetChip(pDevice);
+
+    /* Bug: Athlon fix for B3 silicon only.  This bit does not do anything */
+    /* in other chip revisions. */
+    if(pDevice->DelayPciGrant)
+    {
+        Value32 = REG_RD(pDevice, PciCfg.ClockCtrl);
+        REG_WR(pDevice, PciCfg.ClockCtrl, Value32 | BIT_31);
+    }
+
+    if(pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+    {
+        if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))
+        {
+            Value32 = REG_RD(pDevice, PciCfg.PciState);
+            Value32 |= T3_PCI_STATE_RETRY_SAME_DMA;
+            REG_WR(pDevice, PciCfg.PciState, Value32);
+        }
+    }
+
+    /* Enable TaggedStatus mode. */
+    if(pDevice->UseTaggedStatus)
+    {
+        pDevice->MiscHostCtrl |= MISC_HOST_CTRL_ENABLE_TAGGED_STATUS_MODE;
+    }
+
+    /* Restore PCI configuration registers. */
+    MM_WriteConfig32(pDevice, PCI_CACHE_LINE_SIZE_REG,
+        pDevice->SavedCacheLineReg);
+    MM_WriteConfig32(pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, 
+        (pDevice->SubsystemId << 16) | pDevice->SubsystemVendorId);
+
+    /* Clear the statistics block. */
+    for(j = 0x0300; j < 0x0b00; j++)
+    {
+        MEM_WR_OFFSET(pDevice, j, 0);
+    }
+
+    /* Initialize the statistis Block */
+    pDevice->pStatusBlkVirt->Status = 0;
+    pDevice->pStatusBlkVirt->RcvStdConIdx = 0;
+    pDevice->pStatusBlkVirt->RcvJumboConIdx = 0;
+    pDevice->pStatusBlkVirt->RcvMiniConIdx = 0;
+
+    for(j = 0; j < 16; j++)
+    {
+       pDevice->pStatusBlkVirt->Idx[j].RcvProdIdx = 0;
+       pDevice->pStatusBlkVirt->Idx[j].SendConIdx = 0;
+    }
+
+    for(k = 0; k < T3_STD_RCV_RCB_ENTRY_COUNT ;k++)
+    {
+       pDevice->pRxStdBdVirt[k].HostAddr.High = 0;
+       pDevice->pRxStdBdVirt[k].HostAddr.Low = 0;
+    }
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    /* Receive jumbo BD buffer. */
+    for(k = 0; k < T3_JUMBO_RCV_RCB_ENTRY_COUNT; k++)
+    {
+        pDevice->pRxJumboBdVirt[k].HostAddr.High = 0;
+        pDevice->pRxJumboBdVirt[k].HostAddr.Low = 0;
+    }
+#endif
+
+    REG_WR(pDevice, PciCfg.DmaReadWriteCtrl, pDevice->DmaReadWriteCtrl);    
+
+    /* GRC mode control register. */
+#ifdef BIG_ENDIAN_PCI    /* Jimmy, this ifdef block deleted in new code! */
+    Value32 = 
+        GRC_MODE_WORD_SWAP_DATA |
+        GRC_MODE_WORD_SWAP_NON_FRAME_DATA |
+        GRC_MODE_INT_ON_MAC_ATTN |
+        GRC_MODE_HOST_STACK_UP;
+#else
+    /* No CPU Swap modes for PCI IO */
+    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;
+#endif /* !BIG_ENDIAN_PCI */
+    
+    /* Configure send BD mode. */
+    if(pDevice->NicSendBd == FALSE)
+    {
+        Value32 |= GRC_MODE_HOST_SEND_BDS;
+    }
+    else
+    {
+        Value32 |= GRC_MODE_4X_NIC_BASED_SEND_RINGS;
+    }
+
+    /* Configure pseudo checksum mode. */
+    if(pDevice->NoTxPseudoHdrChksum)
+    {
+        Value32 |= GRC_MODE_TX_NO_PSEUDO_HEADER_CHKSUM;
+    }
+
+    if(pDevice->NoRxPseudoHdrChksum)
+    {
+        Value32 |= GRC_MODE_RX_NO_PSEUDO_HEADER_CHKSUM;
+    }
+
+    REG_WR(pDevice, Grc.Mode, Value32);
+
+    /* Setup the timer prescalar register. */
+    REG_WR(pDevice, Grc.MiscCfg, 65 << 1);      /* Clock is alwasy 66Mhz. */
+
+    /* Set up the MBUF pool base address and size. */
+    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->DmaMbufLowMark)
+    {
+        REG_WR(pDevice, BufMgr.MbufReadDmaLowWaterMark, 
+            pDevice->DmaMbufLowMark);
+    }
+    else
+    {
+        if(pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE)
+        {
+            REG_WR(pDevice, BufMgr.MbufReadDmaLowWaterMark,
+                T3_DEF_DMA_MBUF_LOW_WMARK);
+        }
+        else
+        {
+            REG_WR(pDevice, BufMgr.MbufReadDmaLowWaterMark,
+                T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO);
+        }
+    }
+
+    /* Configure the MAC Rx MBUF low water mark. */
+    if(pDevice->RxMacMbufLowMark)
+    {
+        REG_WR(pDevice, BufMgr.MbufMacRxLowWaterMark,
+            pDevice->RxMacMbufLowMark);
+    }
+    else
+    {
+        if(pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE)
+        {
+            REG_WR(pDevice, BufMgr.MbufMacRxLowWaterMark,
+                T3_DEF_RX_MAC_MBUF_LOW_WMARK);
+        }
+        else
+        {
+            REG_WR(pDevice, BufMgr.MbufMacRxLowWaterMark,
+                T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO);
+        }
+    }
+
+    /* Configure the MBUF high water mark. */
+    if(pDevice->MbufHighMark)
+    {
+        REG_WR(pDevice, BufMgr.MbufHighWaterMark, pDevice->MbufHighMark);
+    }
+    else
+    {
+        if(pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE)
+        {
+            REG_WR(pDevice, BufMgr.MbufHighWaterMark,
+                T3_DEF_MBUF_HIGH_WMARK);
+        }
+        else
+        {
+            REG_WR(pDevice, BufMgr.MbufHighWaterMark,
+                T3_DEF_MBUF_HIGH_WMARK_JUMBO);
+        }
+    }
+
+    REG_WR(pDevice, BufMgr.DmaLowWaterMark, T3_DEF_DMA_DESC_LOW_WMARK);
+    REG_WR(pDevice, BufMgr.DmaHighWaterMark, T3_DEF_DMA_DESC_HIGH_WMARK);
+
+    /* Enable buffer manager. */
+    REG_WR(pDevice, BufMgr.Mode, BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE);
+
+    for(j = 0 ;j < 2000; j++)
+    {
+        if(REG_RD(pDevice, BufMgr.Mode) & BUFMGR_MODE_ENABLE)
+            break;
+        MM_Wait(10);
+    }
+
+    if(j >= 2000)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    /* Enable the FTQs. */
+    REG_WR(pDevice, Ftq.Reset, 0xffffffff);
+    REG_WR(pDevice, Ftq.Reset, 0);
+
+    /* Wait until FTQ is ready */
+    for(j = 0; j < 2000; j++)
+    {
+        if(REG_RD(pDevice, Ftq.Reset) == 0)
+            break;
+        MM_Wait(10);
+    }
+
+    if(j >= 2000)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    /* 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.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);
+
+#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);
+
+    {
+        REG_WR(pDevice, RcvDataBdIn.StdRcvRcb.NicRingAddr,
+            (LM_UINT32) T3_NIC_STD_RCV_BUFFER_DESC_ADDR);
+        REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.NicRingAddr,
+            (LM_UINT32) T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR);
+    }
+
+    /* Receive BD Ring replenish threshold. */
+    REG_WR(pDevice, RcvBdIn.StdRcvThreshold, pDevice->RxStdDescCnt/8);
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    REG_WR(pDevice, RcvBdIn.JumboRcvThreshold, pDevice->RxJumboDescCnt/8);
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    /* Disable all the unused rings. */
+    for(j = 0; j < T3_MAX_SEND_RCB_COUNT; j++) {
+        MEM_WR(pDevice, SendRcb[j].u.MaxLen_Flags, T3_RCB_FLAG_RING_DISABLED);
+    } /* for */
+
+    /* Initialize the indices. */
+    pDevice->SendProdIdx = 0;
+    pDevice->SendConIdx = 0;
+
+    MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, 0); 
+    MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, 0);
+
+    /* Set up host or NIC based send RCB. */
+    if(pDevice->NicSendBd == FALSE)
+    {
+        MEM_WR(pDevice, SendRcb[0].HostRingAddr.High, 
+            pDevice->SendBdPhy.High);
+        MEM_WR(pDevice, SendRcb[0].HostRingAddr.Low, 
+            pDevice->SendBdPhy.Low);
+
+        /* Set up the NIC ring address in the RCB. */
+        MEM_WR(pDevice, SendRcb[0].NicRingAddr,T3_NIC_SND_BUFFER_DESC_ADDR);
+
+        /* Setup the RCB. */
+        MEM_WR(pDevice, SendRcb[0].u.MaxLen_Flags,
+            T3_SEND_RCB_ENTRY_COUNT << 16);
+
+        for(k = 0; k < T3_SEND_RCB_ENTRY_COUNT; k++)
+        {
+            pDevice->pSendBdVirt[k].HostAddr.High = 0;
+            pDevice->pSendBdVirt[k].HostAddr.Low = 0;
+        }
+    }
+    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++)
+        {
+            __raw_writel(0, &(pDevice->pSendBdVirt[k].HostAddr.High));
+            __raw_writel(0, &(pDevice->pSendBdVirt[k].HostAddr.Low));
+            __raw_writel(0, &(pDevice->pSendBdVirt[k].u1.Len_Flags));
+            pDevice->ShadowSendBd[k].HostAddr.High = 0;
+            pDevice->ShadowSendBd[k].u1.Len_Flags = 0;
+        }
+    }
+    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);
+
+    /* Set up the NIC ring address in the RCB. */
+    /* Not very clear from the spec.  I am guessing that for Receive */
+    /* Return Ring, NicRingAddr is not used. */
+    MEM_WR(pDevice, RcvRetRcb[0].NicRingAddr, 0);
+
+    /* Setup the RCB. */
+    MEM_WR(pDevice, RcvRetRcb[0].u.MaxLen_Flags,
+        T3_RCV_RETURN_RCB_ENTRY_COUNT << 16);
+
+    /* Reinitialize RX ring producer index */
+    MB_REG_WR(pDevice, Mailbox.RcvStdProdIdx.Low, 0);
+    MB_REG_WR(pDevice, Mailbox.RcvJumboProdIdx.Low, 0);
+    MB_REG_WR(pDevice, Mailbox.RcvMiniProdIdx.Low, 0);
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    pDevice->RxJumboProdIdx = 0;
+    pDevice->RxJumboQueuedCnt = 0;
+#endif
+
+    /* Reinitialize our copy of the indices. */
+    pDevice->RxStdProdIdx = 0;
+    pDevice->RxStdQueuedCnt = 0;
+
+#if T3_JUMBO_RCV_ENTRY_COUNT
+    pDevice->RxJumboProdIdx = 0;
+#endif /* T3_JUMBO_RCV_ENTRY_COUNT */
+
+    /* Configure the MAC address. */
+    LM_SetMacAddress(pDevice, pDevice->NodeAddress);
+
+    /* Initialize the transmit random backoff seed. */
+    Value32 = (pDevice->NodeAddress[0] + pDevice->NodeAddress[1] + 
+        pDevice->NodeAddress[2] + pDevice->NodeAddress[3] + 
+        pDevice->NodeAddress[4] + pDevice->NodeAddress[5]) & 
+        MAC_TX_BACKOFF_SEED_MASK;
+    REG_WR(pDevice, MacCtrl.TxBackoffSeed, Value32);
+
+    /* Receive MTU.  Frames larger than the MTU is marked as oversized. */
+    REG_WR(pDevice, MacCtrl.MtuSize, pDevice->RxMtu + 8);   /* CRC + VLAN. */
+
+    /* Configure Time slot/IPG per 802.3 */
+    REG_WR(pDevice, MacCtrl.TxLengths, 0x2620);
+
+    /*
+     * Configure Receive Rules so that packets don't match 
+     * Programmble rule will be queued to Return Ring 1 
+     */
+    REG_WR(pDevice, MacCtrl.RcvRuleCfg, RX_RULE_DEFAULT_CLASS);
+
+    /* 
+     * Configure to have 16 Classes of Services (COS) and one
+     * queue per class.  Bad frames are queued to RRR#1.
+     * And frames don't match rules are also queued to COS#1.
+     */
+    REG_WR(pDevice, RcvListPlmt.Config, 0x181);
+    
+    /* Enable Receive Placement Statistics */
+    REG_WR(pDevice, RcvListPlmt.StatsEnableMask,0xffffff);
+    REG_WR(pDevice, RcvListPlmt.StatsCtrl, RCV_LIST_STATS_ENABLE);
+
+    /* Enable Send Data Initator Statistics */
+    REG_WR(pDevice, SndDataIn.StatsEnableMask,0xffffff);
+    REG_WR(pDevice, SndDataIn.StatsCtrl,
+        T3_SND_DATA_IN_STATS_CTRL_ENABLE | \
+        T3_SND_DATA_IN_STATS_CTRL_FASTER_UPDATE);
+
+    /* Disable the host coalescing state machine before configuring it's */
+    /* parameters. */
+    REG_WR(pDevice, HostCoalesce.Mode, 0); 
+    for(j = 0; j < 2000; j++)
+    {
+        Value32 = REG_RD(pDevice, HostCoalesce.Mode);
+        if(!(Value32 & HOST_COALESCE_ENABLE))
+        {
+            break;
+        }
+        MM_Wait(10);
+    }
+
+    /* Host coalescing configurations. */
+    REG_WR(pDevice, HostCoalesce.RxCoalescingTicks, pDevice->RxCoalescingTicks);
+    REG_WR(pDevice, HostCoalesce.TxCoalescingTicks, pDevice->TxCoalescingTicks);
+    REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFrames,
+        pDevice->RxMaxCoalescedFrames);
+    REG_WR(pDevice, HostCoalesce.TxMaxCoalescedFrames,
+        pDevice->TxMaxCoalescedFrames);
+    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. */
+    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);
+
+    /* Enable the Receive List Selector state machine. */
+    REG_WR(pDevice, RcvListSel.Mode, RCV_LIST_SEL_MODE_ENABLE |
+        RCV_LIST_SEL_MODE_ATTN_ENABLE);
+
+    /* Enable transmit DMA, clear statistics. */
+    pDevice->MacMode =  MAC_MODE_ENABLE_TX_STATISTICS |
+        MAC_MODE_ENABLE_RX_STATISTICS | MAC_MODE_ENABLE_TDE |
+        MAC_MODE_ENABLE_RDE | MAC_MODE_ENABLE_FHDE;
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode |
+        MAC_MODE_CLEAR_RX_STATISTICS | MAC_MODE_CLEAR_TX_STATISTICS);
+
+    /* GRC miscellaneous local control register. */
+    pDevice->GrcLocalCtrl = GRC_MISC_LOCAL_CTRL_INT_ON_ATTN |
+        GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM;
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+    {
+        pDevice->GrcLocalCtrl |= GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+            GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1;
+    }
+
+    REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl);
+    MM_Wait(40);
+
+    /* Reset RX counters. */
+    for(j = 0; j < sizeof(LM_RX_COUNTERS); j++)
+    {
+        ((PLM_UINT8) &pDevice->RxCounters)[j] = 0;
+    }
+
+    /* Reset TX counters. */
+    for(j = 0; j < sizeof(LM_TX_COUNTERS); j++)
+    {
+        ((PLM_UINT8) &pDevice->TxCounters)[j] = 0;
+    }
+
+    MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 0);
+
+    /* 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;
+    REG_WR(pDevice, DmaWrite.Mode, Value32);
+
+    if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))
+    {
+        if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+        {
+            Value16 = REG_RD(pDevice, PciCfg.PciXCommand);
+            Value16 &= ~(PCIX_CMD_MAX_SPLIT_MASK | PCIX_CMD_MAX_BURST_MASK);
+            Value16 |= ((PCIX_CMD_MAX_BURST_CPIOB << PCIX_CMD_MAX_BURST_SHL) &
+                PCIX_CMD_MAX_BURST_MASK);
+            if (pDevice->SplitModeEnable == SPLIT_MODE_ENABLE)
+            {
+                Value16 |= (pDevice->SplitModeMaxReq << PCIX_CMD_MAX_SPLIT_SHL)
+                   & PCIX_CMD_MAX_SPLIT_MASK;
+            }
+            REG_WR(pDevice, PciCfg.PciXCommand, Value16);
+        }
+    }
+
+    /* Enable the Read DMA state machine. */
+    Value32 = DMA_READ_MODE_ENABLE |
+        DMA_READ_MODE_TARGET_ABORT_ATTN_ENABLE |
+        DMA_READ_MODE_MASTER_ABORT_ATTN_ENABLE |
+        DMA_READ_MODE_PARITY_ERROR_ATTN_ENABLE |
+        DMA_READ_MODE_ADDR_OVERFLOW_ATTN_ENABLE |
+        DMA_READ_MODE_FIFO_OVERRUN_ATTN_ENABLE |
+        DMA_READ_MODE_FIFO_UNDERRUN_ATTN_ENABLE |
+        DMA_READ_MODE_FIFO_OVERREAD_ATTN_ENABLE |
+        DMA_READ_MODE_LONG_READ_ATTN_ENABLE;
+
+    if (pDevice->SplitModeEnable == SPLIT_MODE_ENABLE)
+    {
+        Value32 |= DMA_READ_MODE_SPLIT_ENABLE;
+    }
+    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);
+
+    /* Enable the Mbuf Cluster Free state machine. */
+    REG_WR(pDevice, MbufClusterFree.Mode, MBUF_CLUSTER_FREE_MODE_ENABLE);
+
+    /* Enable the Send Data Completion state machine. */
+    REG_WR(pDevice, SndDataComp.Mode, SND_DATA_COMP_MODE_ENABLE);
+
+    /* Enable the Send BD Completion state machine. */
+    REG_WR(pDevice, SndBdComp.Mode, SND_BD_COMP_MODE_ENABLE |
+        SND_BD_COMP_MODE_ATTN_ENABLE);
+
+    /* Enable the Receive BD Initiator state machine. */
+    REG_WR(pDevice, RcvBdIn.Mode, RCV_BD_IN_MODE_ENABLE |
+        RCV_BD_IN_MODE_BD_IN_DIABLED_RCB_ATTN_ENABLE);
+
+    /* Enable the Receive Data and Receive BD Initiator state machine. */
+    REG_WR(pDevice, RcvDataBdIn.Mode, RCV_DATA_BD_IN_MODE_ENABLE |
+        RCV_DATA_BD_IN_MODE_INVALID_RING_SIZE);
+
+    /* Enable the Send Data Initiator state machine. */
+    REG_WR(pDevice, SndDataIn.Mode, T3_SND_DATA_IN_MODE_ENABLE);
+
+    /* Enable the Send BD Initiator state machine. */
+    REG_WR(pDevice, SndBdIn.Mode, SND_BD_IN_MODE_ENABLE |
+        SND_BD_IN_MODE_ATTN_ENABLE);
+
+    /* Enable the Send BD Selector state machine. */
+    REG_WR(pDevice, SndBdSel.Mode, SND_BD_SEL_MODE_ENABLE |
+        SND_BD_SEL_MODE_ATTN_ENABLE);
+
+#if INCLUDE_5701_AX_FIX
+    /* Load the firmware for the 5701_A0 workaround. */
+    if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0)
+    {
+        LM_LoadRlsFirmware(pDevice);
+    }
+#endif
+
+    /* Enable the transmitter. */
+    pDevice->TxMode = TX_MODE_ENABLE;
+    REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode);
+    
+    /* Enable the receiver. */
+    pDevice->RxMode = RX_MODE_ENABLE;
+    REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+
+    if (pDevice->RestoreOnWakeUp)
+    {
+        pDevice->RestoreOnWakeUp = FALSE;
+        pDevice->DisableAutoNeg = pDevice->WakeUpDisableAutoNeg;
+        pDevice->RequestedMediaType = pDevice->WakeUpRequestedMediaType;
+    }
+
+    /* Disable auto polling. */
+    pDevice->MiMode = 0xc0000;
+    REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+        T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+    {
+        Value32 = LED_CTRL_PHY_MODE_1;
+    }
+    else
+    {
+        if(pDevice->LedMode == LED_MODE_OUTPUT)
+        {
+            Value32 = LED_CTRL_PHY_MODE_2;
+        }
+        else
+        {
+            Value32 = LED_CTRL_PHY_MODE_1;
+        }
+    }
+    REG_WR(pDevice, MacCtrl.LedCtrl, Value32);
+    
+    /* Activate Link to enable MAC state machine */
+    REG_WR(pDevice, MacCtrl.MiStatus, MI_STATUS_ENABLE_LINK_STATUS_ATTN);
+
+    if (pDevice->EnableTbi)
+    {
+        REG_WR(pDevice, MacCtrl.RxMode, RX_MODE_RESET);
+        MM_Wait(10);
+        REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+        if (pDevice->ChipRevId == T3_CHIP_ID_5703_A1)
+        {
+            REG_WR(pDevice, MacCtrl.SerdesCfg, 0x616000);
+        }
+    }
+    /* Setup the phy chip. */
+    LM_SetupPhy(pDevice);
+
+    if (!pDevice->EnableTbi) {
+        /* Clear CRC stats */
+        LM_ReadPhy(pDevice, 0x1e, &Value32);
+        LM_WritePhy(pDevice, 0x1e, Value32 | 0x8000);
+        LM_ReadPhy(pDevice, 0x14, &Value32);
+    }
+
+    /* Set up the receive mask. */
+    LM_SetReceiveMask(pDevice, pDevice->ReceiveMask);
+
+    /* Queue Rx packet buffers. */
+    if(pDevice->QueueRxPackets)
+    {
+        LM_QueueRxPackets(pDevice);
+    }
+
+    /* Enable interrupt to the host. */
+    if(pDevice->InitDone)
+    {
+        LM_EnableInterrupt(pDevice);
+    }
+
+    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);
+
+    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)
+{
+    REG_WR(pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl &
+        ~MISC_HOST_CTRL_MASK_PCI_INT);
+    MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 0);
+
+    if(pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED)
+    {
+        REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+            GRC_MISC_LOCAL_CTRL_SET_INT);
+    }
+
+    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                                                       */
+/******************************************************************************/
+#if 0
+LM_STATUS
+LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+    LM_UINT32 FragCount;
+    PT3_SND_BD pSendBd;
+    PT3_SND_BD pShadowSendBd;
+    LM_UINT32 Value32, Len;
+    LM_UINT32 Idx;
+
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) {
+        return LM_5700SendPacket(pDevice, pPacket);
+    }
+
+    /* Update the SendBdLeft count. */
+    atomic_sub(pPacket->u.Tx.FragCount, &pDevice->SendBdLeft);
+
+    /* Initalize the send buffer descriptors. */
+    Idx = pDevice->SendProdIdx;
+
+    pSendBd = &pDevice->pSendBdVirt[Idx];
+
+    /* Next producer index. */
+    if (pDevice->NicSendBd == TRUE)
+    {
+        T3_64BIT_HOST_ADDR paddr;
+
+        pShadowSendBd = &pDevice->ShadowSendBd[Idx];
+        for(FragCount = 0; ; )
+        {
+            MM_MapTxDma(pDevice, pPacket, &paddr, &Len, FragCount);
+            /* Initialize the pointer to the send buffer fragment. */
+            if (paddr.High != pShadowSendBd->HostAddr.High)
+            {
+                __raw_writel(paddr.High, &(pSendBd->HostAddr.High));
+                pShadowSendBd->HostAddr.High = paddr.High;
+            }
+            __raw_writel(paddr.Low, &(pSendBd->HostAddr.Low));
+
+            /* Setup the control flags and send buffer size. */
+            Value32 = (Len << 16) | pPacket->Flags;
+
+            Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+
+            FragCount++;
+            if (FragCount >= pPacket->u.Tx.FragCount)
+            {
+                Value32 |= SND_BD_FLAG_END;
+                if (Value32 != pShadowSendBd->u1.Len_Flags)
+                {
+                    __raw_writel(Value32, &(pSendBd->u1.Len_Flags));
+                    pShadowSendBd->u1.Len_Flags = Value32;
+                }
+                if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) {
+                    __raw_writel(pPacket->VlanTag, &(pSendBd->u2.VlanTag));
+                }
+                break;
+            }
+            else
+            {
+                if (Value32 != pShadowSendBd->u1.Len_Flags)
+                {
+                    __raw_writel(Value32, &(pSendBd->u1.Len_Flags));
+                    pShadowSendBd->u1.Len_Flags = Value32;
+                }
+                if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) {
+                    __raw_writel(pPacket->VlanTag, &(pSendBd->u2.VlanTag));
+                }
+            }
+
+            pSendBd++;
+            pShadowSendBd++;
+            if (Idx == 0)
+            {
+                pSendBd = &pDevice->pSendBdVirt[0];
+                pShadowSendBd = &pDevice->ShadowSendBd[0];
+            }
+        } /* for */
+
+        /* Put the packet descriptor in the ActiveQ. */
+        QQ_PushTail(&pDevice->TxPacketActiveQ.Container, pPacket);
+
+        wmb();
+        MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, Idx);
+
+    }
+    else
+    {
+        for(FragCount = 0; ; )
+        {
+            /* 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;
+
+            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)
+            {
+                pSendBd = &pDevice->pSendBdVirt[0];
+            }
+        } /* for */
+
+        /* Put the packet descriptor in the ActiveQ. */
+        QQ_PushTail(&pDevice->TxPacketActiveQ.Container, pPacket);
+
+        wmb();
+        MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, Idx);
+
+    }
+
+    /* Update the producer index. */
+    pDevice->SendProdIdx = Idx;
+
+    return LM_STATUS_SUCCESS;
+}
+#endif
+
+LM_STATUS
+LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+    LM_UINT32 FragCount;
+    PT3_SND_BD pSendBd, pTmpSendBd, pShadowSendBd;
+    T3_SND_BD NicSendBdArr[MAX_FRAGMENT_COUNT];
+    LM_UINT32 StartIdx, Idx;
+
+    while (1)
+    {
+        /* Initalize the send buffer descriptors. */
+        StartIdx = Idx = pDevice->SendProdIdx;
+
+        if (pDevice->NicSendBd)
+        {
+            pTmpSendBd = pSendBd = &NicSendBdArr[0];
+        }
+        else
+        {
+            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;
+
+            Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+                
+            FragCount++;
+            if (FragCount >= pPacket->u.Tx.FragCount)
+            {
+                pSendBd->u1.Len_Flags = Value32 | SND_BD_FLAG_END;
+                break;
+            }
+            else
+            {
+                pSendBd->u1.Len_Flags = Value32;
+            }
+            pSendBd++;
+            if ((Idx == 0) && !pDevice->NicSendBd)
+            {
+                pSendBd = &pDevice->pSendBdVirt[0];
+            }
+        } /* for */
+        if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+        {
+            if (LM_Test4GBoundary(pDevice, pPacket, pTmpSendBd) ==
+                LM_STATUS_SUCCESS)
+            {
+                if (MM_CoalesceTxBuffer(pDevice, pPacket) != LM_STATUS_SUCCESS)
+                {
+                    QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket);
+                    return LM_STATUS_FAILURE;
+                }
+                continue;
+            }
+        }
+        break;
+    }
+    /* Put the packet descriptor in the ActiveQ. */
+    QQ_PushTail(&pDevice->TxPacketActiveQ.Container, pPacket);
+
+    if (pDevice->NicSendBd)
+    {
+        pSendBd = &pDevice->pSendBdVirt[StartIdx];
+        pShadowSendBd = &pDevice->ShadowSendBd[StartIdx];
+
+        while (StartIdx != Idx)
+        {
+            LM_UINT32 Value32;
+
+            if ((Value32 = pTmpSendBd->HostAddr.High) !=
+                pShadowSendBd->HostAddr.High)
+            {
+                __raw_writel(Value32, &(pSendBd->HostAddr.High));
+                pShadowSendBd->HostAddr.High = Value32;
+            }
+
+            __raw_writel(pTmpSendBd->HostAddr.Low, &(pSendBd->HostAddr.Low));
+
+            if ((Value32 = pTmpSendBd->u1.Len_Flags) !=
+                pShadowSendBd->u1.Len_Flags)
+            {
+                __raw_writel(Value32, &(pSendBd->u1.Len_Flags));
+                pShadowSendBd->u1.Len_Flags = Value32;
+            }
+
+            if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG)
+            {
+                __raw_writel(pTmpSendBd->u2.VlanTag, &(pSendBd->u2.VlanTag));
+            }
+
+            StartIdx = (StartIdx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+            if (StartIdx == 0)
+                pSendBd = &pDevice->pSendBdVirt[0];
+            else
+                pSendBd++;
+            pTmpSendBd++;
+        }
+        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);
+        }
+    }
+    else
+    {
+        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);
+        }
+    }
+
+    /* Update the SendBdLeft count. */
+    atomic_sub(pPacket->u.Tx.FragCount, &pDevice->SendBdLeft);
+
+    /* Update the producer index. */
+    pDevice->SendProdIdx = Idx;
+
+    return LM_STATUS_SUCCESS;
+}
+
+STATIC LM_STATUS
+LM_Test4GBoundary(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket,
+    PT3_SND_BD pSendBd)
+{
+    int FragCount;
+    LM_UINT32 Idx, Base, Len;
+
+    Idx = pDevice->SendProdIdx;
+    for(FragCount = 0; ; )
+    {
+        Len = pSendBd->u1.Len_Flags >> 16;
+        if (((Base = pSendBd->HostAddr.Low) > 0xffffdcc0) &&
+            (pSendBd->HostAddr.High == 0) &&
+            ((Base + 8 + Len) < Base))
+        {
+            return LM_STATUS_SUCCESS;
+        }
+        FragCount++;
+        if (FragCount >= pPacket->u.Tx.FragCount)
+        {
+            break;
+        }
+        pSendBd++;
+        if (!pDevice->NicSendBd)
+        {
+            Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+            if (Idx == 0)
+            {
+                pSendBd = &pDevice->pSendBdVirt[0];
+            }
+        }
+    }
+    return LM_STATUS_FAILURE;
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static unsigned long
+ComputeCrc32(
+unsigned char *pBuffer,
+unsigned long BufferSize) {
+    unsigned long Reg;
+    unsigned long Tmp;
+    unsigned long j, k;
+
+    Reg = 0xffffffff;
+
+    for(j = 0; j < BufferSize; j++)
+    {
+        Reg ^= pBuffer[j];
+
+        for(k = 0; k < 8; k++)
+        {
+            Tmp = Reg & 0x01;
+
+            Reg >>= 1;
+
+            if(Tmp)
+            {
+                Reg ^= 0xedb88320;
+            }
+        }
+    }
+
+    return ~Reg;
+} /* ComputeCrc32 */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine sets the receive control register according to ReceiveMask */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_SetReceiveMask(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 Mask) {
+    LM_UINT32 ReceiveMask;
+    LM_UINT32 RxMode;
+    LM_UINT32 j, k;
+
+    ReceiveMask = Mask;
+
+    RxMode = pDevice->RxMode;
+
+    if(Mask & LM_ACCEPT_UNICAST)
+    {
+        Mask &= ~LM_ACCEPT_UNICAST;
+    }
+
+    if(Mask & LM_ACCEPT_MULTICAST)
+    {
+        Mask &= ~LM_ACCEPT_MULTICAST;
+    }
+
+    if(Mask & LM_ACCEPT_ALL_MULTICAST)
+    {
+        Mask &= ~LM_ACCEPT_ALL_MULTICAST;
+    }
+
+    if(Mask & LM_ACCEPT_BROADCAST)
+    {
+        Mask &= ~LM_ACCEPT_BROADCAST;
+    }
+
+    RxMode &= ~RX_MODE_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->RxMode = RxMode;
+    REG_WR(pDevice, MacCtrl.RxMode, RxMode);
+
+    pDevice->ReceiveMask = ReceiveMask;
+
+    /* Set up the MC hash table. */
+    if(ReceiveMask & LM_ACCEPT_ALL_MULTICAST)
+    {
+        for(k = 0; k < 4; k++)
+        {
+            REG_WR(pDevice, MacCtrl.HashReg[k], 0xffffffff);
+        }
+    }
+    else if(ReceiveMask & LM_ACCEPT_MULTICAST)
+    {
+        LM_UINT32 HashReg[4];
+
+        HashReg[0] = 0; HashReg[1] = 0; HashReg[2] = 0; HashReg[3] = 0;
+        for(j = 0; j < pDevice->McEntryCount; j++)
+        {
+            LM_UINT32 RegIndex;
+            LM_UINT32 Bitpos;
+            LM_UINT32 Crc32;
+
+            Crc32 = ComputeCrc32(pDevice->McTable[j], ETHERNET_ADDRESS_SIZE);
+
+            /* The most significant 7 bits of the CRC32 (no inversion), */
+            /* are used to index into one of the possible 128 bit positions. */
+            Bitpos = ~Crc32 & 0x7f;
+
+            /* Hash register index. */
+            RegIndex = (Bitpos & 0x60) >> 5;
+
+            /* Bit to turn on within a hash register. */
+            Bitpos &= 0x1f;
+
+            /* Enable the multicast bit. */
+            HashReg[RegIndex] |= (1 << Bitpos);
+        }
+
+        /* REV_AX has problem with multicast filtering where it uses both */
+        /* DA and SA to perform hashing. */
+        for(k = 0; k < 4; k++)
+        {
+            REG_WR(pDevice, MacCtrl.HashReg[k], HashReg[k]);
+        }
+    }
+    else
+    {
+        /* Reject all multicast frames. */
+        for(j = 0; j < 4; j++)
+        {
+            REG_WR(pDevice, MacCtrl.HashReg[j], 0);
+        }
+    }
+
+    /* By default, Tigon3 will accept broadcast frames.  We need to setup */
+    if(ReceiveMask & LM_ACCEPT_BROADCAST)
+    {
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Rule,
+            REJECT_BROADCAST_RULE1_RULE & RCV_DISABLE_RULE_MASK);
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Value,
+            REJECT_BROADCAST_RULE1_VALUE & RCV_DISABLE_RULE_MASK);
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Rule,
+            REJECT_BROADCAST_RULE1_RULE & RCV_DISABLE_RULE_MASK);
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Value,
+            REJECT_BROADCAST_RULE1_VALUE & RCV_DISABLE_RULE_MASK);
+    }
+    else
+    {
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Rule, 
+            REJECT_BROADCAST_RULE1_RULE);
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Value, 
+            REJECT_BROADCAST_RULE1_VALUE);
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Rule, 
+            REJECT_BROADCAST_RULE2_RULE);
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Value, 
+            REJECT_BROADCAST_RULE2_VALUE);
+    }
+
+    /* disable the rest of the rules. */
+    for(j = RCV_LAST_RULE_IDX; j < 16; 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);
+
+    /* Disable all the state machines. */
+    LM_CntrlBlock(pDevice,T3_BLOCK_MAC_RX_ENGINE,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_RX_BD_INITIATOR,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_RX_LIST_PLMT,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_RX_LIST_SELECTOR,LM_DISABLE);  
+    LM_CntrlBlock(pDevice,T3_BLOCK_RX_DATA_INITIATOR,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_RX_DATA_COMP,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_RX_BD_COMP,LM_DISABLE);
+
+    LM_CntrlBlock(pDevice,T3_BLOCK_SEND_BD_SELECTOR,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_SEND_BD_INITIATOR,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_SEND_DATA_INITIATOR,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_DMA_RD,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_SEND_DATA_COMP,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_DMA_COMP,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_SEND_BD_COMP,LM_DISABLE);
+
+    /* Clear TDE bit */
+    pDevice->MacMode &= ~MAC_MODE_ENABLE_TDE;
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+
+    LM_CntrlBlock(pDevice,T3_BLOCK_MAC_TX_ENGINE,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_HOST_COALESING,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_DMA_WR,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_MBUF_CLUSTER_FREE,LM_DISABLE);
+
+    /* Reset all FTQs */
+    REG_WR(pDevice, Ftq.Reset, 0xffffffff);
+    REG_WR(pDevice, Ftq.Reset, 0x0);
+
+    LM_CntrlBlock(pDevice,T3_BLOCK_MBUF_MANAGER,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_MEM_ARBITOR,LM_DISABLE);
+
+    MM_ACQUIRE_INT_LOCK(pDevice);
+
+    /* Abort packets that have already queued to go out. */
+    pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->TxPacketActiveQ.Container);
+    while(pPacket)
+    {
+
+        pPacket->PacketStatus = LM_STATUS_TRANSMIT_ABORTED;
+        pDevice->TxCounters.TxPacketAbortedCnt++;
+
+        atomic_add(pPacket->u.Tx.FragCount, &pDevice->SendBdLeft);
+
+        QQ_PushTail(&pDevice->TxPacketXmittedQ.Container, pPacket);
+
+        pPacket = (PLM_PACKET) 
+            QQ_PopHead(&pDevice->TxPacketActiveQ.Container);
+    }
+
+    /* Cleanup the receive return rings. */
+    LM_ServiceRxInterrupt(pDevice);
+
+    /* Don't want to indicate rx packets in Ndis miniport shutdown context. */
+    /* Doing so may cause system crash. */
+    if(!pDevice->ShuttingDown)
+    {
+        /* Indicate packets to the protocol. */
+        MM_IndicateTxPackets(pDevice);
+
+        /* Indicate received packets to the protocols. */
+        MM_IndicateRxPackets(pDevice);
+    }
+    else
+    {
+        /* Move the receive packet descriptors in the ReceivedQ to the */
+        /* free queue. */
+        for(; ;)
+        {
+            pPacket = (PLM_PACKET) QQ_PopHead(
+                &pDevice->RxPacketReceivedQ.Container);
+            if(pPacket == NULL)
+            {
+                break;
+            }
+            QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+        }
+    }
+
+    /* Clean up the Std Receive Producer ring. */
+    Idx = pDevice->pStatusBlkVirt->RcvStdConIdx;
+
+    while(Idx != pDevice->RxStdProdIdx) {
+        pPacket = (PLM_PACKET) (MM_UINT_PTR(pDevice->pPacketDescBase) +
+            MM_UINT_PTR(pDevice->pRxStdBdVirt[Idx].Opaque));
+
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+        Idx = (Idx + 1) & T3_STD_RCV_RCB_ENTRY_COUNT_MASK;
+    } /* while */
+
+    /* Reinitialize our copy of the indices. */
+    pDevice->RxStdProdIdx = 0;
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    /* Clean up the Jumbo Receive Producer ring. */
+    Idx = pDevice->pStatusBlkVirt->RcvJumboConIdx;
+
+    while(Idx != pDevice->RxJumboProdIdx) {
+        pPacket = (PLM_PACKET) (MM_UINT_PTR(pDevice->pPacketDescBase) +
+            MM_UINT_PTR(pDevice->pRxJumboBdVirt[Idx].Opaque));
+
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+        Idx = (Idx + 1) & T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK;
+    } /* while */
+
+    /* Reinitialize our copy of the indices. */
+    pDevice->RxJumboProdIdx = 0;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    MM_RELEASE_INT_LOCK(pDevice);
+
+    /* Initialize the statistis Block */
+    pDevice->pStatusBlkVirt->Status = 0;
+    pDevice->pStatusBlkVirt->RcvStdConIdx = 0;
+    pDevice->pStatusBlkVirt->RcvJumboConIdx = 0;
+    pDevice->pStatusBlkVirt->RcvMiniConIdx = 0;
+
+    return LM_STATUS_SUCCESS;
+} /* LM_Abort */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    Disable the interrupt and put the transmitter and receiver engines in   */
+/*    an idle state.  Aborts all pending send requests and receive buffers.   */
+/*    Also free all the receive buffers.                                      */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_Halt(
+PLM_DEVICE_BLOCK pDevice) {
+    PLM_PACKET pPacket;
+    LM_UINT32 EntryCnt;
+
+    LM_Abort(pDevice);
+
+    /* Get the number of entries in the queue. */
+    EntryCnt = QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container);
+
+    /* Make sure all the packets have been accounted for. */
+    for(EntryCnt = 0; EntryCnt < pDevice->RxPacketDescCnt; EntryCnt++)
+    {
+        pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+        if (pPacket == 0)
+            break;
+
+        MM_FreeRxBuffer(pDevice, pPacket);
+
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+    }
+
+    LM_ResetChip(pDevice);
+
+    /* Restore PCI configuration registers. */
+    MM_WriteConfig32(pDevice, PCI_CACHE_LINE_SIZE_REG,
+        pDevice->SavedCacheLineReg);
+    LM_RegWrInd(pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, 
+        (pDevice->SubsystemId << 16) | pDevice->SubsystemVendorId);
+
+    /* Reprogram the MAC address. */
+    LM_SetMacAddress(pDevice, pDevice->NodeAddress);
+
+    return LM_STATUS_SUCCESS;
+} /* LM_Halt */
+
+
+STATIC LM_STATUS
+LM_ResetChip(PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32;
+    LM_UINT32 j;
+
+    /* Wait for access to the nvram interface before resetting.  This is */
+    /* a workaround to prevent EEPROM corruption. */
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 &&
+        T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701)
+    {
+        /* Request access to the flash interface. */
+        REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_SET1);
+
+        for(j = 0; j < 100000; j++)
+        {
+            Value32 = REG_RD(pDevice, Nvram.SwArb);
+            if(Value32 & SW_ARB_GNT1)
+            {
+                break;
+            }
+            MM_Wait(10);
+        }
+    }
+
+    /* Global reset. */
+    REG_WR(pDevice, Grc.MiscCfg, GRC_MISC_CFG_CORE_CLOCK_RESET);
+    MM_Wait(40); MM_Wait(40); MM_Wait(40);
+
+    /* make sure we re-enable indirect accesses */
+    MM_WriteConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG,
+        pDevice->MiscHostCtrl);
+
+    /* Set MAX PCI retry to zero. */
+    Value32 = T3_PCI_STATE_PCI_ROM_ENABLE | T3_PCI_STATE_PCI_ROM_RETRY_ENABLE;
+    if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+    {
+        if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))
+        {
+            Value32 |= T3_PCI_STATE_RETRY_SAME_DMA;
+        }
+    }
+    MM_WriteConfig32(pDevice, T3_PCI_STATE_REG, Value32);
+
+    /* Restore PCI command register. */
+    MM_WriteConfig32(pDevice, PCI_COMMAND_REG,
+        pDevice->PciCommandStatusWords);
+
+    /* Disable PCI-X relaxed ordering bit. */
+    MM_ReadConfig32(pDevice, PCIX_CAP_REG, &Value32);
+    Value32 &= ~PCIX_ENABLE_RELAXED_ORDERING;
+    MM_WriteConfig32(pDevice, PCIX_CAP_REG, Value32);
+
+    /* Enable memory arbiter. */
+    REG_WR(pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE);
+
+#ifdef BIG_ENDIAN_PCI      /* This from jfd */
+        Value32 = GRC_MODE_WORD_SWAP_DATA|
+                  GRC_MODE_WORD_SWAP_NON_FRAME_DATA;
+#else
+#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
+#endif
+    REG_WR(pDevice, Grc.Mode, Value32);
+
+    /* Prevent PXE from restarting. */
+    MEM_WR_OFFSET(pDevice, 0x0b50, T3_MAGIC_NUM);
+
+    if(pDevice->EnableTbi) {
+        pDevice->MacMode = MAC_MODE_PORT_MODE_TBI;
+        REG_WR(pDevice, MacCtrl.Mode, MAC_MODE_PORT_MODE_TBI);
+    }
+    else {
+        REG_WR(pDevice, MacCtrl.Mode, 0);
+    }
+
+    /* Wait for the firmware to finish initialization. */
+    for(j = 0; j < 100000; j++)
+    {
+        MM_Wait(10);
+
+        Value32 = MEM_RD_OFFSET(pDevice, 0x0b50);
+        if(Value32 == ~T3_MAGIC_NUM)
+        {
+            break;
+        }
+    }
+    return LM_STATUS_SUCCESS;
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static void
+LM_ServiceTxInterrupt(
+PLM_DEVICE_BLOCK pDevice) {
+    PLM_PACKET pPacket;
+    LM_UINT32 HwConIdx;
+    LM_UINT32 SwConIdx;
+
+    HwConIdx = pDevice->pStatusBlkVirt->Idx[0].SendConIdx;
+
+    /* Get our copy of the consumer index.  The buffer descriptors */
+    /* that are in between the consumer indices are freed. */
+    SwConIdx = pDevice->SendConIdx;
+
+    /* Move the packets from the TxPacketActiveQ that are sent out to */
+    /* the TxPacketXmittedQ.  Packets that are sent use the */
+    /* descriptors that are between SwConIdx and HwConIdx. */
+    while(SwConIdx != HwConIdx)
+    {
+        /* Get the packet that was sent from the TxPacketActiveQ. */
+        pPacket = (PLM_PACKET) QQ_PopHead(
+            &pDevice->TxPacketActiveQ.Container);
+
+        /* Set the return status. */
+        pPacket->PacketStatus = LM_STATUS_SUCCESS;
+
+        /* Put the packet in the TxPacketXmittedQ for indication later. */
+        QQ_PushTail(&pDevice->TxPacketXmittedQ.Container, pPacket);
+
+        /* Move to the next packet's BD. */
+        SwConIdx = (SwConIdx + pPacket->u.Tx.FragCount) & 
+            T3_SEND_RCB_ENTRY_COUNT_MASK;
+
+        /* Update the number of unused BDs. */
+        atomic_add(pPacket->u.Tx.FragCount, &pDevice->SendBdLeft);
+
+        /* Get the new updated HwConIdx. */
+        HwConIdx = pDevice->pStatusBlkVirt->Idx[0].SendConIdx;
+    } /* while */
+
+    /* Save the new SwConIdx. */
+    pDevice->SendConIdx = SwConIdx;
+
+} /* LM_ServiceTxInterrupt */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static void
+LM_ServiceRxInterrupt(
+PLM_DEVICE_BLOCK pDevice) {
+    PLM_PACKET pPacket;
+    PT3_RCV_BD pRcvBd;
+    LM_UINT32 HwRcvRetProdIdx;
+    LM_UINT32 SwRcvRetConIdx;
+
+    /* Loop thru the receive return rings for received packets. */
+    HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx;
+
+    SwRcvRetConIdx = pDevice->RcvRetConIdx;
+    while(SwRcvRetConIdx != HwRcvRetProdIdx)
+    {
+        pRcvBd = &pDevice->pRcvRetBdVirt[SwRcvRetConIdx];
+
+        /* Get the received packet descriptor. */
+        pPacket = (PLM_PACKET) (MM_UINT_PTR(pDevice->pPacketDescBase) +
+            MM_UINT_PTR(pRcvBd->Opaque));
+
+        /* Check the error flag. */
+        if(pRcvBd->ErrorFlag &&
+            pRcvBd->ErrorFlag != RCV_BD_ERR_ODD_NIBBLED_RCVD_MII)
+        {
+            pPacket->PacketStatus = LM_STATUS_FAILURE;
+
+            pDevice->RxCounters.RxPacketErrCnt++;
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_BAD_CRC)
+            {
+                pDevice->RxCounters.RxErrCrcCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_COLL_DETECT)
+            {
+                pDevice->RxCounters.RxErrCollCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_LINK_LOST_DURING_PKT)
+            {
+                pDevice->RxCounters.RxErrLinkLostCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_PHY_DECODE_ERR)
+            {
+                pDevice->RxCounters.RxErrPhyDecodeCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_ODD_NIBBLED_RCVD_MII)
+            {
+                pDevice->RxCounters.RxErrOddNibbleCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_MAC_ABORT)
+            {
+                pDevice->RxCounters.RxErrMacAbortCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_LEN_LT_64)
+            {
+                pDevice->RxCounters.RxErrShortPacketCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_TRUNC_NO_RESOURCES)
+            {
+                pDevice->RxCounters.RxErrNoResourceCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_GIANT_FRAME_RCVD)
+            {
+                pDevice->RxCounters.RxErrLargePacketCnt++;
+            }
+        }
+        else
+        {
+            pPacket->PacketStatus = LM_STATUS_SUCCESS;
+            pPacket->PacketSize = pRcvBd->Len - 4;
+
+            pPacket->Flags = pRcvBd->Flags;
+            if(pRcvBd->Flags & RCV_BD_FLAG_VLAN_TAG)
+            {
+                pPacket->VlanTag = pRcvBd->VlanTag;
+            }
+
+            pPacket->u.Rx.TcpUdpChecksum = pRcvBd->TcpUdpCksum;
+        }
+
+        /* Put the packet descriptor containing the received packet */
+        /* buffer in the RxPacketReceivedQ for indication later. */
+        QQ_PushTail(&pDevice->RxPacketReceivedQ.Container, pPacket);
+
+        /* Go to the next buffer descriptor. */
+        SwRcvRetConIdx = (SwRcvRetConIdx + 1) &
+            T3_RCV_RETURN_RCB_ENTRY_COUNT_MASK;
+
+        /* Get the updated HwRcvRetProdIdx. */
+        HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx;
+    } /* while */
+
+    pDevice->RcvRetConIdx = SwRcvRetConIdx;
+
+    /* Update the receive return ring consumer index. */
+    MB_REG_WR(pDevice, Mailbox.RcvRetConIdx[0].Low, SwRcvRetConIdx);
+} /* LM_ServiceRxInterrupt */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This is the interrupt event handler routine. It acknowledges all        */
+/*    pending interrupts and process all pending events.                      */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_ServiceInterrupts(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32;
+    int ServicePhyInt = FALSE;
+
+    /* Setup the phy chip whenever the link status changes. */
+    if(pDevice->LinkChngMode == T3_LINK_CHNG_MODE_USE_STATUS_REG)
+    {
+        Value32 = REG_RD(pDevice, MacCtrl.Status);
+        if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT)
+        {
+            if (Value32 & MAC_STATUS_MI_INTERRUPT)
+            {
+                ServicePhyInt = TRUE;
+            }
+        }
+        else if(Value32 & MAC_STATUS_LINK_STATE_CHANGED)
+        {
+            ServicePhyInt = TRUE;
+        }
+    }
+    else
+    {
+        if(pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_LINK_CHANGED_STATUS)
+        {
+            pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED |
+                (pDevice->pStatusBlkVirt->Status & ~STATUS_BLOCK_LINK_CHANGED_STATUS);
+            ServicePhyInt = TRUE;
+        }
+    }
+#if INCLUDE_TBI_SUPPORT
+    if (pDevice->IgnoreTbiLinkChange == TRUE)
+    {
+        ServicePhyInt = FALSE;
+    }
+#endif
+    if (ServicePhyInt == TRUE)
+    {
+        LM_SetupPhy(pDevice);
+    }
+
+    /* Service receive and transmit interrupts. */
+    LM_ServiceRxInterrupt(pDevice);
+    LM_ServiceTxInterrupt(pDevice);
+        
+    /* No spinlock for this queue since this routine is serialized. */
+    if(!QQ_Empty(&pDevice->RxPacketReceivedQ.Container))
+    {
+        /* Indicate receive packets. */
+        MM_IndicateRxPackets(pDevice);
+       /*       LM_QueueRxPackets(pDevice); */
+    }
+
+    /* No spinlock for this queue since this routine is serialized. */
+    if(!QQ_Empty(&pDevice->TxPacketXmittedQ.Container))
+    {
+        MM_IndicateTxPackets(pDevice);
+    }
+
+    return LM_STATUS_SUCCESS;
+} /* LM_ServiceInterrupts */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_MulticastAdd(
+PLM_DEVICE_BLOCK pDevice,
+PLM_UINT8 pMcAddress) {
+    PLM_UINT8 pEntry;
+    LM_UINT32 j;
+
+    pEntry = pDevice->McTable[0];
+    for(j = 0; j < pDevice->McEntryCount; j++)
+    {
+        if(IS_ETH_ADDRESS_EQUAL(pEntry, pMcAddress))
+        {
+            /* Found a match, increment the instance count. */
+            pEntry[LM_MC_INSTANCE_COUNT_INDEX] += 1;
+
+            return LM_STATUS_SUCCESS;
+        }
+
+        pEntry += LM_MC_ENTRY_SIZE;
+    }
+    
+    if(pDevice->McEntryCount >= LM_MAX_MC_TABLE_SIZE)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    pEntry = pDevice->McTable[pDevice->McEntryCount];
+
+    COPY_ETH_ADDRESS(pMcAddress, pEntry);
+    pEntry[LM_MC_INSTANCE_COUNT_INDEX] = 1;
+
+    pDevice->McEntryCount++;
+
+    LM_SetReceiveMask(pDevice, pDevice->ReceiveMask | LM_ACCEPT_MULTICAST);
+
+    return LM_STATUS_SUCCESS;
+} /* LM_MulticastAdd */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_MulticastDel(
+PLM_DEVICE_BLOCK pDevice,
+PLM_UINT8 pMcAddress) {
+    PLM_UINT8 pEntry;
+    LM_UINT32 j;
+
+    pEntry = pDevice->McTable[0];
+    for(j = 0; j < pDevice->McEntryCount; j++)
+    {
+        if(IS_ETH_ADDRESS_EQUAL(pEntry, pMcAddress))
+        {
+            /* Found a match, decrement the instance count. */
+            pEntry[LM_MC_INSTANCE_COUNT_INDEX] -= 1;
+
+            /* No more instance left, remove the address from the table. */
+            /* Move the last entry in the table to the delete slot. */
+            if(pEntry[LM_MC_INSTANCE_COUNT_INDEX] == 0 &&
+                pDevice->McEntryCount > 1)
+            {
+
+                COPY_ETH_ADDRESS(
+                    pDevice->McTable[pDevice->McEntryCount-1], pEntry);
+                pEntry[LM_MC_INSTANCE_COUNT_INDEX] =
+                    pDevice->McTable[pDevice->McEntryCount-1]
+                    [LM_MC_INSTANCE_COUNT_INDEX];
+            }
+            pDevice->McEntryCount--;
+
+            /* Update the receive mask if the table is empty. */
+            if(pDevice->McEntryCount == 0)
+            {
+                LM_SetReceiveMask(pDevice, 
+                    pDevice->ReceiveMask & ~LM_ACCEPT_MULTICAST);
+            }
+
+            return LM_STATUS_SUCCESS;
+        }
+
+        pEntry += LM_MC_ENTRY_SIZE;
+    }
+
+    return LM_STATUS_FAILURE;
+} /* LM_MulticastDel */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_MulticastClear(
+PLM_DEVICE_BLOCK pDevice) {
+    pDevice->McEntryCount = 0;
+
+    LM_SetReceiveMask(pDevice, pDevice->ReceiveMask & ~LM_ACCEPT_MULTICAST);
+
+    return LM_STATUS_SUCCESS;
+} /* LM_MulticastClear */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_SetMacAddress(
+    PLM_DEVICE_BLOCK pDevice,
+    PLM_UINT8 pMacAddress)
+{
+    LM_UINT32 j;
+
+    for(j = 0; j < 4; j++)
+    {
+        REG_WR(pDevice, MacCtrl.MacAddr[j].High,
+            (pMacAddress[0] << 8) | pMacAddress[1]);
+        REG_WR(pDevice, MacCtrl.MacAddr[j].Low,
+            (pMacAddress[2] << 24) | (pMacAddress[3] << 16) |
+            (pMacAddress[4] << 8) | pMacAddress[5]);
+    }
+
+    return LM_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    Sets up the default line speed, and duplex modes based on the requested */
+/*    media type.                                                             */
+/*                                                                            */
+/* Return:                                                                    */
+/*    None.                                                                   */
+/******************************************************************************/
+static LM_STATUS
+LM_TranslateRequestedMediaType(
+LM_REQUESTED_MEDIA_TYPE RequestedMediaType,
+PLM_MEDIA_TYPE pMediaType,
+PLM_LINE_SPEED pLineSpeed,
+PLM_DUPLEX_MODE pDuplexMode) {
+    *pMediaType = LM_MEDIA_TYPE_AUTO;
+    *pLineSpeed = LM_LINE_SPEED_UNKNOWN;
+    *pDuplexMode = LM_DUPLEX_MODE_UNKNOWN;
+
+    /* determine media type */
+    switch(RequestedMediaType) {
+        case LM_REQUESTED_MEDIA_TYPE_BNC:
+            *pMediaType = LM_MEDIA_TYPE_BNC;
+            *pLineSpeed = LM_LINE_SPEED_10MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_HALF;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_UTP_AUTO:
+            *pMediaType = LM_MEDIA_TYPE_UTP;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS:
+            *pMediaType = LM_MEDIA_TYPE_UTP;
+            *pLineSpeed = LM_LINE_SPEED_10MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_HALF;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX:
+            *pMediaType = LM_MEDIA_TYPE_UTP;
+            *pLineSpeed = LM_LINE_SPEED_10MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_FULL;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS:
+            *pMediaType = LM_MEDIA_TYPE_UTP;
+            *pLineSpeed = LM_LINE_SPEED_100MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_HALF;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX:
+            *pMediaType = LM_MEDIA_TYPE_UTP;
+            *pLineSpeed = LM_LINE_SPEED_100MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_FULL;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS:
+            *pMediaType = LM_MEDIA_TYPE_UTP;
+            *pLineSpeed = LM_LINE_SPEED_1000MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_HALF;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX:
+            *pMediaType = LM_MEDIA_TYPE_UTP;
+            *pLineSpeed = LM_LINE_SPEED_1000MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_FULL;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS:
+            *pMediaType = LM_MEDIA_TYPE_FIBER;
+            *pLineSpeed = LM_LINE_SPEED_100MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_HALF;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS_FULL_DUPLEX:
+            *pMediaType = LM_MEDIA_TYPE_FIBER;
+            *pLineSpeed = LM_LINE_SPEED_100MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_FULL;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS:
+            *pMediaType = LM_MEDIA_TYPE_FIBER;
+            *pLineSpeed = LM_LINE_SPEED_1000MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_HALF;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX:
+            *pMediaType = LM_MEDIA_TYPE_FIBER;
+            *pLineSpeed = LM_LINE_SPEED_1000MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_FULL;
+            break;
+
+        default:
+            break;
+    } /* switch */
+
+    return LM_STATUS_SUCCESS;
+} /* LM_TranslateRequestedMediaType */
+
+/******************************************************************************/
+/* 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;
+
+#if 1  /* jmb: bugfix -- moved here, out of code that sets initial pwr state */
+    LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x2);
+#endif
+    if((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
+    {
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+
+        if(!pDevice->InitDone)
+        {
+            Value32 = 0;
+        }
+
+        if(!(Value32 & PHY_STATUS_LINK_PASS))
+        {
+            LM_WritePhy(pDevice, BCM5401_AUX_CTRL,  0x0c20);
+
+            LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012);
+            LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1804);
+                
+            LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013);
+            LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1204);
+                
+            LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+            LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0132);
+
+            LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+            LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0232);
+                
+            LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f);
+            LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0a20);
+
+            LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+            for(j = 0; j < 1000; j++)
+            {
+                MM_Wait(10);
+
+                LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+                if(Value32 & PHY_STATUS_LINK_PASS)
+                {
+                    MM_Wait(40);
+                    break;
+                }
+            }
+
+            if((pDevice->PhyId & PHY_ID_REV_MASK) == PHY_BCM5401_B0_REV)
+            {
+                if(!(Value32 & PHY_STATUS_LINK_PASS) &&
+                    (pDevice->OldLineSpeed == LM_LINE_SPEED_1000MBPS))
+                {
+                    LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_PHY_RESET);
+                    for(j = 0; j < 100; j++)
+                    {
+                        MM_Wait(10);
+
+                        LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+                        if(!(Value32 & PHY_CTRL_PHY_RESET))
+                        {
+                            MM_Wait(40);
+                            break;
+                        }
+                    }
+
+                    LM_WritePhy(pDevice, BCM5401_AUX_CTRL,  0x0c20);
+
+                    LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012);
+                    LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1804);
+                        
+                    LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013);
+                    LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1204);
+                        
+                    LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+                    LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0132);
+
+                    LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+                    LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0232);
+                        
+                    LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f);
+                    LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0a20);
+                }
+            }
+        }
+    }
+    else if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+        pDevice->ChipRevId == T3_CHIP_ID_5701_B0)
+    {
+        /* Bug: 5701 A0, B0 TX CRC workaround. */
+        LM_WritePhy(pDevice, 0x15, 0x0a75);
+        LM_WritePhy(pDevice, 0x1c, 0x8c68);
+        LM_WritePhy(pDevice, 0x1c, 0x8d68);
+        LM_WritePhy(pDevice, 0x1c, 0x8c68);
+    }
+
+    /* Acknowledge interrupts. */
+    LM_ReadPhy(pDevice, BCM540X_INT_STATUS_REG, &Value32);
+    LM_ReadPhy(pDevice, BCM540X_INT_STATUS_REG, &Value32);
+
+    /* Configure the interrupt mask. */
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT)
+    {
+        LM_WritePhy(pDevice, BCM540X_INT_MASK_REG, ~BCM540X_INT_LINK_CHANGE);
+    }
+
+    /* Configure PHY led mode. */
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701 ||
+        (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700))
+    {
+        if(pDevice->LedMode == LED_MODE_THREE_LINK)
+        {
+            LM_WritePhy(pDevice, BCM540X_EXT_CTRL_REG, 
+                BCM540X_EXT_CTRL_LINK3_LED_MODE);
+        }
+        else
+        {
+            LM_WritePhy(pDevice, BCM540X_EXT_CTRL_REG, 0);
+        }
+    }
+
+    CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+
+    /* Get current link and duplex mode. */
+    for(j = 0; j < 100; j++)
+    {
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+
+        if(Value32 & PHY_STATUS_LINK_PASS)
+        {
+            break;
+        }
+        MM_Wait(40);
+    }
+
+    if(Value32 & PHY_STATUS_LINK_PASS)
+    {
+
+        /* Determine the current line and duplex settings. */
+        LM_ReadPhy(pDevice, BCM540X_AUX_STATUS_REG, &Value32);
+        for(j = 0; j < 2000; j++)
+        {
+            MM_Wait(10);
+
+            LM_ReadPhy(pDevice, BCM540X_AUX_STATUS_REG, &Value32);
+            if(Value32)
+            {
+                break;
+            }
+        }
+
+        switch(Value32 & BCM540X_AUX_SPEED_MASK)
+        {
+            case BCM540X_AUX_10BASET_HD:
+                CurrentLineSpeed = LM_LINE_SPEED_10MBPS;
+                CurrentDuplexMode = LM_DUPLEX_MODE_HALF;
+                break;
+
+            case BCM540X_AUX_10BASET_FD:
+                CurrentLineSpeed = LM_LINE_SPEED_10MBPS;
+                CurrentDuplexMode = LM_DUPLEX_MODE_FULL;
+                break;
+
+            case BCM540X_AUX_100BASETX_HD:
+                CurrentLineSpeed = LM_LINE_SPEED_100MBPS;
+                CurrentDuplexMode = LM_DUPLEX_MODE_HALF;
+                break;
+
+            case BCM540X_AUX_100BASETX_FD:
+                CurrentLineSpeed = LM_LINE_SPEED_100MBPS;
+                CurrentDuplexMode = LM_DUPLEX_MODE_FULL;
+                break;
+
+            case BCM540X_AUX_100BASET_HD:
+                CurrentLineSpeed = LM_LINE_SPEED_1000MBPS;
+                CurrentDuplexMode = LM_DUPLEX_MODE_HALF;
+                break;
+
+            case BCM540X_AUX_100BASET_FD:
+                CurrentLineSpeed = LM_LINE_SPEED_1000MBPS;
+                CurrentDuplexMode = LM_DUPLEX_MODE_FULL;
+                break;
+
+            default:
+
+                CurrentLineSpeed = LM_LINE_SPEED_UNKNOWN;
+                CurrentDuplexMode = LM_DUPLEX_MODE_UNKNOWN;
+                break;
+        }
+
+        /* Make sure we are in auto-neg mode. */
+        for (j = 0; j < 200; j++)
+        {
+            LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+            if(Value32 && Value32 != 0x7fff)
+            {
+                break;
+            }
+
+            if(Value32 == 0 && pDevice->RequestedMediaType == 
+                LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS)
+            {
+                break;
+            }
+
+            MM_Wait(10);
+        }
+
+        /* Use the current line settings for "auto" mode. */
+        if(pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO ||
+            pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_UTP_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. */
+                LM_ReadPhy(pDevice, BCM540X_1000BASET_CTRL_REG, &Value32);
+                pDevice->advertising1000 = Value32;
+                /* 5702FE supports 10/100Mb only. */
+                if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5703 ||
+                    pDevice->BondId != GRC_MISC_BD_ID_5702FE)
+                {
+                    if(!(Value32 & (BCM540X_AN_AD_1000BASET_HALF |
+                        BCM540X_AN_AD_1000BASET_FULL)))
+                    {
+                        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;
+        pDevice->MediaType = LM_MEDIA_TYPE_UTP;
+    }
+
+    return CurrentLinkStatus;
+} /* LM_InitBcm540xPhy */
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_SetFlowControl(
+    PLM_DEVICE_BLOCK pDevice,
+    LM_UINT32 LocalPhyAd,
+    LM_UINT32 RemotePhyAd)
+{
+    LM_FLOW_CONTROL FlowCap;
+
+    /* Resolve flow control. */
+    FlowCap = LM_FLOW_CONTROL_NONE;
+
+    /* See Table 28B-3 of 802.3ab-1999 spec. */
+    if(pDevice->FlowControlCap & LM_FLOW_CONTROL_AUTO_PAUSE)
+    {
+        if(LocalPhyAd & PHY_AN_AD_PAUSE_CAPABLE)
+        {
+            if(LocalPhyAd & PHY_AN_AD_ASYM_PAUSE)
+            {
+                if(RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE)
+                {
+                    FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE |
+                        LM_FLOW_CONTROL_RECEIVE_PAUSE;
+                }
+                else if(RemotePhyAd & PHY_LINK_PARTNER_ASYM_PAUSE)
+                {
+                    FlowCap = LM_FLOW_CONTROL_RECEIVE_PAUSE;
+                }
+            }
+            else
+            {
+                if(RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE)
+                {
+                    FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE |
+                        LM_FLOW_CONTROL_RECEIVE_PAUSE;
+                }
+            }
+        }
+        else if(LocalPhyAd & PHY_AN_AD_ASYM_PAUSE)
+        {
+            if((RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE) &&
+                (RemotePhyAd & PHY_LINK_PARTNER_ASYM_PAUSE))
+            {
+                FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE;
+            }
+        }
+    }
+    else
+    {
+        FlowCap = pDevice->FlowControlCap;
+    }
+
+    /* Enable/disable rx PAUSE. */
+    pDevice->RxMode &= ~RX_MODE_ENABLE_FLOW_CONTROL;
+    if(FlowCap & LM_FLOW_CONTROL_RECEIVE_PAUSE &&
+        (pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE ||
+        pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE))
+    {
+        pDevice->FlowControl |= LM_FLOW_CONTROL_RECEIVE_PAUSE;
+        pDevice->RxMode |= RX_MODE_ENABLE_FLOW_CONTROL;
+
+    }
+    REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+
+    /* Enable/disable tx PAUSE. */
+    pDevice->TxMode &= ~TX_MODE_ENABLE_FLOW_CONTROL;
+    if(FlowCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE &&
+        (pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE ||
+        pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE))
+    {
+        pDevice->FlowControl |= LM_FLOW_CONTROL_TRANSMIT_PAUSE;
+        pDevice->TxMode |= TX_MODE_ENABLE_FLOW_CONTROL;
+
+    }
+    REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode);
+
+    return LM_STATUS_SUCCESS;
+}
+
+
+#if INCLUDE_TBI_SUPPORT
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_InitBcm800xPhy(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32;
+    LM_UINT32 j;
+
+    Value32 = REG_RD(pDevice, MacCtrl.Status);
+
+    /* Reset the SERDES during init and when we have link. */
+    if(!pDevice->InitDone || Value32 & MAC_STATUS_PCS_SYNCED)
+    {
+        /* Set PLL lock range. */
+        LM_WritePhy(pDevice, 0x16, 0x8007);
+
+        /* Software reset. */
+        LM_WritePhy(pDevice, 0x00, 0x8000);
+
+        /* Wait for reset to complete. */
+        for(j = 0; j < 500; j++)
+        {
+            MM_Wait(10);
+        }
+
+        /* Config mode; seletct PMA/Ch 1 regs. */
+        LM_WritePhy(pDevice, 0x10, 0x8411);
+
+        /* Enable auto-lock and comdet, select txclk for tx. */
+        LM_WritePhy(pDevice, 0x11, 0x0a10);
+
+        LM_WritePhy(pDevice, 0x18, 0x00a0);
+        LM_WritePhy(pDevice, 0x16, 0x41ff);
+
+        /* Assert and deassert POR. */
+        LM_WritePhy(pDevice, 0x13, 0x0400);
+        MM_Wait(40);
+        LM_WritePhy(pDevice, 0x13, 0x0000);
+
+        LM_WritePhy(pDevice, 0x11, 0x0a50);
+        MM_Wait(40);
+        LM_WritePhy(pDevice, 0x11, 0x0a10);
+
+        /* Delay for signal to stabilize. */
+        for(j = 0; j < 15000; j++)
+        {
+            MM_Wait(10);
+        }
+
+        /* Deselect the channel register so we can read the PHY id later. */
+        LM_WritePhy(pDevice, 0x10, 0x8011);
+    }
+
+    return LM_STATUS_SUCCESS;
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_SetupFiberPhy(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_STATUS CurrentLinkStatus;
+    AUTONEG_STATUS AnStatus = 0;
+    LM_UINT32 Value32;
+    LM_UINT32 Cnt;
+    LM_UINT32 j, k;
+
+    pDevice->MacMode &= ~(MAC_MODE_HALF_DUPLEX | MAC_MODE_PORT_MODE_MASK);
+
+    /* Initialize the send_config register. */
+    REG_WR(pDevice, MacCtrl.TxAutoNeg, 0);
+
+    /* Enable TBI and full duplex mode. */
+    pDevice->MacMode |= MAC_MODE_PORT_MODE_TBI;
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+
+    /* Initialize the BCM8002 SERDES PHY. */
+    switch(pDevice->PhyId & PHY_ID_MASK)
+    {
+        case PHY_BCM8002_PHY_ID:
+            LM_InitBcm800xPhy(pDevice);
+            break;
+
+        default:
+            break;
+    }
+
+    /* Enable link change interrupt. */
+    REG_WR(pDevice, MacCtrl.MacEvent, MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN);
+
+    /* Default to link down. */
+    CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+
+    /* Get the link status. */
+    Value32 = REG_RD(pDevice, MacCtrl.Status);
+    if(Value32 & MAC_STATUS_PCS_SYNCED)
+    {
+        if((pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO) ||
+            (pDevice->DisableAutoNeg == FALSE))
+        {
+            /* auto-negotiation mode. */
+            /* Initialize the autoneg default capaiblities. */
+            AutonegInit(&pDevice->AnInfo);
+
+            /* Set the context pointer to point to the main device structure. */
+            pDevice->AnInfo.pContext = pDevice;
+
+            /* Setup flow control advertisement register. */
+            Value32 = GetPhyAdFlowCntrlSettings(pDevice);
+            if(Value32 & PHY_AN_AD_PAUSE_CAPABLE)
+            {
+                pDevice->AnInfo.mr_adv_sym_pause = 1;
+            }
+            else
+            {
+                pDevice->AnInfo.mr_adv_sym_pause = 0;
+            }
+
+            if(Value32 & PHY_AN_AD_ASYM_PAUSE)
+            {
+                pDevice->AnInfo.mr_adv_asym_pause = 1;
+            }
+            else
+            {
+                pDevice->AnInfo.mr_adv_asym_pause = 0;
+            }
+
+            /* Try to autoneg up to six times. */
+            if (pDevice->IgnoreTbiLinkChange)
+            {
+                Cnt = 1;
+            }
+            else
+            {
+                Cnt = 6;
+            }
+            for (j = 0; j < Cnt; j++)
+            {
+                REG_WR(pDevice, MacCtrl.TxAutoNeg, 0);
+
+                Value32 = pDevice->MacMode & ~MAC_MODE_PORT_MODE_MASK;
+                REG_WR(pDevice, MacCtrl.Mode, Value32);
+                MM_Wait(20);
+
+                REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode |
+                    MAC_MODE_SEND_CONFIGS);
+
+                MM_Wait(20);
+
+                pDevice->AnInfo.State = AN_STATE_UNKNOWN;
+                pDevice->AnInfo.CurrentTime_us = 0;
+
+                REG_WR(pDevice, Grc.Timer, 0);
+                for(k = 0; (pDevice->AnInfo.CurrentTime_us < 75000) &&
+                    (k < 75000); k++)
+                {
+                    AnStatus = Autoneg8023z(&pDevice->AnInfo);
+
+                    if((AnStatus == AUTONEG_STATUS_DONE) || 
+                        (AnStatus == AUTONEG_STATUS_FAILED))
+                    {
+                        break;
+                    }
+
+                    pDevice->AnInfo.CurrentTime_us = REG_RD(pDevice, Grc.Timer);
+                
+                }
+                if((AnStatus == AUTONEG_STATUS_DONE) || 
+                    (AnStatus == AUTONEG_STATUS_FAILED))
+                {
+                    break;
+                }
+                if (j >= 1)
+                {
+                    if (!(REG_RD(pDevice, MacCtrl.Status) &
+                        MAC_STATUS_PCS_SYNCED)) {
+                        break;
+                    }
+                }
+            }
+
+            /* Stop sending configs. */
+            MM_AnTxIdle(&pDevice->AnInfo);
+
+            /* Resolve flow control settings. */
+            if((AnStatus == AUTONEG_STATUS_DONE) &&
+                pDevice->AnInfo.mr_an_complete && pDevice->AnInfo.mr_link_ok &&
+                pDevice->AnInfo.mr_lp_adv_full_duplex)
+                {
+                LM_UINT32 RemotePhyAd;
+                LM_UINT32 LocalPhyAd;
+
+                LocalPhyAd = 0;
+                if(pDevice->AnInfo.mr_adv_sym_pause)
+                {
+                    LocalPhyAd |= PHY_AN_AD_PAUSE_CAPABLE;
+                }
+
+                if(pDevice->AnInfo.mr_adv_asym_pause)
+                {
+                    LocalPhyAd |= PHY_AN_AD_ASYM_PAUSE;
+                }
+
+                RemotePhyAd = 0;
+                if(pDevice->AnInfo.mr_lp_adv_sym_pause)
+                {
+                    RemotePhyAd |= PHY_LINK_PARTNER_PAUSE_CAPABLE;
+                }
+
+                if(pDevice->AnInfo.mr_lp_adv_asym_pause)
+                {
+                    RemotePhyAd |= PHY_LINK_PARTNER_ASYM_PAUSE;
+                }
+
+                LM_SetFlowControl(pDevice, LocalPhyAd, RemotePhyAd);
+
+                CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+            }
+            for (j = 0; j < 30; j++)
+            {
+                MM_Wait(20);
+                REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED |
+                    MAC_STATUS_CFG_CHANGED);
+                MM_Wait(20);
+                if ((REG_RD(pDevice, MacCtrl.Status) &
+                    (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)) == 0)
+                    break;
+            }
+            if (pDevice->PollTbiLink)
+            {
+                Value32 = REG_RD(pDevice, MacCtrl.Status);
+                if (Value32 & MAC_STATUS_RECEIVING_CFG)
+                {
+                    pDevice->IgnoreTbiLinkChange = TRUE;
+                }
+                else
+                {
+                    pDevice->IgnoreTbiLinkChange = FALSE;
+                }
+            }
+            Value32 = REG_RD(pDevice, MacCtrl.Status);
+            if (CurrentLinkStatus == LM_STATUS_LINK_DOWN &&
+                 (Value32 & MAC_STATUS_PCS_SYNCED) &&
+                 ((Value32 & MAC_STATUS_RECEIVING_CFG) == 0))
+            {
+                CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+            }
+        }
+        else
+        {
+            /* We are forcing line speed. */
+            pDevice->FlowControlCap &= ~LM_FLOW_CONTROL_AUTO_PAUSE;
+            LM_SetFlowControl(pDevice, 0, 0);
+
+            CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+            REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode |
+                MAC_MODE_SEND_CONFIGS);
+        }
+    }
+    /* Set the link polarity bit. */
+    pDevice->MacMode &= ~MAC_MODE_LINK_POLARITY;
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+
+    pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED |
+        (pDevice->pStatusBlkVirt->Status & ~STATUS_BLOCK_LINK_CHANGED_STATUS);
+
+    for (j = 0; j < 100; j++)
+    {
+        REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED |
+            MAC_STATUS_CFG_CHANGED);
+        MM_Wait(5);
+        if ((REG_RD(pDevice, MacCtrl.Status) &
+            (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)) == 0)
+            break;
+    }
+
+    Value32 = REG_RD(pDevice, MacCtrl.Status);
+    if((Value32 & MAC_STATUS_PCS_SYNCED) == 0)
+    {
+        CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+        if (pDevice->DisableAutoNeg == FALSE)
+        {
+            REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode |
+                MAC_MODE_SEND_CONFIGS);
+            MM_Wait(1);
+            REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+        }
+    }
+
+    /* Initialize the current link status. */
+    if(CurrentLinkStatus == LM_STATUS_LINK_ACTIVE)
+    {
+        pDevice->LineSpeed = LM_LINE_SPEED_1000MBPS;
+        pDevice->DuplexMode = LM_DUPLEX_MODE_FULL;
+        REG_WR(pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED |
+            LED_CTRL_1000MBPS_LED_ON);
+    }
+    else
+    {
+        pDevice->LineSpeed = LM_LINE_SPEED_UNKNOWN;
+        pDevice->DuplexMode = LM_DUPLEX_MODE_UNKNOWN;
+        REG_WR(pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED |
+            LED_CTRL_OVERRIDE_TRAFFIC_LED);
+    }
+
+    /* Indicate link status. */
+    if (pDevice->LinkStatus != CurrentLinkStatus) {
+        pDevice->LinkStatus = CurrentLinkStatus;
+        MM_IndicateStatus(pDevice, CurrentLinkStatus);
+    }
+
+    return LM_STATUS_SUCCESS;
+}
+#endif /* INCLUDE_TBI_SUPPORT */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_SetupCopperPhy(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_STATUS CurrentLinkStatus;
+    LM_UINT32 Value32;
+
+    /* Assume there is not link first. */
+    CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+
+    /* Disable phy link change attention. */
+    REG_WR(pDevice, MacCtrl.MacEvent, 0);
+
+    /* Clear link change attention. */
+    REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED |
+        MAC_STATUS_CFG_CHANGED);
+
+    /* Disable auto-polling for the moment. */
+    pDevice->MiMode = 0xc0000;
+    REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+    MM_Wait(40);
+
+    /* Determine the requested line speed and duplex. */
+    pDevice->OldLineSpeed = pDevice->LineSpeed;
+    LM_TranslateRequestedMediaType(pDevice->RequestedMediaType,
+        &pDevice->MediaType, &pDevice->LineSpeed, &pDevice->DuplexMode);
+
+    /* Initialize the phy chip. */
+    switch(pDevice->PhyId & PHY_ID_MASK)
+    {
+        case PHY_BCM5400_PHY_ID:
+        case PHY_BCM5401_PHY_ID:
+        case PHY_BCM5411_PHY_ID:
+        case PHY_BCM5701_PHY_ID:
+        case PHY_BCM5703_PHY_ID:
+        case PHY_BCM5704_PHY_ID:
+            CurrentLinkStatus = LM_InitBcm540xPhy(pDevice);
+            break;
+
+        default:
+            break;
+    }
+
+    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->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO ||
+                pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_UTP_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, pDevice->RequestedMediaType);
+
+        /* If we force line speed, we make get link right away. */
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+        if(Value32 & PHY_STATUS_LINK_PASS)
+        {
+            CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+        }
+    }
+
+    /* GMII interface. */
+    pDevice->MacMode &= ~MAC_MODE_PORT_MODE_MASK;
+    if(CurrentLinkStatus == LM_STATUS_LINK_ACTIVE)
+    {
+        if(pDevice->LineSpeed == LM_LINE_SPEED_100MBPS ||
+            pDevice->LineSpeed == LM_LINE_SPEED_10MBPS)
+        {
+            pDevice->MacMode |= MAC_MODE_PORT_MODE_MII;
+        }
+        else
+        {
+            pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII;
+        }
+    }
+    else {
+        pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII;
+    }
+
+    /* Set the MAC to operate in the appropriate duplex mode. */
+    pDevice->MacMode &= ~MAC_MODE_HALF_DUPLEX;
+    if(pDevice->DuplexMode == LM_DUPLEX_MODE_HALF)
+    {
+        pDevice->MacMode |= MAC_MODE_HALF_DUPLEX;
+    }
+
+    /* Set the link polarity bit. */
+    pDevice->MacMode &= ~MAC_MODE_LINK_POLARITY;
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+    {
+        if((pDevice->LedMode == LED_MODE_LINK10) ||
+             (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE &&
+             pDevice->LineSpeed == LM_LINE_SPEED_10MBPS))
+        {
+            pDevice->MacMode |= MAC_MODE_LINK_POLARITY;
+        }
+    }
+    else
+    {
+        if (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE)
+        {
+            pDevice->MacMode |= MAC_MODE_LINK_POLARITY;
+        }
+
+        /* Set LED mode. */
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            Value32 = LED_CTRL_PHY_MODE_1;
+        }
+        else
+        {
+            if(pDevice->LedMode == LED_MODE_OUTPUT)
+            {
+                Value32 = LED_CTRL_PHY_MODE_2;
+            }
+            else
+            {
+                Value32 = LED_CTRL_PHY_MODE_1;
+            }
+        }
+        REG_WR(pDevice, MacCtrl.LedCtrl, Value32);
+    }
+
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+
+    /* Enable auto polling. */
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+    {
+        pDevice->MiMode |= MI_MODE_AUTO_POLLING_ENABLE;
+        REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+    }
+
+    /* Enable phy link change attention. */
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT)
+    {
+        REG_WR(pDevice, MacCtrl.MacEvent, MAC_EVENT_ENABLE_MI_INTERRUPT);
+    }
+    else
+    {
+        REG_WR(pDevice, MacCtrl.MacEvent, 
+            MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN);
+    }
+    if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) &&
+        (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) &&
+        (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) &&
+        (((pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) &&
+          (pDevice->PciState & T3_PCI_STATE_BUS_SPEED_HIGH)) ||
+         !(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)))
+    {
+        MM_Wait(120);
+        REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED |
+            MAC_STATUS_CFG_CHANGED);
+        MEM_WR_OFFSET(pDevice, T3_FIRMWARE_MAILBOX,
+            T3_MAGIC_NUM_DISABLE_DMAW_ON_LINK_CHANGE);
+    }
+
+    /* Indicate link status. */
+    if (pDevice->LinkStatus != CurrentLinkStatus) {
+        pDevice->LinkStatus = CurrentLinkStatus;
+        MM_IndicateStatus(pDevice, CurrentLinkStatus);
+    }
+
+    return LM_STATUS_SUCCESS;
+} /* LM_SetupCopperPhy */
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_SetupPhy(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_STATUS LmStatus;
+    LM_UINT32 Value32;
+
+#if INCLUDE_TBI_SUPPORT
+    if(pDevice->EnableTbi)
+    {
+        LmStatus = LM_SetupFiberPhy(pDevice);
+    }
+    else
+#endif /* INCLUDE_TBI_SUPPORT */
+    {
+        LmStatus = LM_SetupCopperPhy(pDevice);
+    }
+    if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+    {
+        if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))
+        {
+            Value32 = REG_RD(pDevice, PciCfg.PciState);
+            REG_WR(pDevice, PciCfg.PciState,
+                Value32 | T3_PCI_STATE_RETRY_SAME_DMA);
+        }
+    }
+    if ((pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) &&
+        (pDevice->DuplexMode == LM_DUPLEX_MODE_HALF))
+    {
+        REG_WR(pDevice, MacCtrl.TxLengths, 0x26ff);
+    }
+    else
+    {
+        REG_WR(pDevice, MacCtrl.TxLengths, 0x2620);
+    }
+
+    return LmStatus;
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_VOID
+LM_ReadPhy(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 PhyReg,
+PLM_UINT32 pData32) {
+    LM_UINT32 Value32;
+    LM_UINT32 j;
+
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+    {
+        REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode &
+            ~MI_MODE_AUTO_POLLING_ENABLE);
+        MM_Wait(40);
+    }
+
+    Value32 = (pDevice->PhyAddr << MI_COM_FIRST_PHY_ADDR_BIT) |
+        ((PhyReg & MI_COM_PHY_REG_ADDR_MASK) << MI_COM_FIRST_PHY_REG_ADDR_BIT) |
+        MI_COM_CMD_READ | MI_COM_START;
+
+    REG_WR(pDevice, MacCtrl.MiCom, Value32);
+    
+    for(j = 0; j < 20; j++)
+    {
+        MM_Wait(25);
+
+        Value32 = REG_RD(pDevice, MacCtrl.MiCom);
+
+        if(!(Value32 & MI_COM_BUSY))
+        {
+            MM_Wait(5);
+            Value32 = REG_RD(pDevice, MacCtrl.MiCom);
+            Value32 &= MI_COM_PHY_DATA_MASK;
+            break;
+        }
+    }
+
+    if(Value32 & MI_COM_BUSY)
+    {
+        Value32 = 0;
+    }
+
+    *pData32 = Value32;
+
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+    {
+        REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+        MM_Wait(40);
+    }
+} /* LM_ReadPhy */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_VOID
+LM_WritePhy(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 PhyReg,
+LM_UINT32 Data32) {
+    LM_UINT32 Value32;
+    LM_UINT32 j;
+
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+    {
+        REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode &
+            ~MI_MODE_AUTO_POLLING_ENABLE);
+        MM_Wait(40);
+    }
+
+    Value32 = (pDevice->PhyAddr << MI_COM_FIRST_PHY_ADDR_BIT) |
+        ((PhyReg & MI_COM_PHY_REG_ADDR_MASK) << MI_COM_FIRST_PHY_REG_ADDR_BIT) |
+        (Data32 & MI_COM_PHY_DATA_MASK) | MI_COM_CMD_WRITE | MI_COM_START;
+
+    REG_WR(pDevice, MacCtrl.MiCom, Value32);
+    
+    for(j = 0; j < 20; j++)
+    {
+        MM_Wait(25);
+
+        Value32 = REG_RD(pDevice, MacCtrl.MiCom);
+
+        if(!(Value32 & MI_COM_BUSY))
+        {
+            MM_Wait(5);
+            break;
+        }
+    }
+
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+    {
+        REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+        MM_Wait(40);
+    }
+} /* LM_WritePhy */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_SetPowerState(
+PLM_DEVICE_BLOCK pDevice,
+LM_POWER_STATE PowerLevel) {
+    LM_UINT32 PmeSupport;
+    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);
+
+        REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl);
+        MM_Wait (40);
+#if 0   /* Bugfix by jmb...can't call WritePhy here because pDevice not fully initialized */
+        LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x02);
+#endif
+
+        return LM_STATUS_SUCCESS;
+    }
+    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->WakeUpRequestedMediaType = pDevice->RequestedMediaType;
+    }
+
+    /* Force auto-negotiation to 10 line speed. */
+    pDevice->DisableAutoNeg = FALSE;
+    pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS;
+    LM_SetupPhy(pDevice);
+
+    /* Put the driver in the initial state, and go through the power down */
+    /* sequence. */
+    LM_Halt(pDevice);
+
+    MM_ReadConfig32(pDevice, T3_PCI_PM_CAP_REG, &PmeSupport);
+
+    if (pDevice->WakeUpModeCap != LM_WAKE_UP_MODE_NONE)
+    {
+
+        /* Enable WOL. */
+        LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x5a);
+        MM_Wait(40);
+
+        /* Set LED mode. */
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            Value32 = LED_CTRL_PHY_MODE_1;
+        }
+        else
+        {
+            if(pDevice->LedMode == LED_MODE_OUTPUT)
+            {
+                Value32 = LED_CTRL_PHY_MODE_2;
+            }
+            else
+            {
+                Value32 = LED_CTRL_PHY_MODE_1;
+            }
+        }
+
+        Value32 = MAC_MODE_PORT_MODE_MII;
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+        {
+            if(pDevice->LedMode == LED_MODE_LINK10 ||
+                pDevice->WolSpeed == WOL_SPEED_10MB)
+            {
+                Value32 |= MAC_MODE_LINK_POLARITY;
+            }
+        }
+        else
+        {
+            Value32 |= MAC_MODE_LINK_POLARITY;
+        }
+        REG_WR(pDevice, MacCtrl.Mode, Value32);
+        MM_Wait(40); MM_Wait(40); MM_Wait(40);
+
+        /* Always enable magic packet wake-up if we have vaux. */
+        if((PmeSupport & T3_PCI_PM_CAP_PME_D3COLD) && 
+            (pDevice->WakeUpModeCap & LM_WAKE_UP_MODE_MAGIC_PACKET))
+        {
+            Value32 |= MAC_MODE_DETECT_MAGIC_PACKET_ENABLE;
+        }
+
+        REG_WR(pDevice, MacCtrl.Mode, Value32);
+
+        /* Enable the receiver. */
+        REG_WR(pDevice, MacCtrl.RxMode, RX_MODE_ENABLE);
+    }
+
+    /* Disable tx/rx clocks, and seletect an alternate clock. */
+    if(pDevice->WolSpeed == WOL_SPEED_100MB)
+    {
+        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;
+        }
+        else
+        {
+            Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK;
+        }
+        REG_WR(pDevice, PciCfg.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
+        {
+            Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK |
+                T3_PCI_44MHZ_CORE_CLOCK;
+        }
+
+        REG_WR(pDevice, PciCfg.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_44MHZ_CORE_CLOCK;
+        }
+        else
+        {
+            Value32 = T3_PCI_44MHZ_CORE_CLOCK;
+        }
+
+        REG_WR(pDevice, PciCfg.ClockCtrl, Value32);
+    }
+    else
+    {
+        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_POWER_DOWN_PCI_PLL133;
+        }
+        else
+        {
+            Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK |
+                T3_PCI_POWER_DOWN_PCI_PLL133;
+        }
+
+        REG_WR(pDevice, PciCfg.ClockCtrl, Value32);
+    }
+
+    MM_Wait(40);
+
+    if(!pDevice->EepromWp && (pDevice->WakeUpModeCap != LM_WAKE_UP_MODE_NONE))
+    {
+        /* Switch adapter to auxilliary power. */
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 0. */
+            REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE2 | 
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1);
+                MM_Wait(40);
+        }
+        else
+        {
+            /* GPIO0 = 0, GPIO1 = 1, GPIO2 = 1. */
+            REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE2 | 
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 | 
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2);
+                MM_Wait(40);
+
+            /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 1. */
+            REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE2 | 
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2);
+                MM_Wait(40);
+
+            /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 0. */
+            REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE0 | 
+                GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE2 | 
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1);
+                MM_Wait(40);
+        }
+    }
+
+    /* Set the phy to low power mode. */
+    /* Put the the hardware in low power mode. */
+    MM_WriteConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, PmCtrl);
+
+    return LM_STATUS_SUCCESS;
+} /* LM_SetPowerState */
+
+
+
+/******************************************************************************/
+/* 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->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO ||
+        pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_UTP_AUTO)
+    {
+        /* Please refer to Table 28B-3 of the 802.3ab-1999 spec. */
+        if((pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE) ||
+            ((pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE) &&
+            (pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)))
+        {
+            Value32 |= PHY_AN_AD_PAUSE_CAPABLE;
+        }
+        else if(pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
+        {
+            Value32 |= PHY_AN_AD_ASYM_PAUSE;
+        }
+        else if(pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE)
+        {
+            Value32 |= PHY_AN_AD_PAUSE_CAPABLE | PHY_AN_AD_ASYM_PAUSE;
+        }
+    }
+
+    return Value32;
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_FAILURE                                                       */
+/*    LM_STATUS_SUCCESS                                                       */
+/*                                                                            */
+/******************************************************************************/
+static LM_STATUS
+LM_ForceAutoNegBcm540xPhy(
+PLM_DEVICE_BLOCK pDevice, 
+LM_REQUESTED_MEDIA_TYPE RequestedMediaType)
+{
+    LM_MEDIA_TYPE MediaType;
+    LM_LINE_SPEED LineSpeed;
+    LM_DUPLEX_MODE DuplexMode;
+    LM_UINT32 NewPhyCtrl;
+    LM_UINT32 Value32;
+    LM_UINT32 Cnt;
+
+    /* Get the interface type, line speed, and duplex mode. */
+    LM_TranslateRequestedMediaType(RequestedMediaType, &MediaType, &LineSpeed,
+        &DuplexMode);
+
+    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)
+    {
+        /* Setup the 10/100 Mbps auto-negotiation advertisement register. */
+        Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD |
+            PHY_AN_AD_10BASET_HALF | PHY_AN_AD_10BASET_FULL |
+            PHY_AN_AD_100BASETX_FULL | PHY_AN_AD_100BASETX_HALF;
+        Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+
+        LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+        pDevice->advertising = Value32;
+
+        /* Advertise 1000Mbps */
+        Value32 = BCM540X_AN_AD_1000BASET_HALF | BCM540X_AN_AD_1000BASET_FULL;
+
+#if INCLUDE_5701_AX_FIX
+        /* Bug: workaround for CRC error in gigabit mode when we are in */
+        /* slave mode.  This will force the PHY to operate in */
+        /* master mode. */
+        if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+            pDevice->ChipRevId == T3_CHIP_ID_5701_B0)
+        {
+            Value32 |= BCM540X_CONFIG_AS_MASTER |
+                BCM540X_ENABLE_CONFIG_AS_MASTER;
+        }
+#endif
+
+        LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, Value32);
+        pDevice->advertising1000 = Value32;
+    }
+    else
+    {
+        if(LineSpeed == LM_LINE_SPEED_1000MBPS)
+        {
+            Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
+            Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+
+            LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+            pDevice->advertising = Value32;
+
+            if(DuplexMode != LM_DUPLEX_MODE_FULL)
+            {
+                Value32 = BCM540X_AN_AD_1000BASET_HALF;
+            }
+            else
+            {
+                Value32 = BCM540X_AN_AD_1000BASET_FULL;
+            }
+
+            LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, Value32);
+            pDevice->advertising1000 = Value32;
+        }
+        else if(LineSpeed == LM_LINE_SPEED_100MBPS)
+        {
+            LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, 0);
+            pDevice->advertising1000 = 0;
+
+            if(DuplexMode != LM_DUPLEX_MODE_FULL)
+            {
+                Value32 = PHY_AN_AD_100BASETX_HALF;
+            }
+            else
+            {
+                Value32 = PHY_AN_AD_100BASETX_FULL;
+            }
+
+            Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
+            Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+
+            LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+            pDevice->advertising = Value32;
+        }
+        else if(LineSpeed == LM_LINE_SPEED_10MBPS)
+        {
+            LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, 0);
+            pDevice->advertising1000 = 0;
+
+            if(DuplexMode != LM_DUPLEX_MODE_FULL)
+            {
+                Value32 = PHY_AN_AD_10BASET_HALF;
+            }
+            else
+            {
+                Value32 = PHY_AN_AD_10BASET_FULL;
+            }
+
+            Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
+            Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+
+            LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+            pDevice->advertising = Value32;
+        }
+    }
+
+    /* Force line speed if auto-negotiation is disabled. */
+    if(pDevice->DisableAutoNeg && LineSpeed != LM_LINE_SPEED_UNKNOWN)
+    {
+        /* This code path is executed only when there is link. */
+        pDevice->MediaType = MediaType;
+        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 < 15000; 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:                                                                    */
+/******************************************************************************/
+static LM_STATUS
+LM_ForceAutoNeg(
+PLM_DEVICE_BLOCK pDevice, 
+LM_REQUESTED_MEDIA_TYPE RequestedMediaType)
+{
+    LM_STATUS LmStatus;
+
+    /* Initialize the phy chip. */
+    switch(pDevice->PhyId & PHY_ID_MASK)
+    {
+        case PHY_BCM5400_PHY_ID:
+        case PHY_BCM5401_PHY_ID:
+        case PHY_BCM5411_PHY_ID:
+        case PHY_BCM5701_PHY_ID:
+        case PHY_BCM5703_PHY_ID:
+        case PHY_BCM5704_PHY_ID:
+            LmStatus = LM_ForceAutoNegBcm540xPhy(pDevice, RequestedMediaType);
+            break;
+
+        default:
+            LmStatus = LM_STATUS_FAILURE;
+            break;
+    }
+
+    return LmStatus;
+} /* LM_ForceAutoNeg */
+
+/******************************************************************************/
+/* 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;
+
+    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 < T3_RX_CPU_SPAD_SIZE; i+=4)
+        { 
+            LM_RegWrInd(pDevice,T3_RX_CPU_SPAD_ADDR+i,0);
+        }
+
+        /* Copy code first */
+        address = T3_RX_CPU_SPAD_ADDR + (pFwImg->Text.Offset & 0xffff);
+        for (i = 0; i <= pFwImg->Text.Length; i+=4)
+        {
+            LM_RegWrInd(pDevice,address+i,
+                        ((LM_UINT32 *)pFwImg->Text.Buffer)[i/4]);
+        }
+
+        address = T3_RX_CPU_SPAD_ADDR + (pFwImg->ROnlyData.Offset & 0xffff);
+        for (i = 0; i <= pFwImg->ROnlyData.Length; i+=4)
+        {
+            LM_RegWrInd(pDevice,address+i,
+                        ((LM_UINT32 *)pFwImg->ROnlyData.Buffer)[i/4]);
+        }
+
+        address = T3_RX_CPU_SPAD_ADDR + (pFwImg->Data.Offset & 0xffff);
+        for (i= 0; i <= pFwImg->Data.Length; i+=4)
+        {
+            LM_RegWrInd(pDevice,address+i,
+                        ((LM_UINT32 *)pFwImg->Data.Buffer)[i/4]);
+        }
+    }
+
+    if (LoadCpu & T3_TX_CPU_ID)
+    {
+        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)
+        { 
+            LM_RegWrInd(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)
+        {
+            LM_RegWrInd(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)
+        {
+            LM_RegWrInd(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)
+        {
+            LM_RegWrInd(pDevice,address+i,
+                        ((LM_UINT32 *)pFwImg->Data.Buffer)[i/4]);
+        }
+    }
+
+    if (StartCpu & T3_RX_CPU_ID)
+    {
+        /* Start Rx CPU */
+        REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+        REG_WR(pDevice,rxCpu.reg.PC,pFwImg->StartAddress);
+        for (i = 0 ; i < 5; i++)
+        {
+          if (pFwImg->StartAddress == REG_RD(pDevice,rxCpu.reg.PC))
+             break;
+
+          REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+          REG_WR(pDevice,rxCpu.reg.mode,CPU_MODE_HALT);
+          REG_WR(pDevice,rxCpu.reg.PC,pFwImg->StartAddress);
+          MM_Wait(1000);
+        }
+
+        REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+        REG_WR(pDevice,rxCpu.reg.mode, 0);
+    }
+
+    if (StartCpu & T3_TX_CPU_ID)
+    {
+        /* Start Tx CPU */
+        REG_WR(pDevice,txCpu.reg.state, 0xffffffff);
+        REG_WR(pDevice,txCpu.reg.PC,pFwImg->StartAddress);
+        for (i = 0 ; i < 5; i++)
+        {
+          if (pFwImg->StartAddress == REG_RD(pDevice,txCpu.reg.PC))
+             break;
+
+          REG_WR(pDevice,txCpu.reg.state, 0xffffffff);
+          REG_WR(pDevice,txCpu.reg.mode,CPU_MODE_HALT);
+          REG_WR(pDevice,txCpu.reg.PC,pFwImg->StartAddress);
+          MM_Wait(1000);
+        }
+        
+        REG_WR(pDevice,txCpu.reg.state, 0xffffffff);
+        REG_WR(pDevice,txCpu.reg.mode, 0);
+    }
+    
+    return LM_STATUS_SUCCESS;
+}
+
+STATIC LM_STATUS LM_HaltCpu(PLM_DEVICE_BLOCK pDevice,LM_UINT32 cpu_number)
+{
+    LM_UINT32 i;
+
+    if (cpu_number == T3_RX_CPU_ID)
+    {
+        for (i = 0 ; i < 10000; i++)
+        {
+            REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+            REG_WR(pDevice,rxCpu.reg.mode,CPU_MODE_HALT);
+
+            if (REG_RD(pDevice,rxCpu.reg.mode) & CPU_MODE_HALT)
+              break;
+        }
+
+        REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+        REG_WR(pDevice,rxCpu.reg.mode,CPU_MODE_HALT);
+        MM_Wait(10);
+    }
+    else
+    {
+        for (i = 0 ; i < 10000; i++)
+        {
+            REG_WR(pDevice,txCpu.reg.state, 0xffffffff);
+            REG_WR(pDevice,txCpu.reg.mode,CPU_MODE_HALT);
+
+            if (REG_RD(pDevice,txCpu.reg.mode) & CPU_MODE_HALT)
+               break;
+        }
+    }
+
+  return (( i == 10000) ? LM_STATUS_FAILURE : LM_STATUS_SUCCESS);
+}
+
+
+int
+LM_BlinkLED(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDurationSec)
+{
+       LM_UINT32 Oldcfg;
+       int j;
+       int ret = 0;
+
+       if(BlinkDurationSec == 0)
+       {
+               return 0;
+        }
+       if(BlinkDurationSec > 120)
+        {
+               BlinkDurationSec = 120;
+       }
+
+       Oldcfg = REG_RD(pDevice, MacCtrl.LedCtrl);
+       for(j = 0; j < BlinkDurationSec * 2; j++)
+       {
+               if(j % 2)
+               {
+                       /* Turn on the LEDs. */
+                       REG_WR(pDevice, MacCtrl.LedCtrl,
+                               LED_CTRL_OVERRIDE_LINK_LED |
+                               LED_CTRL_1000MBPS_LED_ON |
+                               LED_CTRL_100MBPS_LED_ON |
+                               LED_CTRL_10MBPS_LED_ON |
+                               LED_CTRL_OVERRIDE_TRAFFIC_LED |
+                               LED_CTRL_BLINK_TRAFFIC_LED |
+                               LED_CTRL_TRAFFIC_LED);
+               }
+               else
+               {
+                       /* Turn off the LEDs. */
+                       REG_WR(pDevice, MacCtrl.LedCtrl,
+                               LED_CTRL_OVERRIDE_LINK_LED |
+                               LED_CTRL_OVERRIDE_TRAFFIC_LED);
+               }
+
+#ifndef EMBEDDED
+                current->state = TASK_INTERRUPTIBLE;
+                if (schedule_timeout(HZ/2) != 0) {
+                        ret = -EINTR;
+                        break;
+                }
+#else
+                udelay(100000);  /* 1s sleep */
+#endif
+       }
+       REG_WR(pDevice, MacCtrl.LedCtrl, Oldcfg);
+       return ret;
+}
+
+int t3_do_dma(PLM_DEVICE_BLOCK pDevice, 
+                   LM_PHYSICAL_ADDRESS host_addr_phy, int length,
+                   int dma_read)
+{
+    T3_DMA_DESC dma_desc;
+    int i;
+    LM_UINT32 dma_desc_addr;
+    LM_UINT32 value32;
+
+    REG_WR(pDevice, BufMgr.Mode, 0);
+    REG_WR(pDevice, Ftq.Reset, 0);
+
+    dma_desc.host_addr.High = host_addr_phy.High;
+    dma_desc.host_addr.Low = host_addr_phy.Low;
+    dma_desc.nic_mbuf = 0x2100;
+    dma_desc.len = length;
+    dma_desc.flags = 0x00000004; /* Generate Rx-CPU event */
+
+    if (dma_read)
+    {
+        dma_desc.cqid_sqid = (T3_QID_RX_BD_COMP << 8) |
+            T3_QID_DMA_HIGH_PRI_READ;
+        REG_WR(pDevice, DmaRead.Mode, DMA_READ_MODE_ENABLE);
+    }
+    else
+    {
+        dma_desc.cqid_sqid = (T3_QID_RX_DATA_COMP << 8) |
+            T3_QID_DMA_HIGH_PRI_WRITE;
+        REG_WR(pDevice, DmaWrite.Mode, DMA_WRITE_MODE_ENABLE);
+    }
+
+    dma_desc_addr = T3_NIC_DMA_DESC_POOL_ADDR;
+
+    /* Writing this DMA descriptor to DMA memory */
+    for (i = 0; i < sizeof(T3_DMA_DESC); i += 4)
+    {
+        value32 = *((PLM_UINT32) (((PLM_UINT8) &dma_desc) + i));
+        MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, dma_desc_addr+i);
+        MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, cpu_to_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;
+
+    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)
+        {
+            return LM_STATUS_FAILURE;
+        }
+
+        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)
+        {
+            return LM_STATUS_FAILURE;
+        }
+
+        MM_Wait(40);
+        /* Check for data */
+        ptr = (LM_UINT32 *)pBufferVirt;
+        for (j = 0; j < BufferSize/4; j++)
+        {
+            if (*ptr++ != j)
+            {
+                if ((pDevice->DmaReadWriteCtrl & DMA_CTRL_WRITE_BOUNDARY_MASK)
+                    == DMA_CTRL_WRITE_BOUNDARY_DISABLE)
+                {
+                    pDevice->DmaReadWriteCtrl = (pDevice->DmaReadWriteCtrl &
+                         ~DMA_CTRL_WRITE_BOUNDARY_MASK) |
+                          DMA_CTRL_WRITE_BOUNDARY_16;
+                    REG_WR(pDevice, PciCfg.DmaReadWriteCtrl,
+                           pDevice->DmaReadWriteCtrl);
+                    break;
+                 }
+                 else
+                 {
+                     return LM_STATUS_FAILURE;
+                 }
+            }
+        }
+        if (j == (BufferSize/4))
+            dma_success = 1;
+    }
+    return LM_STATUS_SUCCESS;
+}
+#endif /* !defined(CONFIG_NET_MULTI) */
diff --git a/drivers/tigon3.h b/drivers/tigon3.h
new file mode 100644 (file)
index 0000000..6914734
--- /dev/null
@@ -0,0 +1,3469 @@
+
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/*                                                                            */
+/******************************************************************************/
+
+#ifndef TIGON3_H
+#define TIGON3_H
+
+#include "bcm570x_lm.h"
+#if INCLUDE_TBI_SUPPORT
+#include "bcm570x_autoneg.h"
+#endif
+
+
+/* io defines */
+#if !defined(BIG_ENDIAN_HOST) 
+#define readl(addr) \
+              (LONGSWAP((*(volatile unsigned int *)(addr))))
+#define writel(b,addr) \
+              ((*(volatile unsigned int *)(addr)) = (LONGSWAP(b)))
+#else
+#if 0 /* !defined(PPC603) */
+#define readl(addr) (*(volatile unsigned int*)(0xa0000000 + (unsigned long)(addr)))
+#define writel(b,addr) ((*(volatile unsigned int *) ((unsigned long)(addr) + 0xa0000000)) = (b))
+#else
+#if 1
+#define readl(addr) (*(volatile unsigned int*)(addr))
+#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b))
+#else
+extern int sprintf(char* buf, const char* f, ...);
+static __inline unsigned int readl(void* addr){
+    char buf[128];
+    unsigned int tmp = (*(volatile unsigned int*)(addr));
+    sprintf(buf,"%s:%s: read 0x%x from 0x%x\n",__FILE__,__LINE__,tmp,addr,0,0);
+    sysSerialPrintString(buf);
+    return tmp;
+}
+static __inline void writel(unsigned int b, unsigned int addr){
+    char buf[128];
+    ((*(volatile unsigned int *) (addr)) = (b));
+    sprintf(buf,"%s:%s: write 0x%x to 0x%x\n",__FILE__,__LINE__,b,addr,0,0);
+    sysSerialPrintString(buf);
+}
+#endif
+#endif /* PPC603 */
+#endif
+
+
+
+
+/******************************************************************************/
+/* Constants. */
+/******************************************************************************/
+
+/* Maxim number of packet descriptors used for sending packets. */
+#define MAX_TX_PACKET_DESC_COUNT            600
+#define DEFAULT_TX_PACKET_DESC_COUNT        2
+
+/* Maximum number of packet descriptors used for receiving packets. */
+#if T3_JUMBO_RCB_ENTRY_COUNT
+#define MAX_RX_PACKET_DESC_COUNT                                            \
+    (T3_STD_RCV_RCB_ENTRY_COUNT + T3_JUMBO_RCV_RCB_ENTRY_COUNT)
+#else
+#define MAX_RX_PACKET_DESC_COUNT            800
+#endif
+#define DEFAULT_RX_PACKET_DESC_COUNT        2
+
+/* 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                       0x4B657654 
+#define T3_MAGIC_NUM_DISABLE_DMAW_ON_LINK_CHANGE 0x4861764b
+
+#define T3_NIC_DATA_SIG_ADDR               0x0b54
+#define T3_NIC_DATA_SIG                    0x4b657654
+
+#define T3_NIC_DATA_NIC_CFG_ADDR           0x0b58
+#define T3_NIC_CFG_LED_MODE_UNKNOWN        BIT_NONE
+#define T3_NIC_CFG_LED_MODE_TRIPLE_SPEED   BIT_2
+#define T3_NIC_CFG_LED_MODE_LINK_SPEED     BIT_3
+#define T3_NIC_CFG_LED_MODE_OPEN_DRAIN     BIT_2
+#define T3_NIC_CFG_LED_MODE_OUTPUT         BIT_3
+#define T3_NIC_CFG_LED_MODE_MASK           (BIT_2 | BIT_3)
+#define T3_NIC_CFG_PHY_TYPE_UNKNOWN         BIT_NONE
+#define T3_NIC_CFG_PHY_TYPE_COPPER          BIT_4
+#define T3_NIC_CFG_PHY_TYPE_FIBER           BIT_5
+#define T3_NIC_CFG_PHY_TYPE_MASK            (BIT_4 | BIT_5)
+#define T3_NIC_CFG_ENABLE_WOL               BIT_6
+#define T3_NIC_CFG_ENABLE_ASF               BIT_7
+#define T3_NIC_EEPROM_WP                    BIT_8
+
+#define T3_NIC_DATA_PHY_ID_ADDR            0x0b74
+#define T3_NIC_PHY_ID1_MASK                0xffff0000
+#define T3_NIC_PHY_ID2_MASK                0x0000ffff
+
+#define T3_CMD_MAILBOX                      0x0b78
+#define T3_CMD_NICDRV_ALIVE                 0x01
+#define T3_CMD_NICDRV_PAUSE_FW              0x02
+#define T3_CMD_NICDRV_IPV4ADDR_CHANGE       0x03
+#define T3_CMD_NICDRV_IPV6ADDR_CHANGE       0x04
+#define T3_CMD_5703A0_FIX_DMAFW_DMAR        0x05
+#define T3_CMD_5703A0_FIX_DMAFW_DMAW        0x06
+
+#define T3_CMD_LENGTH_MAILBOX               0x0b7c
+#define T3_CMD_DATA_MAILBOX                 0x0b80
+
+#define T3_ASF_FW_STATUS_MAILBOX            0x0c00
+
+#define T3_DRV_STATE_MAILBOX                0x0c04
+#define T3_DRV_STATE_START                  0x01
+#define T3_DRV_STATE_UNLOAD                 0x02
+#define T3_DRV_STATE_WOL                    0x03
+#define T3_DRV_STATE_SUSPEND                0x04
+
+#define T3_FW_RESET_TYPE_MAILBOX            0x0c08
+
+#define T3_MAC_ADDR_HIGH_MAILBOX            0x0c14
+#define T3_MAC_ADDR_LOW_MAILBOX             0x0c18
+
+/******************************************************************************/
+/* Hardware constants. */
+/******************************************************************************/
+
+/* Number of entries in the send ring:  must be 512. */
+#define T3_SEND_RCB_ENTRY_COUNT             512     
+#define T3_SEND_RCB_ENTRY_COUNT_MASK        (T3_SEND_RCB_ENTRY_COUNT-1)
+
+/* Number of send RCBs.  May be 1-16 but for now, only support one. */
+#define T3_MAX_SEND_RCB_COUNT               16
+
+/* Number of entries in the Standard Receive RCB.  Must be 512 entries. */
+#define T3_STD_RCV_RCB_ENTRY_COUNT          512
+#define T3_STD_RCV_RCB_ENTRY_COUNT_MASK     (T3_STD_RCV_RCB_ENTRY_COUNT-1)
+#define DEFAULT_STD_RCV_DESC_COUNT          200    /* Must be < 512. */
+#define MAX_STD_RCV_BUFFER_SIZE             0x600
+
+/* Number of entries in the Mini Receive RCB.  This value can either be */
+/* 0, 1024.  Currently Mini Receive RCB is disabled. */
+#ifndef T3_MINI_RCV_RCB_ENTRY_COUNT
+#define T3_MINI_RCV_RCB_ENTRY_COUNT         0
+#endif /* T3_MINI_RCV_RCB_ENTRY_COUNT */
+#define T3_MINI_RCV_RCB_ENTRY_COUNT_MASK    (T3_MINI_RCV_RCB_ENTRY_COUNT-1)
+#define MAX_MINI_RCV_BUFFER_SIZE            512
+#define DEFAULT_MINI_RCV_BUFFER_SIZE        64
+#define DEFAULT_MINI_RCV_DESC_COUNT         100    /* Must be < 1024. */
+
+/* Number of entries in the Jumbo Receive RCB.  This value must 256 or 0. */
+/* Currently, Jumbo Receive RCB is disabled. */
+#ifndef T3_JUMBO_RCV_RCB_ENTRY_COUNT
+#define T3_JUMBO_RCV_RCB_ENTRY_COUNT        0
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+#define T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK   (T3_JUMBO_RCV_RCB_ENTRY_COUNT-1)
+
+#define MAX_JUMBO_RCV_BUFFER_SIZE           (10 * 1024) /* > 1514 */
+#define DEFAULT_JUMBO_RCV_BUFFER_SIZE       (4 * 1024) /* > 1514 */
+#define DEFAULT_JUMBO_RCV_DESC_COUNT        128     /* Must be < 256. */
+
+#define MAX_JUMBO_TX_BUFFER_SIZE            (8 * 1024) /* > 1514 */
+#define DEFAULT_JUMBO_TX_BUFFER_SIZE        (4 * 1024) /* > 1514 */
+
+/* Number of receive return RCBs.  Maybe 1-16 but for now, only support one. */
+#define T3_MAX_RCV_RETURN_RCB_COUNT         16
+
+/* Number of entries in a Receive Return ring.  This value is either 1024 */
+/* or 2048. */
+#ifndef T3_RCV_RETURN_RCB_ENTRY_COUNT 
+#define T3_RCV_RETURN_RCB_ENTRY_COUNT       1024
+#endif /* T3_RCV_RETURN_RCB_ENTRY_COUNT */
+#define T3_RCV_RETURN_RCB_ENTRY_COUNT_MASK  (T3_RCV_RETURN_RCB_ENTRY_COUNT-1)
+
+
+/* Default coalescing parameters. */
+#define DEFAULT_RX_COALESCING_TICKS         100
+#define MAX_RX_COALESCING_TICKS             500
+#define DEFAULT_TX_COALESCING_TICKS         400
+#define MAX_TX_COALESCING_TICKS             500
+#define DEFAULT_RX_MAX_COALESCED_FRAMES     10
+#define MAX_RX_MAX_COALESCED_FRAMES         100
+#define ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES    5
+#define ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES    42
+#define ADAPTIVE_LO_RX_COALESCING_TICKS         50
+#define ADAPTIVE_HI_RX_COALESCING_TICKS         300
+#define ADAPTIVE_LO_PKT_THRESH              30000
+#define ADAPTIVE_HI_PKT_THRESH              74000
+#define DEFAULT_TX_MAX_COALESCED_FRAMES     40
+#define ADAPTIVE_LO_TX_MAX_COALESCED_FRAMES    25
+#define ADAPTIVE_HI_TX_MAX_COALESCED_FRAMES    75
+#define MAX_TX_MAX_COALESCED_FRAMES         100
+
+#define DEFAULT_RX_COALESCING_TICKS_DURING_INT          25
+#define DEFAULT_TX_COALESCING_TICKS_DURING_INT          25
+#define DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT      5
+#define DEFAULT_TX_MAX_COALESCED_FRAMES_DURING_INT      5
+
+#define BAD_DEFAULT_VALUE                               0xffffffff
+
+#define DEFAULT_STATS_COALESCING_TICKS      1000000
+#define MAX_STATS_COALESCING_TICKS          3600000000U
+
+
+/* Receive BD Replenish thresholds. */
+#define DEFAULT_RCV_STD_BD_REPLENISH_THRESHOLD      4
+#define DEFAULT_RCV_JUMBO_BD_REPLENISH_THRESHOLD    4
+
+#define SPLIT_MODE_DISABLE                          0
+#define SPLIT_MODE_ENABLE                           1
+
+#define SPLIT_MODE_5704_MAX_REQ                     3
+
+/* Maximum physical fragment size. */
+#define MAX_FRAGMENT_SIZE                   (64 * 1024)
+
+
+/* Standard view. */
+#define T3_STD_VIEW_SIZE                    (64 * 1024)
+#define T3_FLAT_VIEW_SIZE                   (32 * 1024 * 1024)
+
+
+/* Buffer descriptor base address on the NIC's memory. */
+
+#define T3_NIC_SND_BUFFER_DESC_ADDR         0x4000
+#define T3_NIC_STD_RCV_BUFFER_DESC_ADDR     0x6000
+#define T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR   0x7000
+
+#define T3_NIC_STD_RCV_BUFFER_DESC_ADDR_EXT_MEM     0xc000
+#define T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR_EXT_MEM   0xd000
+#define T3_NIC_MINI_RCV_BUFFER_DESC_ADDR_EXT_MEM    0xe000
+
+#define T3_NIC_SND_BUFFER_DESC_SIZE         (T3_SEND_RCB_ENTRY_COUNT * \
+                                            sizeof(T3_SND_BD) / 4)
+
+#define T3_NIC_STD_RCV_BUFFER_DESC_SIZE     (T3_STD_RCV_RCB_ENTRY_COUNT * \
+                                            sizeof(T3_RCV_BD) / 4)
+
+#define T3_NIC_JUMBO_RCV_BUFFER_DESC_SIZE   (T3_JUMBO_RCV_RCB_ENTRY_COUNT * \
+                                            sizeof(T3_EXT_RCV_BD) / 4)
+
+
+/* MBUF pool. */
+#define T3_NIC_MBUF_POOL_ADDR               0x8000
+/* #define T3_NIC_MBUF_POOL_SIZE               0x18000 */
+#define T3_NIC_MBUF_POOL_SIZE96             0x18000
+#define T3_NIC_MBUF_POOL_SIZE64             0x10000
+
+
+#define T3_NIC_MBUF_POOL_ADDR_EXT_MEM       0x20000
+
+/* 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           0x40
+#define T3_DEF_RX_MAC_MBUF_LOW_WMARK        0x20
+#define T3_DEF_MBUF_HIGH_WMARK              0x60
+
+#define T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO     304
+#define T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO  152
+#define T3_DEF_MBUF_HIGH_WMARK_JUMBO        380
+
+#define T3_DEF_DMA_DESC_LOW_WMARK           5
+#define T3_DEF_DMA_DESC_HIGH_WMARK          10
+
+/* Maximum size of giant TCP packet can be sent */
+#define T3_TCP_SEG_MAX_OFFLOAD_SIZE         64*1000
+#define T3_TCP_SEG_MIN_NUM_SEG              20
+
+#define T3_RX_CPU_ID    0x1
+#define T3_TX_CPU_ID    0x2
+#define T3_RX_CPU_SPAD_ADDR  0x30000
+#define T3_RX_CPU_SPAD_SIZE  0x4000
+#define T3_TX_CPU_SPAD_ADDR  0x34000
+#define T3_TX_CPU_SPAD_SIZE  0x4000
+
+typedef struct T3_DIR_ENTRY
+{
+  PLM_UINT8 Buffer;
+  LM_UINT32 Offset;
+  LM_UINT32 Length;
+} T3_DIR_ENTRY,*PT3_DIR_ENTRY;
+
+typedef struct T3_FWIMG_INFO
+{
+  LM_UINT32 StartAddress;
+  T3_DIR_ENTRY Text;
+  T3_DIR_ENTRY ROnlyData;
+  T3_DIR_ENTRY Data;
+  T3_DIR_ENTRY Sbss;
+  T3_DIR_ENTRY Bss;
+} T3_FWIMG_INFO, *PT3_FWIMG_INFO;
+
+
+
+/******************************************************************************/
+/* Tigon3 PCI Registers. */
+/******************************************************************************/
+#define T3_PCI_ID_BCM5700                   0x164414e4
+#define T3_PCI_ID_BCM5701                   0x164514e4
+#define T3_PCI_ID_BCM5702                   0x164614e4
+#define T3_PCI_ID_BCM5702x                  0x16A614e4
+#define T3_PCI_ID_BCM5703                   0x164714e4
+#define T3_PCI_ID_BCM5703x                  0x16A714e4
+#define T3_PCI_ID_BCM5702FE                 0x164D14e4
+#define T3_PCI_ID_BCM5704                   0x164814e4
+
+#define T3_PCI_VENDOR_ID                    (T3_PCI_ID & 0xffff)
+#define T3_PCI_DEVICE_ID                    (T3_PCI_ID >> 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_5704_A0                  0x2000
+
+/* 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
+
+
+/* Chip id and revision. */
+#define T3_CHIP_REV(_ChipRevId)             ((_ChipRevId) >> 8)
+#define T3_CHIP_REV_5700_AX                 0x70
+#define T3_CHIP_REV_5700_BX                 0x71
+#define T3_CHIP_REV_5700_CX                 0x72
+#define T3_CHIP_REV_5701_AX                 0x00
+
+/* Metal revision. */
+#define T3_METAL_REV(_ChipRevId)            ((_ChipRevId) & 0xff)
+#define T3_METAL_REV_A0                     0x00
+#define T3_METAL_REV_A1                     0x01
+#define T3_METAL_REV_B0                     0x00
+#define T3_METAL_REV_B1                     0x01
+#define T3_METAL_REV_B2                     0x02
+
+#define T3_PCI_REG_CLOCK_CTRL               0x74
+
+#define T3_PCI_DISABLE_RX_CLOCK             BIT_10
+#define T3_PCI_DISABLE_TX_CLOCK             BIT_11
+#define T3_PCI_SELECT_ALTERNATE_CLOCK       BIT_12
+#define T3_PCI_POWER_DOWN_PCI_PLL133        BIT_15
+#define T3_PCI_44MHZ_CORE_CLOCK             BIT_18
+
+
+#define T3_PCI_REG_ADDR_REG                 0x78
+#define T3_PCI_REG_DATA_REG                 0x80
+
+#define T3_PCI_MEM_WIN_ADDR_REG             0x7c
+#define T3_PCI_MEM_WIN_DATA_REG             0x84
+
+#define T3_PCI_PM_CAP_REG                   0x48
+
+#define T3_PCI_PM_CAP_PME_D3COLD            BIT_31
+#define T3_PCI_PM_CAP_PME_D3HOT             BIT_30
+
+#define T3_PCI_PM_STATUS_CTRL_REG           0x4c
+
+#define T3_PM_POWER_STATE_MASK              (BIT_0 | BIT_1)
+#define T3_PM_POWER_STATE_D0                BIT_NONE
+#define T3_PM_POWER_STATE_D1                BIT_0
+#define T3_PM_POWER_STATE_D2                BIT_1
+#define T3_PM_POWER_STATE_D3                (BIT_0 | BIT_1)
+
+#define T3_PM_PME_ENABLE                    BIT_8
+#define T3_PM_PME_ASSERTED                  BIT_15
+
+
+/* PCI state register. */
+#define T3_PCI_STATE_REG                    0x70
+
+#define T3_PCI_STATE_FORCE_RESET            BIT_0
+#define T3_PCI_STATE_INT_NOT_ACTIVE         BIT_1
+#define T3_PCI_STATE_CONVENTIONAL_PCI_MODE  BIT_2
+#define T3_PCI_STATE_BUS_SPEED_HIGH         BIT_3
+#define T3_PCI_STATE_32BIT_PCI_BUS          BIT_4
+
+
+/* Broadcom subsystem/subvendor IDs. */
+#define T3_SVID_BROADCOM                            0x14e4
+
+#define T3_SSID_BROADCOM_BCM95700A6                 0x1644
+#define T3_SSID_BROADCOM_BCM95701A5                 0x0001
+#define T3_SSID_BROADCOM_BCM95700T6                 0x0002  /* BCM8002 */
+#define T3_SSID_BROADCOM_BCM95700A9                 0x0003  /* Agilent */
+#define T3_SSID_BROADCOM_BCM95701T1                 0x0005
+#define T3_SSID_BROADCOM_BCM95701T8                 0x0006
+#define T3_SSID_BROADCOM_BCM95701A7                 0x0007  /* Agilent */
+#define T3_SSID_BROADCOM_BCM95701A10                0x0008
+#define T3_SSID_BROADCOM_BCM95701A12                0x8008
+#define T3_SSID_BROADCOM_BCM95703Ax1                0x0009
+#define T3_SSID_BROADCOM_BCM95703Ax2                0x8009
+
+/* 3COM subsystem/subvendor IDs. */
+#define T3_SVID_3COM                                0x10b7
+
+#define T3_SSID_3COM_3C996T                         0x1000
+#define T3_SSID_3COM_3C996BT                        0x1006
+#define T3_SSID_3COM_3C996CT                        0x1002
+#define T3_SSID_3COM_3C997T                         0x1003
+#define T3_SSID_3COM_3C1000T                        0x1007
+#define T3_SSID_3COM_3C940BR01                      0x1008
+
+/* Fiber boards. */
+#define T3_SSID_3COM_3C996SX                        0x1004
+#define T3_SSID_3COM_3C997SX                        0x1005
+
+
+/* Dell subsystem/subvendor IDs. */
+
+#define T3_SVID_DELL                                0x1028
+
+#define T3_SSID_DELL_VIPER                          0x00d1
+#define T3_SSID_DELL_JAGUAR                         0x0106
+#define T3_SSID_DELL_MERLOT                         0x0109
+#define T3_SSID_DELL_SLIM_MERLOT                    0x010a
+
+/* Compaq subsystem/subvendor IDs */
+
+#define T3_SVID_COMPAQ                              0x0e11
+
+#define T3_SSID_COMPAQ_BANSHEE                      0x007c
+#define T3_SSID_COMPAQ_BANSHEE_2                    0x009a
+#define T3_SSID_COMPAQ_CHANGELING                   0x007d
+#define T3_SSID_COMPAQ_NC7780                       0x0085
+#define T3_SSID_COMPAQ_NC7780_2                     0x0099
+
+
+/******************************************************************************/
+/* MII registers. */
+/******************************************************************************/
+
+/* Control register. */
+#define PHY_CTRL_REG                                0x00
+
+#define PHY_CTRL_SPEED_MASK                         (BIT_6 | BIT_13)
+#define PHY_CTRL_SPEED_SELECT_10MBPS                BIT_NONE
+#define PHY_CTRL_SPEED_SELECT_100MBPS               BIT_13
+#define PHY_CTRL_SPEED_SELECT_1000MBPS              BIT_6
+#define PHY_CTRL_COLLISION_TEST_ENABLE              BIT_7
+#define PHY_CTRL_FULL_DUPLEX_MODE                   BIT_8
+#define PHY_CTRL_RESTART_AUTO_NEG                   BIT_9
+#define PHY_CTRL_ISOLATE_PHY                        BIT_10
+#define PHY_CTRL_LOWER_POWER_MODE                   BIT_11
+#define PHY_CTRL_AUTO_NEG_ENABLE                    BIT_12
+#define PHY_CTRL_LOOPBACK_MODE                      BIT_14
+#define PHY_CTRL_PHY_RESET                          BIT_15
+
+
+/* Status register. */
+#define PHY_STATUS_REG                              0x01
+
+#define PHY_STATUS_LINK_PASS                        BIT_2
+#define PHY_STATUS_AUTO_NEG_COMPLETE                BIT_5
+
+
+/* Phy Id registers. */
+#define PHY_ID1_REG                                 0x02
+#define PHY_ID1_OUI_MASK                            0xffff
+
+#define PHY_ID2_REG                                 0x03
+#define PHY_ID2_REV_MASK                            0x000f
+#define PHY_ID2_MODEL_MASK                          0x03f0
+#define PHY_ID2_OUI_MASK                            0xfc00
+
+
+/* Auto-negotiation advertisement register. */
+#define PHY_AN_AD_REG                               0x04
+
+#define PHY_AN_AD_ASYM_PAUSE                        BIT_11
+#define PHY_AN_AD_PAUSE_CAPABLE                     BIT_10
+#define PHY_AN_AD_10BASET_HALF                      BIT_5
+#define PHY_AN_AD_10BASET_FULL                      BIT_6
+#define PHY_AN_AD_100BASETX_HALF                    BIT_7
+#define PHY_AN_AD_100BASETX_FULL                    BIT_8
+#define PHY_AN_AD_PROTOCOL_802_3_CSMA_CD            0x01
+
+
+/* Auto-negotiation Link Partner Ability register. */
+#define PHY_LINK_PARTNER_ABILITY_REG                0x05
+
+#define PHY_LINK_PARTNER_ASYM_PAUSE                 BIT_11
+#define PHY_LINK_PARTNER_PAUSE_CAPABLE              BIT_10
+
+
+/* Auto-negotiation expansion register. */
+#define PHY_AN_EXPANSION_REG                        0x06
+
+
+
+/******************************************************************************/
+/* BCM5400 and BCM5401 phy info. */
+/******************************************************************************/
+
+#define PHY_DEVICE_ID           1
+
+/* OUI: bit 31-10;   Model#: bit 9-4;   Rev# bit 3-0. */
+#define PHY_UNKNOWN_PHY                             0x00000000
+#define PHY_BCM5400_PHY_ID                          0x60008040
+#define PHY_BCM5401_PHY_ID                          0x60008050
+#define PHY_BCM5411_PHY_ID                          0x60008070
+#define PHY_BCM5701_PHY_ID                          0x60008110
+#define PHY_BCM5703_PHY_ID                          0x60008160
+#define PHY_BCM5704_PHY_ID                          0x60008190
+#define PHY_BCM8002_PHY_ID                          0x60010140
+
+#define PHY_BCM5401_B0_REV                          0x1
+#define PHY_BCM5401_B2_REV                          0x3
+#define PHY_BCM5401_C0_REV                          0x6
+
+#define PHY_ID_OUI_MASK                             0xfffffc00
+#define PHY_ID_MODEL_MASK                           0x000003f0
+#define PHY_ID_REV_MASK                             0x0000000f
+#define PHY_ID_MASK                                 (PHY_ID_OUI_MASK |      \
+                                                    PHY_ID_MODEL_MASK)
+
+
+#define UNKNOWN_PHY_ID(x)   ((((x) & PHY_ID_MASK) != PHY_BCM5400_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5401_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5411_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5701_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5703_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5704_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM8002_PHY_ID))
+
+
+
+/* 1000Base-T control register. */
+#define BCM540X_1000BASET_CTRL_REG                  0x09
+
+#define BCM540X_AN_AD_1000BASET_HALF                BIT_8
+#define BCM540X_AN_AD_1000BASET_FULL                BIT_9
+#define BCM540X_CONFIG_AS_MASTER                    BIT_11
+#define BCM540X_ENABLE_CONFIG_AS_MASTER             BIT_12
+
+
+/* Extended control register. */
+#define BCM540X_EXT_CTRL_REG                        0x10
+
+#define BCM540X_EXT_CTRL_LINK3_LED_MODE             BIT_1
+#define BCM540X_EXT_CTRL_TBI                        BIT_15
+
+/* PHY extended status register. */
+#define BCM540X_EXT_STATUS_REG                      0x11
+
+#define BCM540X_EXT_STATUS_LINK_PASS                BIT_8
+
+
+/* DSP Coefficient Read/Write Port. */
+#define BCM540X_DSP_RW_PORT                         0x15
+
+
+/* DSP Coeficient Address Register. */
+#define BCM540X_DSP_ADDRESS_REG                     0x17
+
+#define BCM540X_DSP_TAP_NUMBER_MASK                 0x00
+#define BCM540X_DSP_AGC_A                           0x00
+#define BCM540X_DSP_AGC_B                           0x01
+#define BCM540X_DSP_MSE_PAIR_STATUS                 0x02
+#define BCM540X_DSP_SOFT_DECISION                   0x03
+#define BCM540X_DSP_PHASE_REG                       0x04
+#define BCM540X_DSP_SKEW                            0x05
+#define BCM540X_DSP_POWER_SAVER_UPPER_BOUND         0x06
+#define BCM540X_DSP_POWER_SAVER_LOWER_BOUND         0x07
+#define BCM540X_DSP_LAST_ECHO                       0x08
+#define BCM540X_DSP_FREQUENCY                       0x09
+#define BCM540X_DSP_PLL_BANDWIDTH                   0x0a
+#define BCM540X_DSP_PLL_PHASE_OFFSET                0x0b
+
+#define BCM540X_DSP_FILTER_DCOFFSET                 (BIT_10 | BIT_11)
+#define BCM540X_DSP_FILTER_FEXT3                    (BIT_8 | BIT_9 | BIT_11)
+#define BCM540X_DSP_FILTER_FEXT2                    (BIT_9 | BIT_11)
+#define BCM540X_DSP_FILTER_FEXT1                    (BIT_8 | BIT_11)
+#define BCM540X_DSP_FILTER_FEXT0                    BIT_11
+#define BCM540X_DSP_FILTER_NEXT3                    (BIT_8 | BIT_9 | BIT_10)
+#define BCM540X_DSP_FILTER_NEXT2                    (BIT_9 | BIT_10)
+#define BCM540X_DSP_FILTER_NEXT1                    (BIT_8 | BIT_10)
+#define BCM540X_DSP_FILTER_NEXT0                    BIT_10
+#define BCM540X_DSP_FILTER_ECHO                     (BIT_8 | BIT_9)
+#define BCM540X_DSP_FILTER_DFE                      BIT_9
+#define BCM540X_DSP_FILTER_FFE                      BIT_8
+
+#define BCM540X_DSP_CONTROL_ALL_FILTERS             BIT_12
+
+#define BCM540X_DSP_SEL_CH_0                        BIT_NONE
+#define BCM540X_DSP_SEL_CH_1                        BIT_13
+#define BCM540X_DSP_SEL_CH_2                        BIT_14
+#define BCM540X_DSP_SEL_CH_3                        (BIT_13 | BIT_14)
+
+#define BCM540X_CONTROL_ALL_CHANNELS                BIT_15
+
+
+/* Auxilliary Control Register (Shadow Register) */
+#define BCM5401_AUX_CTRL                            0x18
+
+#define BCM5401_SHADOW_SEL_MASK                     0x7
+#define BCM5401_SHADOW_SEL_NORMAL                   0x00
+#define BCM5401_SHADOW_SEL_10BASET                  0x01
+#define BCM5401_SHADOW_SEL_POWER_CONTROL            0x02
+#define BCM5401_SHADOW_SEL_IP_PHONE                 0x03
+#define BCM5401_SHADOW_SEL_MISC_TEST1               0x04
+#define BCM5401_SHADOW_SEL_MISC_TEST2               0x05
+#define BCM5401_SHADOW_SEL_IP_PHONE_SEED            0x06
+
+
+/* Shadow register selector == '000' */
+#define BCM5401_SHDW_NORMAL_DIAG_MODE               BIT_3
+#define BCM5401_SHDW_NORMAL_DISABLE_MBP             BIT_4
+#define BCM5401_SHDW_NORMAL_DISABLE_LOW_PWR         BIT_5
+#define BCM5401_SHDW_NORMAL_DISABLE_INV_PRF         BIT_6
+#define BCM5401_SHDW_NORMAL_DISABLE_PRF             BIT_7
+#define BCM5401_SHDW_NORMAL_RX_SLICING_NORMAL       BIT_NONE
+#define BCM5401_SHDW_NORMAL_RX_SLICING_4D           BIT_8
+#define BCM5401_SHDW_NORMAL_RX_SLICING_3LVL_1D      BIT_9
+#define BCM5401_SHDW_NORMAL_RX_SLICING_5LVL_1D      (BIT_8 | BIT_9)
+#define BCM5401_SHDW_NORMAL_TX_6DB_CODING           BIT_10
+#define BCM5401_SHDW_NORMAL_ENABLE_SM_DSP_CLOCK     BIT_11
+#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_4NS       BIT_NONE
+#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_5NS       BIT_12
+#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_3NS       BIT_13
+#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_0NS       (BIT_12 | BIT_13)
+#define BCM5401_SHDW_NORMAL_EXT_PACKET_LENGTH       BIT_14
+#define BCM5401_SHDW_NORMAL_EXTERNAL_LOOPBACK       BIT_15
+
+
+/* Auxilliary status summary. */
+#define BCM540X_AUX_STATUS_REG                      0x19
+
+#define BCM540X_AUX_LINK_PASS                       BIT_2
+#define BCM540X_AUX_SPEED_MASK                      (BIT_8 | BIT_9 | BIT_10)
+#define BCM540X_AUX_10BASET_HD                      BIT_8
+#define BCM540X_AUX_10BASET_FD                      BIT_9
+#define BCM540X_AUX_100BASETX_HD                    (BIT_8 | BIT_9)
+#define BCM540X_AUX_100BASET4                       BIT_10
+#define BCM540X_AUX_100BASETX_FD                    (BIT_8 | BIT_10)
+#define BCM540X_AUX_100BASET_HD                     (BIT_9 | BIT_10)
+#define BCM540X_AUX_100BASET_FD                     (BIT_8 | BIT_9 | BIT_10)
+
+
+/* Interrupt status. */
+#define BCM540X_INT_STATUS_REG                      0x1a
+
+#define BCM540X_INT_LINK_CHANGE                     BIT_1
+#define BCM540X_INT_SPEED_CHANGE                    BIT_2
+#define BCM540X_INT_DUPLEX_CHANGE                   BIT_3
+#define BCM540X_INT_AUTO_NEG_PAGE_RX                BIT_10
+
+
+/* Interrupt mask register. */
+#define BCM540X_INT_MASK_REG                        0x1b
+
+
+
+/******************************************************************************/
+/* Register definitions. */
+/******************************************************************************/
+
+typedef volatile LM_UINT8 T3_8BIT_REGISTER, *PT3_8BIT_REGISTER;
+typedef volatile LM_UINT16 T3_16BIT_REGISTER, *PT3_16BIT_REGISTER;
+typedef volatile LM_UINT32 T3_32BIT_REGISTER, *PT3_32BIT_REGISTER;
+
+typedef struct {
+    /* Big endian format. */
+    T3_32BIT_REGISTER High;
+    T3_32BIT_REGISTER Low;
+} T3_64BIT_REGISTER, *PT3_64BIT_REGISTER;
+
+typedef T3_64BIT_REGISTER T3_64BIT_HOST_ADDR, *PT3_64BIT_HOST_ADDR;
+
+#define T3_NUM_OF_DMA_DESC    256
+#define T3_NUM_OF_MBUF        768
+
+typedef struct 
+{
+  T3_64BIT_REGISTER host_addr;
+  T3_32BIT_REGISTER nic_mbuf;
+  T3_16BIT_REGISTER len;
+  T3_16BIT_REGISTER cqid_sqid;
+  T3_32BIT_REGISTER flags;
+  T3_32BIT_REGISTER opaque1;
+  T3_32BIT_REGISTER opaque2;
+  T3_32BIT_REGISTER opaque3;
+}T3_DMA_DESC, *PT3_DMA_DESC;
+
+
+
+/******************************************************************************/
+/* Ring control block. */
+/******************************************************************************/
+
+typedef struct {
+    T3_64BIT_REGISTER HostRingAddr;
+
+    union {
+        struct {
+#ifdef BIG_ENDIAN_HOST
+            T3_16BIT_REGISTER MaxLen;
+            T3_16BIT_REGISTER Flags;
+#else /* BIG_ENDIAN_HOST */
+            T3_16BIT_REGISTER Flags;
+            T3_16BIT_REGISTER MaxLen;
+#endif
+        } s;
+
+        T3_32BIT_REGISTER MaxLen_Flags;
+    } u;
+
+    T3_32BIT_REGISTER NicRingAddr;
+} T3_RCB, *PT3_RCB;
+
+#define T3_RCB_FLAG_USE_EXT_RECV_BD                     BIT_0
+#define T3_RCB_FLAG_RING_DISABLED                       BIT_1
+
+
+
+/******************************************************************************/
+/* Status block. */
+/******************************************************************************/
+
+/* 
+ * Size of status block is actually 0x50 bytes.  Use 0x80 bytes for
+ * cache line alignment. 
+ */
+#define T3_STATUS_BLOCK_SIZE                                    0x80
+
+typedef struct {
+    volatile LM_UINT32 Status;
+    #define STATUS_BLOCK_UPDATED                                BIT_0
+    #define STATUS_BLOCK_LINK_CHANGED_STATUS                    BIT_1
+    #define STATUS_BLOCK_ERROR                                  BIT_2
+
+    volatile LM_UINT32 StatusTag;
+
+#ifdef BIG_ENDIAN_HOST
+    volatile LM_UINT16 RcvStdConIdx;
+    volatile LM_UINT16 RcvJumboConIdx;
+
+    volatile LM_UINT16 Reserved2;
+    volatile LM_UINT16 RcvMiniConIdx;
+
+    struct {
+        volatile LM_UINT16 SendConIdx;   /* Send consumer index. */
+        volatile LM_UINT16 RcvProdIdx;   /* Receive producer index. */
+    } Idx[16];
+#else /* BIG_ENDIAN_HOST */
+    volatile LM_UINT16 RcvJumboConIdx;
+    volatile LM_UINT16 RcvStdConIdx;
+
+    volatile LM_UINT16 RcvMiniConIdx;
+    volatile LM_UINT16 Reserved2;
+
+    struct {
+        volatile LM_UINT16 RcvProdIdx;   /* Receive producer index. */
+        volatile LM_UINT16 SendConIdx;   /* Send consumer index. */
+    } Idx[16];
+#endif
+} T3_STATUS_BLOCK, *PT3_STATUS_BLOCK;
+
+
+
+/******************************************************************************/
+/* Receive buffer descriptors. */
+/******************************************************************************/
+
+typedef struct {
+    T3_64BIT_HOST_ADDR HostAddr;
+
+#ifdef BIG_ENDIAN_HOST
+    volatile LM_UINT16 Index;
+    volatile LM_UINT16 Len;
+
+    volatile LM_UINT16 Type;
+    volatile LM_UINT16 Flags;
+
+    volatile LM_UINT16 IpCksum;
+    volatile LM_UINT16 TcpUdpCksum;
+
+    volatile LM_UINT16 ErrorFlag;
+    volatile LM_UINT16 VlanTag;
+#else /* BIG_ENDIAN_HOST */
+    volatile LM_UINT16 Len;
+    volatile LM_UINT16 Index;
+
+    volatile LM_UINT16 Flags;
+    volatile LM_UINT16 Type;
+
+    volatile LM_UINT16 TcpUdpCksum;
+    volatile LM_UINT16 IpCksum;
+
+    volatile LM_UINT16 VlanTag;
+    volatile LM_UINT16 ErrorFlag;
+#endif
+
+    volatile LM_UINT32 Reserved;
+    volatile LM_UINT32 Opaque;
+} T3_RCV_BD, *PT3_RCV_BD;
+
+
+typedef struct {
+    T3_64BIT_HOST_ADDR HostAddr[3];
+
+#ifdef BIG_ENDIAN_HOST
+    LM_UINT16 Len1;
+    LM_UINT16 Len2;
+
+    LM_UINT16 Len3;
+    LM_UINT16 Reserved1;
+#else /* BIG_ENDIAN_HOST */
+    LM_UINT16 Len2;
+    LM_UINT16 Len1;
+
+    LM_UINT16 Reserved1;
+    LM_UINT16 Len3;
+#endif
+
+    T3_RCV_BD StdRcvBd;
+} T3_EXT_RCV_BD, *PT3_EXT_RCV_BD;
+
+
+/* Error flags. */
+#define RCV_BD_ERR_BAD_CRC                          0x0001
+#define RCV_BD_ERR_COLL_DETECT                      0x0002
+#define RCV_BD_ERR_LINK_LOST_DURING_PKT             0x0004
+#define RCV_BD_ERR_PHY_DECODE_ERR                   0x0008
+#define RCV_BD_ERR_ODD_NIBBLED_RCVD_MII             0x0010
+#define RCV_BD_ERR_MAC_ABORT                        0x0020
+#define RCV_BD_ERR_LEN_LT_64                        0x0040
+#define RCV_BD_ERR_TRUNC_NO_RESOURCES               0x0080
+#define RCV_BD_ERR_GIANT_FRAME_RCVD                 0x0100
+
+
+/* Buffer descriptor flags. */
+#define RCV_BD_FLAG_END                             0x0004
+#define RCV_BD_FLAG_JUMBO_RING                      0x0020
+#define RCV_BD_FLAG_VLAN_TAG                        0x0040
+#define RCV_BD_FLAG_FRAME_HAS_ERROR                 0x0400
+#define RCV_BD_FLAG_MINI_RING                       0x0800
+#define RCV_BD_FLAG_IP_CHKSUM_FIELD                 0x1000
+#define RCV_BD_FLAG_TCP_UDP_CHKSUM_FIELD            0x2000
+#define RCV_BD_FLAG_TCP_PACKET                      0x4000
+
+
+
+/******************************************************************************/
+/* Send buffer descriptor. */
+/******************************************************************************/
+
+typedef struct {
+    T3_64BIT_HOST_ADDR HostAddr;
+
+    union {
+        struct {
+#ifdef BIG_ENDIAN_HOST
+            LM_UINT16 Len;
+            LM_UINT16 Flags;
+#else /* BIG_ENDIAN_HOST */
+            LM_UINT16 Flags;
+            LM_UINT16 Len;
+#endif
+        } s1;
+
+        LM_UINT32 Len_Flags;
+    } u1;
+
+    union {
+        struct {
+#ifdef BIG_ENDIAN_HOST
+            LM_UINT16 Reserved;
+            LM_UINT16 VlanTag;
+#else /* BIG_ENDIAN_HOST */
+            LM_UINT16 VlanTag;
+            LM_UINT16 Reserved;
+#endif
+        } s2;
+
+        LM_UINT32 VlanTag;
+    } u2;
+} T3_SND_BD, *PT3_SND_BD;
+
+
+/* Send buffer descriptor flags. */
+#define SND_BD_FLAG_TCP_UDP_CKSUM                   0x0001
+#define SND_BD_FLAG_IP_CKSUM                        0x0002
+#define SND_BD_FLAG_END                             0x0004
+#define SND_BD_FLAG_IP_FRAG                         0x0008
+#define SND_BD_FLAG_IP_FRAG_END                     0x0010
+#define SND_BD_FLAG_VLAN_TAG                        0x0040
+#define SND_BD_FLAG_COAL_NOW                        0x0080
+#define SND_BD_FLAG_CPU_PRE_DMA                     0x0100
+#define SND_BD_FLAG_CPU_POST_DMA                    0x0200
+#define SND_BD_FLAG_INSERT_SRC_ADDR                 0x1000
+#define SND_BD_FLAG_CHOOSE_SRC_ADDR                 0x6000
+#define SND_BD_FLAG_DONT_GEN_CRC                    0x8000
+
+/* MBUFs */
+typedef struct T3_MBUF_FRAME_DESC {
+#ifdef BIG_ENDIAN_HOST
+  LM_UINT32 status_control;
+  union {
+    struct {
+      LM_UINT8 cqid;
+      LM_UINT8 reserved1;
+      LM_UINT16 length;
+    }s1;
+    LM_UINT32 word;
+  }u1;
+  union {
+    struct 
+    {
+      LM_UINT16 ip_hdr_start;
+      LM_UINT16 tcp_udp_hdr_start;
+    }s2;
+
+    LM_UINT32 word;
+  }u2;
+
+  union {
+    struct {
+      LM_UINT16 data_start;
+      LM_UINT16 vlan_id;
+    }s3;
+    
+    LM_UINT32 word;
+  }u3;
+
+  union {
+    struct {
+      LM_UINT16 ip_checksum;
+      LM_UINT16 tcp_udp_checksum;
+    }s4;
+
+    LM_UINT32 word;
+  }u4;
+
+  union {
+    struct {
+      LM_UINT16 pseudo_checksum;
+      LM_UINT16 checksum_status;
+    }s5;
+
+    LM_UINT32 word;
+  }u5;
+  
+  union {
+    struct {
+      LM_UINT16 rule_match;
+      LM_UINT8 class;
+      LM_UINT8 rupt;
+    }s6;
+
+    LM_UINT32 word;
+  }u6;
+
+  union {
+    struct {
+      LM_UINT16 reserved2;
+      LM_UINT16 mbuf_num;
+    }s7;
+
+    LM_UINT32 word;
+  }u7;
+
+  LM_UINT32 reserved3;
+  LM_UINT32 reserved4;
+#else
+  LM_UINT32 status_control;
+  union {
+    struct {
+      LM_UINT16 length;
+      LM_UINT8  reserved1;
+      LM_UINT8  cqid;
+    }s1;
+    LM_UINT32 word;
+  }u1;
+  union {
+    struct 
+    {
+      LM_UINT16 tcp_udp_hdr_start;
+      LM_UINT16 ip_hdr_start;
+    }s2;
+
+    LM_UINT32 word;
+  }u2;
+
+  union {
+    struct {
+      LM_UINT16 vlan_id;
+      LM_UINT16 data_start;
+    }s3;
+    
+    LM_UINT32 word;
+  }u3;
+
+  union {
+    struct {
+      LM_UINT16 tcp_udp_checksum;
+      LM_UINT16 ip_checksum;
+    }s4;
+
+    LM_UINT32 word;
+  }u4;
+
+  union {
+    struct {
+      LM_UINT16 checksum_status;
+      LM_UINT16 pseudo_checksum;
+    }s5;
+
+    LM_UINT32 word;
+  }u5;
+  
+  union {
+    struct {
+      LM_UINT8 rupt;
+      LM_UINT8 class;
+      LM_UINT16 rule_match;
+    }s6;
+
+    LM_UINT32 word;
+  }u6;
+
+  union {
+    struct {
+      LM_UINT16 mbuf_num;
+      LM_UINT16 reserved2;
+    }s7;
+
+    LM_UINT32 word;
+  }u7;
+
+  LM_UINT32 reserved3;
+  LM_UINT32 reserved4;
+#endif
+}T3_MBUF_FRAME_DESC,*PT3_MBUF_FRAME_DESC;
+
+typedef struct T3_MBUF_HDR {
+  union {
+    struct {
+      unsigned int C:1;
+      unsigned int F:1;
+      unsigned int reserved1:7;
+      unsigned int next_mbuf:16;
+      unsigned int length:7;
+    }s1;
+    
+    LM_UINT32 word;
+  }u1;
+  
+  LM_UINT32 next_frame_ptr;
+}T3_MBUF_HDR, *PT3_MBUF_HDR;
+
+typedef struct T3_MBUF
+{
+  T3_MBUF_HDR hdr;
+  union
+  {
+    struct {
+      T3_MBUF_FRAME_DESC frame_hdr;
+      LM_UINT32 data[20];
+    }s1;
+
+    struct {
+      LM_UINT32 data[30];
+    }s2;
+  }body;
+}T3_MBUF, *PT3_MBUF;
+
+#define T3_MBUF_BASE   (T3_NIC_MBUF_POOL_ADDR >> 7)
+#define T3_MBUF_END    ((T3_NIC_MBUF_POOL_ADDR + T3_NIC_MBUF_POOL_SIZE) >> 7)
+
+
+
+/******************************************************************************/
+/* Statistics block. */
+/******************************************************************************/
+
+typedef struct {
+    LM_UINT8 Reserved0[0x400-0x300];
+
+    /* Statistics maintained by Receive MAC. */
+    T3_64BIT_REGISTER ifHCInOctets;
+    T3_64BIT_REGISTER Reserved1;
+    T3_64BIT_REGISTER etherStatsFragments;
+    T3_64BIT_REGISTER ifHCInUcastPkts;
+    T3_64BIT_REGISTER ifHCInMulticastPkts;
+    T3_64BIT_REGISTER ifHCInBroadcastPkts;
+    T3_64BIT_REGISTER dot3StatsFCSErrors;
+    T3_64BIT_REGISTER dot3StatsAlignmentErrors;
+    T3_64BIT_REGISTER xonPauseFramesReceived;
+    T3_64BIT_REGISTER xoffPauseFramesReceived;
+    T3_64BIT_REGISTER macControlFramesReceived;
+    T3_64BIT_REGISTER xoffStateEntered;
+    T3_64BIT_REGISTER dot3StatsFramesTooLong;
+    T3_64BIT_REGISTER etherStatsJabbers;
+    T3_64BIT_REGISTER etherStatsUndersizePkts;
+    T3_64BIT_REGISTER inRangeLengthError;
+    T3_64BIT_REGISTER outRangeLengthError;
+    T3_64BIT_REGISTER etherStatsPkts64Octets;
+    T3_64BIT_REGISTER etherStatsPkts65Octetsto127Octets;
+    T3_64BIT_REGISTER etherStatsPkts128Octetsto255Octets;
+    T3_64BIT_REGISTER etherStatsPkts256Octetsto511Octets;
+    T3_64BIT_REGISTER etherStatsPkts512Octetsto1023Octets;
+    T3_64BIT_REGISTER etherStatsPkts1024Octetsto1522Octets;
+    T3_64BIT_REGISTER etherStatsPkts1523Octetsto2047Octets;
+    T3_64BIT_REGISTER etherStatsPkts2048Octetsto4095Octets;
+    T3_64BIT_REGISTER etherStatsPkts4096Octetsto8191Octets;
+    T3_64BIT_REGISTER etherStatsPkts8192Octetsto9022Octets;
+
+    T3_64BIT_REGISTER Unused1[37];
+
+    /* Statistics maintained by Transmit MAC. */
+    T3_64BIT_REGISTER ifHCOutOctets;
+    T3_64BIT_REGISTER Reserved2;
+    T3_64BIT_REGISTER etherStatsCollisions;
+    T3_64BIT_REGISTER outXonSent;
+    T3_64BIT_REGISTER outXoffSent;
+    T3_64BIT_REGISTER flowControlDone;
+    T3_64BIT_REGISTER dot3StatsInternalMacTransmitErrors;
+    T3_64BIT_REGISTER dot3StatsSingleCollisionFrames;
+    T3_64BIT_REGISTER dot3StatsMultipleCollisionFrames;
+    T3_64BIT_REGISTER dot3StatsDeferredTransmissions;
+    T3_64BIT_REGISTER Reserved3;
+    T3_64BIT_REGISTER dot3StatsExcessiveCollisions;
+    T3_64BIT_REGISTER dot3StatsLateCollisions;
+    T3_64BIT_REGISTER dot3Collided2Times;
+    T3_64BIT_REGISTER dot3Collided3Times;
+    T3_64BIT_REGISTER dot3Collided4Times;
+    T3_64BIT_REGISTER dot3Collided5Times;
+    T3_64BIT_REGISTER dot3Collided6Times;
+    T3_64BIT_REGISTER dot3Collided7Times;
+    T3_64BIT_REGISTER dot3Collided8Times;
+    T3_64BIT_REGISTER dot3Collided9Times;
+    T3_64BIT_REGISTER dot3Collided10Times;
+    T3_64BIT_REGISTER dot3Collided11Times;
+    T3_64BIT_REGISTER dot3Collided12Times;
+    T3_64BIT_REGISTER dot3Collided13Times;
+    T3_64BIT_REGISTER dot3Collided14Times;
+    T3_64BIT_REGISTER dot3Collided15Times;
+    T3_64BIT_REGISTER ifHCOutUcastPkts;
+    T3_64BIT_REGISTER ifHCOutMulticastPkts;
+    T3_64BIT_REGISTER ifHCOutBroadcastPkts;
+    T3_64BIT_REGISTER dot3StatsCarrierSenseErrors;
+    T3_64BIT_REGISTER ifOutDiscards;
+    T3_64BIT_REGISTER ifOutErrors;
+
+    T3_64BIT_REGISTER Unused2[31];
+
+    /* Statistics maintained by Receive List Placement. */
+    T3_64BIT_REGISTER COSIfHCInPkts[16];
+    T3_64BIT_REGISTER COSFramesDroppedDueToFilters;
+    T3_64BIT_REGISTER nicDmaWriteQueueFull;
+    T3_64BIT_REGISTER nicDmaWriteHighPriQueueFull;
+    T3_64BIT_REGISTER nicNoMoreRxBDs;
+    T3_64BIT_REGISTER ifInDiscards;
+    T3_64BIT_REGISTER ifInErrors;
+    T3_64BIT_REGISTER nicRecvThresholdHit;
+
+    T3_64BIT_REGISTER Unused3[9];
+
+    /* Statistics maintained by Send Data Initiator. */
+    T3_64BIT_REGISTER COSIfHCOutPkts[16];
+    T3_64BIT_REGISTER nicDmaReadQueueFull;
+    T3_64BIT_REGISTER nicDmaReadHighPriQueueFull;
+    T3_64BIT_REGISTER nicSendDataCompQueueFull;
+
+    /* Statistics maintained by Host Coalescing. */
+    T3_64BIT_REGISTER nicRingSetSendProdIndex;
+    T3_64BIT_REGISTER nicRingStatusUpdate;
+    T3_64BIT_REGISTER nicInterrupts;
+    T3_64BIT_REGISTER nicAvoidedInterrupts;
+    T3_64BIT_REGISTER nicSendThresholdHit;
+
+    LM_UINT8 Reserved4[0xb00-0x9c0];
+} T3_STATS_BLOCK, *PT3_STATS_BLOCK;
+
+
+
+/******************************************************************************/
+/* PCI configuration registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_16BIT_REGISTER VendorId;
+    T3_16BIT_REGISTER DeviceId;
+
+    T3_16BIT_REGISTER Command;
+    T3_16BIT_REGISTER Status;
+
+    T3_32BIT_REGISTER ClassCodeRevId;
+
+    T3_8BIT_REGISTER CacheLineSize;
+    T3_8BIT_REGISTER LatencyTimer;
+    T3_8BIT_REGISTER HeaderType;
+    T3_8BIT_REGISTER Bist;
+
+    T3_32BIT_REGISTER MemBaseAddrLow;
+    T3_32BIT_REGISTER MemBaseAddrHigh;
+
+    LM_UINT8 Unused1[20];
+
+    T3_16BIT_REGISTER SubsystemVendorId;
+    T3_16BIT_REGISTER SubsystemId;
+
+    T3_32BIT_REGISTER RomBaseAddr;
+
+    T3_8BIT_REGISTER PciXCapiblityPtr;
+    LM_UINT8 Unused2[7];
+
+    T3_8BIT_REGISTER IntLine;
+    T3_8BIT_REGISTER IntPin;
+    T3_8BIT_REGISTER MinGnt;
+    T3_8BIT_REGISTER MaxLat;
+
+    T3_8BIT_REGISTER PciXCapabilities;
+    T3_8BIT_REGISTER PmCapabilityPtr;
+    T3_16BIT_REGISTER PciXCommand;
+
+    T3_32BIT_REGISTER PciXStatus;
+
+    T3_8BIT_REGISTER PmCapabilityId;
+    T3_8BIT_REGISTER VpdCapabilityPtr;
+    T3_16BIT_REGISTER PmCapabilities;
+
+    T3_16BIT_REGISTER PmCtrlStatus;
+    #define PM_CTRL_PME_STATUS            BIT_15
+    #define PM_CTRL_PME_ENABLE            BIT_8
+    #define PM_CTRL_PME_POWER_STATE_D0    0
+    #define PM_CTRL_PME_POWER_STATE_D1    1
+    #define PM_CTRL_PME_POWER_STATE_D2    2
+    #define PM_CTRL_PME_POWER_STATE_D3H   3
+
+    T3_8BIT_REGISTER BridgeSupportExt;
+    T3_8BIT_REGISTER PmData;
+
+    T3_8BIT_REGISTER VpdCapabilityId;
+    T3_8BIT_REGISTER MsiCapabilityPtr;
+    T3_16BIT_REGISTER VpdAddrFlag;
+    #define VPD_FLAG_WRITE      (1 << 15)
+    #define VPD_FLAG_RW_MASK    (1 << 15)
+    #define VPD_FLAG_READ       0
+
+
+    T3_32BIT_REGISTER VpdData;
+
+    T3_8BIT_REGISTER MsiCapabilityId;
+    T3_8BIT_REGISTER NextCapabilityPtr;
+    T3_16BIT_REGISTER MsiCtrl;
+    #define MSI_CTRL_64BIT_CAP     (1 << 7)
+    #define MSI_CTRL_MSG_ENABLE(x) (x << 4)
+    #define MSI_CTRL_MSG_CAP(x)    (x << 1)
+    #define MSI_CTRL_ENABLE        (1 << 0)
+  
+
+    T3_32BIT_REGISTER MsiAddrLow;
+    T3_32BIT_REGISTER MsiAddrHigh;
+
+    T3_16BIT_REGISTER MsiData;
+    T3_16BIT_REGISTER Unused3;
+
+    T3_32BIT_REGISTER MiscHostCtrl;
+    #define MISC_HOST_CTRL_CLEAR_INT                        BIT_0
+    #define MISC_HOST_CTRL_MASK_PCI_INT                     BIT_1
+    #define MISC_HOST_CTRL_ENABLE_ENDIAN_BYTE_SWAP          BIT_2
+    #define MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP          BIT_3
+    #define MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW          BIT_4
+    #define MISC_HOST_CTRL_ENABLE_CLK_REG_RW                BIT_5
+    #define MISC_HOST_CTRL_ENABLE_REG_WORD_SWAP             BIT_6
+    #define MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS           BIT_7
+    #define MISC_HOST_CTRL_ENABLE_INT_MASK_MODE             BIT_8
+    #define MISC_HOST_CTRL_ENABLE_TAGGED_STATUS_MODE        BIT_9
+
+    T3_32BIT_REGISTER DmaReadWriteCtrl;
+    #define DMA_CTRL_WRITE_BOUNDARY_MASK            (BIT_11 | BIT_12 | BIT_13)
+    #define DMA_CTRL_WRITE_BOUNDARY_DISABLE         0
+    #define DMA_CTRL_WRITE_BOUNDARY_16              BIT_11
+    #define DMA_CTRL_WRITE_BOUNDARY_32              BIT_12
+    #define DMA_CTRL_WRITE_BOUNDARY_64              (BIT_12 | BIT_11)
+    #define DMA_CTRL_WRITE_BOUNDARY_128             BIT_13
+    #define DMA_CTRL_WRITE_BOUNDARY_256             (BIT_13 | BIT_11)
+    #define DMA_CTRL_WRITE_BOUNDARY_512             (BIT_13 | BIT_12)
+    #define DMA_CTRL_WRITE_BOUNDARY_1024            (BIT_13 | BIT_12 | BIT_11)
+    #define DMA_CTRL_WRITE_ONE_DMA_AT_ONCE          BIT_14
+
+
+    T3_32BIT_REGISTER PciState;
+    #define T3_PCI_STATE_FORCE_PCI_RESET                    BIT_0
+    #define T3_PCI_STATE_INTERRUPT_NOT_ACTIVE               BIT_1
+    #define T3_PCI_STATE_NOT_PCI_X_BUS                      BIT_2
+    #define T3_PCI_STATE_HIGH_BUS_SPEED                     BIT_3
+    #define T3_PCI_STATE_32BIT_PCI_BUS                      BIT_4
+    #define T3_PCI_STATE_PCI_ROM_ENABLE                     BIT_5
+    #define T3_PCI_STATE_PCI_ROM_RETRY_ENABLE               BIT_6
+    #define T3_PCI_STATE_FLAT_VIEW                          BIT_8
+    #define T3_PCI_STATE_RETRY_SAME_DMA                     BIT_13
+
+    T3_32BIT_REGISTER ClockCtrl;
+    #define T3_PCI_CLKCTRL_TXCPU_CLK_DISABLE                BIT_11
+    #define T3_PCI_CLKCTRL_RXCPU_CLK_DISABLE                BIT_10
+    #define T3_PCI_CLKCTRL_CORE_CLK_DISABLE                 BIT_9
+
+    T3_32BIT_REGISTER RegBaseAddr;
+
+    T3_32BIT_REGISTER MemWindowBaseAddr;
+    
+#ifdef NIC_CPU_VIEW
+  /* These registers are ONLY visible to NIC CPU */
+    T3_32BIT_REGISTER PowerConsumed;
+    T3_32BIT_REGISTER PowerDissipated;
+#else /* NIC_CPU_VIEW */
+    T3_32BIT_REGISTER RegData;
+    T3_32BIT_REGISTER MemWindowData;
+#endif /* !NIC_CPU_VIEW */
+
+    T3_32BIT_REGISTER ModeCtrl;
+
+    T3_32BIT_REGISTER MiscCfg;
+
+    T3_32BIT_REGISTER MiscLocalCtrl;
+
+    T3_32BIT_REGISTER Unused4;
+
+    /* NOTE: Big/Little-endian clarification needed.  Are these register */
+    /* in big or little endian formate. */
+    T3_64BIT_REGISTER StdRingProdIdx;
+    T3_64BIT_REGISTER RcvRetRingConIdx;
+    T3_64BIT_REGISTER SndProdIdx;
+
+    LM_UINT8 Unused5[80];
+} T3_PCI_CONFIGURATION, *PT3_PCI_CONFIGURATION;
+
+#define PCIX_CMD_MAX_SPLIT_MASK                         0x0070
+#define PCIX_CMD_MAX_SPLIT_SHL                          4
+#define PCIX_CMD_MAX_BURST_MASK                         0x000c
+#define PCIX_CMD_MAX_BURST_SHL                          2
+#define PCIX_CMD_MAX_BURST_CPIOB                        2
+
+/******************************************************************************/
+/* Mac control registers. */
+/******************************************************************************/
+
+typedef struct {
+    /* MAC mode control. */
+    T3_32BIT_REGISTER Mode;
+    #define MAC_MODE_GLOBAL_RESET                       BIT_0
+    #define MAC_MODE_HALF_DUPLEX                        BIT_1
+    #define MAC_MODE_PORT_MODE_MASK                     (BIT_2 | BIT_3)
+    #define MAC_MODE_PORT_MODE_TBI                      (BIT_2 | BIT_3)
+    #define MAC_MODE_PORT_MODE_GMII                     BIT_3
+    #define MAC_MODE_PORT_MODE_MII                      BIT_2
+    #define MAC_MODE_PORT_MODE_NONE                     BIT_NONE
+    #define MAC_MODE_PORT_INTERNAL_LOOPBACK             BIT_4
+    #define MAC_MODE_TAGGED_MAC_CONTROL                 BIT_7
+    #define MAC_MODE_TX_BURSTING                        BIT_8
+    #define MAC_MODE_MAX_DEFER                          BIT_9
+    #define MAC_MODE_LINK_POLARITY                      BIT_10
+    #define MAC_MODE_ENABLE_RX_STATISTICS               BIT_11
+    #define MAC_MODE_CLEAR_RX_STATISTICS                BIT_12
+    #define MAC_MODE_FLUSH_RX_STATISTICS                BIT_13
+    #define MAC_MODE_ENABLE_TX_STATISTICS               BIT_14
+    #define MAC_MODE_CLEAR_TX_STATISTICS                BIT_15
+    #define MAC_MODE_FLUSH_TX_STATISTICS                BIT_16
+    #define MAC_MODE_SEND_CONFIGS                       BIT_17
+    #define MAC_MODE_DETECT_MAGIC_PACKET_ENABLE         BIT_18
+    #define MAC_MODE_ACPI_POWER_ON_ENABLE               BIT_19
+    #define MAC_MODE_ENABLE_MIP                         BIT_20
+    #define MAC_MODE_ENABLE_TDE                         BIT_21
+    #define MAC_MODE_ENABLE_RDE                         BIT_22
+    #define MAC_MODE_ENABLE_FHDE                        BIT_23
+
+    /* MAC status */
+    T3_32BIT_REGISTER Status;
+    #define MAC_STATUS_PCS_SYNCED                       BIT_0
+    #define MAC_STATUS_SIGNAL_DETECTED                  BIT_1
+    #define MAC_STATUS_RECEIVING_CFG                    BIT_2
+    #define MAC_STATUS_CFG_CHANGED                      BIT_3
+    #define MAC_STATUS_SYNC_CHANGED                     BIT_4
+    #define MAC_STATUS_PORT_DECODE_ERROR                BIT_10
+    #define MAC_STATUS_LINK_STATE_CHANGED               BIT_12
+    #define MAC_STATUS_MI_COMPLETION                    BIT_22
+    #define MAC_STATUS_MI_INTERRUPT                     BIT_23
+    #define MAC_STATUS_AP_ERROR                         BIT_24
+    #define MAC_STATUS_ODI_ERROR                        BIT_25
+    #define MAC_STATUS_RX_STATS_OVERRUN                 BIT_26
+    #define MAC_STATUS_TX_STATS_OVERRUN                 BIT_27
+
+    /* Event Enable */
+    T3_32BIT_REGISTER MacEvent;
+    #define MAC_EVENT_ENABLE_PORT_DECODE_ERR            BIT_10
+    #define MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN    BIT_12
+    #define MAC_EVENT_ENABLE_MI_COMPLETION              BIT_22
+    #define MAC_EVENT_ENABLE_MI_INTERRUPT               BIT_23
+    #define MAC_EVENT_ENABLE_AP_ERROR                   BIT_24
+    #define MAC_EVENT_ENABLE_ODI_ERROR                  BIT_25
+    #define MAC_EVENT_ENABLE_RX_STATS_OVERRUN           BIT_26
+    #define MAC_EVENT_ENABLE_TX_STATS_OVERRUN           BIT_27
+
+    /* Led control. */
+    T3_32BIT_REGISTER LedCtrl;
+    #define LED_CTRL_OVERRIDE_LINK_LED                  BIT_0
+    #define LED_CTRL_1000MBPS_LED_ON                    BIT_1
+    #define LED_CTRL_100MBPS_LED_ON                     BIT_2
+    #define LED_CTRL_10MBPS_LED_ON                      BIT_3
+    #define LED_CTRL_OVERRIDE_TRAFFIC_LED               BIT_4
+    #define LED_CTRL_BLINK_TRAFFIC_LED                  BIT_5
+    #define LED_CTRL_TRAFFIC_LED                        BIT_6
+    #define LED_CTRL_1000MBPS_LED_STATUS                BIT_7
+    #define LED_CTRL_100MBPS_LED_STATUS                 BIT_8
+    #define LED_CTRL_10MBPS_LED_STATUS                  BIT_9
+    #define LED_CTRL_TRAFFIC_LED_STATUS                 BIT_10
+    #define LED_CTRL_MAC_MODE                           BIT_NONE
+    #define LED_CTRL_PHY_MODE_1                         BIT_11
+    #define LED_CTRL_PHY_MODE_2                         BIT_12
+    #define LED_CTRL_BLINK_RATE_MASK                    0x7ff80000
+    #define LED_CTRL_OVERRIDE_BLINK_PERIOD              BIT_19
+    #define LED_CTRL_OVERRIDE_BLINK_RATE                BIT_31
+
+    /* MAC addresses. */
+    struct {
+        T3_32BIT_REGISTER High;             /* Upper 2 bytes. */
+        T3_32BIT_REGISTER Low;              /* Lower 4 bytes. */
+    } MacAddr[4];
+
+    /* ACPI Mbuf pointer. */
+    T3_32BIT_REGISTER AcpiMbufPtr;
+
+    /* ACPI Length and Offset. */
+    T3_32BIT_REGISTER AcpiLengthOffset;
+    #define ACPI_LENGTH_MASK                            0xffff
+    #define ACPI_OFFSET_MASK                            0x0fff0000
+    #define ACPI_LENGTH(x)                              x
+    #define ACPI_OFFSET(x)                              ((x) << 16)
+
+    /* Transmit random backoff. */
+    T3_32BIT_REGISTER TxBackoffSeed;
+    #define MAC_TX_BACKOFF_SEED_MASK                    0x3ff
+
+    /* Receive MTU */
+    T3_32BIT_REGISTER MtuSize;
+    #define MAC_RX_MTU_MASK                             0xffff
+
+    /* Gigabit PCS Test. */
+    T3_32BIT_REGISTER PcsTest;
+    #define MAC_PCS_TEST_DATA_PATTERN_MASK              0x0fffff
+    #define MAC_PCS_TEST_ENABLE                         BIT_20
+
+    /* Transmit Gigabit Auto-Negotiation. */
+    T3_32BIT_REGISTER TxAutoNeg;
+    #define MAC_AN_TX_AN_DATA_MASK                      0xffff
+
+    /* Receive Gigabit Auto-Negotiation. */
+    T3_32BIT_REGISTER RxAutoNeg;
+    #define MAC_AN_RX_AN_DATA_MASK                      0xffff
+
+    /* MI Communication. */
+    T3_32BIT_REGISTER MiCom;
+    #define MI_COM_CMD_MASK                             (BIT_26 | BIT_27)
+    #define MI_COM_CMD_WRITE                            BIT_26
+    #define MI_COM_CMD_READ                             BIT_27
+    #define MI_COM_READ_FAILED                          BIT_28
+    #define MI_COM_START                                BIT_29
+    #define MI_COM_BUSY                                 BIT_29
+
+    #define MI_COM_PHY_ADDR_MASK                        0x1f
+    #define MI_COM_FIRST_PHY_ADDR_BIT                   21
+
+    #define MI_COM_PHY_REG_ADDR_MASK                    0x1f
+    #define MI_COM_FIRST_PHY_REG_ADDR_BIT               16
+
+    #define MI_COM_PHY_DATA_MASK                        0xffff
+
+    /* MI Status. */
+    T3_32BIT_REGISTER MiStatus;
+    #define MI_STATUS_ENABLE_LINK_STATUS_ATTN           BIT_0
+
+    /* MI Mode. */
+    T3_32BIT_REGISTER MiMode;
+    #define MI_MODE_CLOCK_SPEED_10MHZ                   BIT_0
+    #define MI_MODE_USE_SHORT_PREAMBLE                  BIT_1
+    #define MI_MODE_AUTO_POLLING_ENABLE                 BIT_4
+    #define MI_MODE_CORE_CLOCK_SPEED_62MHZ              BIT_15
+
+    /* Auto-polling status. */
+    T3_32BIT_REGISTER AutoPollStatus;
+    #define AUTO_POLL_ERROR                             BIT_0
+
+    /* Transmit MAC mode. */
+    T3_32BIT_REGISTER TxMode;
+    #define TX_MODE_RESET                               BIT_0
+    #define TX_MODE_ENABLE                              BIT_1
+    #define TX_MODE_ENABLE_FLOW_CONTROL                 BIT_4
+    #define TX_MODE_ENABLE_BIG_BACKOFF                  BIT_5
+    #define TX_MODE_ENABLE_LONG_PAUSE                   BIT_6
+
+    /* Transmit MAC status. */
+    T3_32BIT_REGISTER TxStatus;
+    #define TX_STATUS_RX_CURRENTLY_XOFFED               BIT_0
+    #define TX_STATUS_SENT_XOFF                         BIT_1
+    #define TX_STATUS_SENT_XON                          BIT_2
+    #define TX_STATUS_LINK_UP                           BIT_3
+    #define TX_STATUS_ODI_UNDERRUN                      BIT_4
+    #define TX_STATUS_ODI_OVERRUN                       BIT_5
+
+    /* Transmit MAC length. */
+    T3_32BIT_REGISTER TxLengths;
+    #define TX_LEN_SLOT_TIME_MASK                       0xff
+    #define TX_LEN_IPG_MASK                             0x0f00
+    #define TX_LEN_IPG_CRS_MASK                         (BIT_12 | BIT_13)
+
+    /* Receive MAC mode. */
+    T3_32BIT_REGISTER RxMode;
+    #define RX_MODE_RESET                               BIT_0
+    #define RX_MODE_ENABLE                              BIT_1
+    #define RX_MODE_ENABLE_FLOW_CONTROL                 BIT_2
+    #define RX_MODE_KEEP_MAC_CONTROL                    BIT_3
+    #define RX_MODE_KEEP_PAUSE                          BIT_4
+    #define RX_MODE_ACCEPT_OVERSIZED                    BIT_5
+    #define RX_MODE_ACCEPT_RUNTS                        BIT_6
+    #define RX_MODE_LENGTH_CHECK                        BIT_7
+    #define RX_MODE_PROMISCUOUS_MODE                    BIT_8
+    #define RX_MODE_NO_CRC_CHECK                        BIT_9
+    #define RX_MODE_KEEP_VLAN_TAG                       BIT_10
+
+    /* Receive MAC status. */
+    T3_32BIT_REGISTER RxStatus;
+    #define RX_STATUS_REMOTE_TRANSMITTER_XOFFED         BIT_0
+    #define RX_STATUS_XOFF_RECEIVED                     BIT_1
+    #define RX_STATUS_XON_RECEIVED                      BIT_2
+
+    /* Hash registers. */
+    T3_32BIT_REGISTER HashReg[4];
+
+    /* Receive placement rules registers. */
+    struct {
+        T3_32BIT_REGISTER Rule;
+        T3_32BIT_REGISTER Value;
+    } RcvRules[16];
+
+    #define RCV_DISABLE_RULE_MASK                       0x7fffffff
+
+    #define RCV_RULE1_REJECT_BROADCAST_IDX              0x00
+    #define REJECT_BROADCAST_RULE1_RULE                 0xc2000000
+    #define REJECT_BROADCAST_RULE1_VALUE                0xffffffff
+
+    #define RCV_RULE2_REJECT_BROADCAST_IDX              0x01
+    #define REJECT_BROADCAST_RULE2_RULE                 0x86000004
+    #define REJECT_BROADCAST_RULE2_VALUE                0xffffffff
+
+#if INCLUDE_5701_AX_FIX
+    #define RCV_LAST_RULE_IDX                           0x04
+#else
+    #define RCV_LAST_RULE_IDX                           0x02
+#endif
+
+    T3_32BIT_REGISTER RcvRuleCfg;
+    #define RX_RULE_DEFAULT_CLASS                       (1 << 3)
+
+    LM_UINT8 Reserved1[140];
+
+    T3_32BIT_REGISTER SerdesCfg;
+    T3_32BIT_REGISTER SerdesStatus;
+
+    LM_UINT8 Reserved2[104];
+
+    volatile LM_UINT8 TxMacState[16];
+    volatile LM_UINT8 RxMacState[20];
+
+    LM_UINT8 Reserved3[476];
+
+    T3_32BIT_REGISTER RxStats[26];
+
+    LM_UINT8 Reserved4[24];
+
+    T3_32BIT_REGISTER TxStats[28];
+
+    LM_UINT8 Reserved5[784];
+} T3_MAC_CONTROL, *PT3_MAC_CONTROL;
+
+
+
+/******************************************************************************/
+/* Send data initiator control registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define T3_SND_DATA_IN_MODE_RESET                       BIT_0
+    #define T3_SND_DATA_IN_MODE_ENABLE                      BIT_1
+    #define T3_SND_DATA_IN_MODE_STATS_OFLW_ATTN_ENABLE      BIT_2
+
+    T3_32BIT_REGISTER Status;
+    #define T3_SND_DATA_IN_STATUS_STATS_OFLW_ATTN           BIT_2
+
+    T3_32BIT_REGISTER StatsCtrl;
+    #define T3_SND_DATA_IN_STATS_CTRL_ENABLE                BIT_0
+    #define T3_SND_DATA_IN_STATS_CTRL_FASTER_UPDATE         BIT_1
+    #define T3_SND_DATA_IN_STATS_CTRL_CLEAR                 BIT_2
+    #define T3_SND_DATA_IN_STATS_CTRL_FLUSH                 BIT_3
+    #define T3_SND_DATA_IN_STATS_CTRL_FORCE_ZERO            BIT_4
+
+    T3_32BIT_REGISTER StatsEnableMask;
+    T3_32BIT_REGISTER StatsIncMask;
+
+    LM_UINT8 Reserved[108];
+
+    T3_32BIT_REGISTER ClassOfServCnt[16];
+    T3_32BIT_REGISTER DmaReadQFullCnt;
+    T3_32BIT_REGISTER DmaPriorityReadQFullCnt;
+    T3_32BIT_REGISTER SdcQFullCnt;
+
+    T3_32BIT_REGISTER NicRingSetSendProdIdxCnt;
+    T3_32BIT_REGISTER StatusUpdatedCnt;
+    T3_32BIT_REGISTER InterruptsCnt;
+    T3_32BIT_REGISTER AvoidInterruptsCnt;
+    T3_32BIT_REGISTER SendThresholdHitCnt;
+
+    /* Unused space. */
+    LM_UINT8 Unused[800];
+} T3_SEND_DATA_INITIATOR, *PT3_SEND_DATA_INITIATOR;
+
+
+
+/******************************************************************************/
+/* Send data completion control registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define SND_DATA_COMP_MODE_RESET                        BIT_0
+    #define SND_DATA_COMP_MODE_ENABLE                       BIT_1
+
+    /* Unused space. */
+    LM_UINT8 Unused[1020];
+} T3_SEND_DATA_COMPLETION, *PT3_SEND_DATA_COMPLETION;
+
+
+
+/******************************************************************************/
+/* Send BD Ring Selector Control Registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define SND_BD_SEL_MODE_RESET                           BIT_0
+    #define SND_BD_SEL_MODE_ENABLE                          BIT_1
+    #define SND_BD_SEL_MODE_ATTN_ENABLE                     BIT_2
+
+    T3_32BIT_REGISTER Status;
+    #define SND_BD_SEL_STATUS_ERROR_ATTN                    BIT_2
+
+    T3_32BIT_REGISTER HwDiag;
+
+    /* Unused space. */
+    LM_UINT8 Unused1[52];
+
+    /* Send BD Ring Selector Local NIC Send BD Consumer Index. */
+    T3_32BIT_REGISTER NicSendBdSelConIdx[16];
+
+    /* Unused space. */
+    LM_UINT8 Unused2[896];
+} T3_SEND_BD_SELECTOR, *PT3_SEND_BD_SELECTOR;
+
+
+
+/******************************************************************************/
+/* Send BD initiator control registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define SND_BD_IN_MODE_RESET                            BIT_0
+    #define SND_BD_IN_MODE_ENABLE                           BIT_1
+    #define SND_BD_IN_MODE_ATTN_ENABLE                      BIT_2
+
+    T3_32BIT_REGISTER Status;
+    #define SND_BD_IN_STATUS_ERROR_ATTN                     BIT_2
+
+    /* Send BD initiator local NIC send BD producer index. */
+    T3_32BIT_REGISTER NicSendBdInProdIdx[16];
+
+    /* Unused space. */
+    LM_UINT8 Unused2[952];
+} T3_SEND_BD_INITIATOR, *PT3_SEND_BD_INITIATOR;
+
+
+
+/******************************************************************************/
+/* Send BD Completion Control. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define SND_BD_COMP_MODE_RESET                          BIT_0
+    #define SND_BD_COMP_MODE_ENABLE                         BIT_1
+    #define SND_BD_COMP_MODE_ATTN_ENABLE                    BIT_2
+
+    /* Unused space. */
+    LM_UINT8 Unused2[1020];
+} T3_SEND_BD_COMPLETION, *PT3_SEND_BD_COMPLETION;
+
+
+
+/******************************************************************************/
+/* Receive list placement control registers. */
+/******************************************************************************/
+
+typedef struct {
+    /* Mode. */
+    T3_32BIT_REGISTER Mode;
+    #define RCV_LIST_PLMT_MODE_RESET                        BIT_0
+    #define RCV_LIST_PLMT_MODE_ENABLE                       BIT_1
+    #define RCV_LIST_PLMT_MODE_CLASS0_ATTN_ENABLE           BIT_2
+    #define RCV_LIST_PLMT_MODE_MAPPING_OOR_ATTN_ENABLE      BIT_3
+    #define RCV_LIST_PLMT_MODE_STATS_OFLOW_ATTN_ENABLE      BIT_4
+
+    /* Status. */
+    T3_32BIT_REGISTER Status;
+    #define RCV_LIST_PLMT_STATUS_CLASS0_ATTN                BIT_2
+    #define RCV_LIST_PLMT_STATUS_MAPPING_ATTN               BIT_3
+    #define RCV_LIST_PLMT_STATUS_STATS_OFLOW_ATTN           BIT_4
+
+    /* Receive selector list lock register. */
+    T3_32BIT_REGISTER Lock;
+    #define RCV_LIST_SEL_LOCK_REQUEST_MASK                  0xffff
+    #define RCV_LIST_SEL_LOCK_GRANT_MASK                    0xffff0000
+
+    /* Selector non-empty bits. */
+    T3_32BIT_REGISTER NonEmptyBits;
+    #define RCV_LIST_SEL_NON_EMPTY_MASK                     0xffff
+
+    /* Receive list placement configuration register. */
+    T3_32BIT_REGISTER Config;
+
+    /* Receive List Placement statistics Control. */
+    T3_32BIT_REGISTER StatsCtrl;
+#define RCV_LIST_STATS_ENABLE                               BIT_0
+#define RCV_LIST_STATS_FAST_UPDATE                          BIT_1
+
+    /* Receive List Placement statistics Enable Mask. */
+    T3_32BIT_REGISTER StatsEnableMask;
+
+    /* Receive List Placement statistics Increment Mask. */
+    T3_32BIT_REGISTER StatsIncMask;
+
+    /* Unused space. */
+    LM_UINT8 Unused1[224];
+
+    struct {
+        T3_32BIT_REGISTER Head;
+        T3_32BIT_REGISTER Tail;
+        T3_32BIT_REGISTER Count;
+
+        /* Unused space. */
+        LM_UINT8 Unused[4];
+    } RcvSelectorList[16];
+
+    /* Local statistics counter. */
+    T3_32BIT_REGISTER ClassOfServCnt[16];
+
+    T3_32BIT_REGISTER DropDueToFilterCnt;
+    T3_32BIT_REGISTER DmaWriteQFullCnt;
+    T3_32BIT_REGISTER DmaHighPriorityWriteQFullCnt;
+    T3_32BIT_REGISTER NoMoreReceiveBdCnt;
+    T3_32BIT_REGISTER IfInDiscardsCnt;
+    T3_32BIT_REGISTER IfInErrorsCnt;
+    T3_32BIT_REGISTER RcvThresholdHitCnt;
+
+    /* Another unused space. */
+    LM_UINT8 Unused2[420];
+} T3_RCV_LIST_PLACEMENT, *PT3_RCV_LIST_PLACEMENT;
+
+
+
+/******************************************************************************/
+/* Receive Data and Receive BD Initiator Control. */
+/******************************************************************************/
+
+typedef struct {
+    /* Mode. */
+    T3_32BIT_REGISTER Mode;
+    #define RCV_DATA_BD_IN_MODE_RESET                   BIT_0
+    #define RCV_DATA_BD_IN_MODE_ENABLE                  BIT_1
+    #define RCV_DATA_BD_IN_MODE_JUMBO_BD_NEEDED         BIT_2
+    #define RCV_DATA_BD_IN_MODE_FRAME_TOO_BIG           BIT_3
+    #define RCV_DATA_BD_IN_MODE_INVALID_RING_SIZE       BIT_4
+
+    /* Status. */
+    T3_32BIT_REGISTER Status;
+    #define RCV_DATA_BD_IN_STATUS_JUMBO_BD_NEEDED       BIT_2
+    #define RCV_DATA_BD_IN_STATUS_FRAME_TOO_BIG         BIT_3
+    #define RCV_DATA_BD_IN_STATUS_INVALID_RING_SIZE     BIT_4
+
+    /* Split frame minium size. */
+    T3_32BIT_REGISTER SplitFrameMinSize;
+
+    /* Unused space. */
+    LM_UINT8 Unused1[0x2440-0x240c];
+
+    /* Receive RCBs. */
+    T3_RCB JumboRcvRcb;
+    T3_RCB StdRcvRcb;
+    T3_RCB MiniRcvRcb;
+
+    /* Receive Data and Receive BD Ring Initiator Local NIC Receive */
+    /* BD Consumber Index. */
+    T3_32BIT_REGISTER NicJumboConIdx;
+    T3_32BIT_REGISTER NicStdConIdx;
+    T3_32BIT_REGISTER NicMiniConIdx;
+
+    /* Unused space. */
+    LM_UINT8 Unused2[4];
+
+    /* Receive Data and Receive BD Initiator Local Receive Return ProdIdx. */
+    T3_32BIT_REGISTER RcvDataBdProdIdx[16];
+
+    /* Receive Data and Receive BD Initiator Hardware Diagnostic. */
+    T3_32BIT_REGISTER HwDiag;
+
+    /* Unused space. */
+    LM_UINT8 Unused3[828];
+} T3_RCV_DATA_BD_INITIATOR, *PT3_RCV_DATA_BD_INITIATOR;
+
+
+
+/******************************************************************************/
+/* Receive Data Completion Control Registes. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define RCV_DATA_COMP_MODE_RESET                        BIT_0
+    #define RCV_DATA_COMP_MODE_ENABLE                       BIT_1
+    #define RCV_DATA_COMP_MODE_ATTN_ENABLE                  BIT_2
+
+    /* Unused spaced. */
+    LM_UINT8 Unused[1020];
+} T3_RCV_DATA_COMPLETION, *PT3_RCV_DATA_COMPLETION;
+
+
+
+/******************************************************************************/
+/* Receive BD Initiator Control. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define RCV_BD_IN_MODE_RESET                            BIT_0
+    #define RCV_BD_IN_MODE_ENABLE                           BIT_1
+    #define RCV_BD_IN_MODE_BD_IN_DIABLED_RCB_ATTN_ENABLE    BIT_2
+
+    T3_32BIT_REGISTER Status;
+    #define RCV_BD_IN_STATUS_BD_IN_DIABLED_RCB_ATTN         BIT_2
+
+    T3_32BIT_REGISTER NicJumboRcvProdIdx;
+    T3_32BIT_REGISTER NicStdRcvProdIdx;
+    T3_32BIT_REGISTER NicMiniRcvProdIdx;
+
+    T3_32BIT_REGISTER MiniRcvThreshold;
+    T3_32BIT_REGISTER StdRcvThreshold;
+    T3_32BIT_REGISTER JumboRcvThreshold;
+
+    /* Unused space. */
+    LM_UINT8 Unused[992];
+} T3_RCV_BD_INITIATOR, *PT3_RCV_BD_INITIATOR;
+
+
+
+/******************************************************************************/
+/* Receive BD Completion Control Registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define RCV_BD_COMP_MODE_RESET                          BIT_0
+    #define RCV_BD_COMP_MODE_ENABLE                         BIT_1
+    #define RCV_BD_COMP_MODE_ATTN_ENABLE                    BIT_2
+
+    T3_32BIT_REGISTER Status;
+    #define RCV_BD_COMP_STATUS_ERROR_ATTN                   BIT_2
+
+    T3_32BIT_REGISTER  NicJumboRcvBdProdIdx;
+    T3_32BIT_REGISTER  NicStdRcvBdProdIdx;
+    T3_32BIT_REGISTER  NicMiniRcvBdProdIdx;
+
+    /* Unused space. */
+    LM_UINT8 Unused[1004];
+} T3_RCV_BD_COMPLETION, *PT3_RCV_BD_COMPLETION;
+
+
+
+/******************************************************************************/
+/* Receive list selector control register. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define RCV_LIST_SEL_MODE_RESET                         BIT_0
+    #define RCV_LIST_SEL_MODE_ENABLE                        BIT_1
+    #define RCV_LIST_SEL_MODE_ATTN_ENABLE                   BIT_2
+
+    T3_32BIT_REGISTER Status;
+    #define RCV_LIST_SEL_STATUS_ERROR_ATTN                  BIT_2
+
+    /* Unused space. */
+    LM_UINT8 Unused[1016];
+} T3_RCV_LIST_SELECTOR, *PT3_RCV_LIST_SELECTOR;
+
+
+
+/******************************************************************************/
+/* Mbuf cluster free registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+#define MBUF_CLUSTER_FREE_MODE_RESET    BIT_0
+#define MBUF_CLUSTER_FREE_MODE_ENABLE   BIT_1
+
+    T3_32BIT_REGISTER Status;
+
+    /* Unused space. */
+    LM_UINT8 Unused[1016];
+} T3_MBUF_CLUSTER_FREE, *PT3_MBUF_CLUSTER_FREE;
+
+
+
+/******************************************************************************/
+/* Host coalescing control registers. */
+/******************************************************************************/
+
+typedef struct {
+    /* Mode. */
+    T3_32BIT_REGISTER Mode;
+    #define HOST_COALESCE_RESET                         BIT_0
+    #define HOST_COALESCE_ENABLE                        BIT_1
+    #define HOST_COALESCE_ATTN                          BIT_2
+    #define HOST_COALESCE_NOW                           BIT_3
+    #define HOST_COALESCE_FULL_STATUS_MODE              BIT_NONE
+    #define HOST_COALESCE_64_BYTE_STATUS_MODE           BIT_7
+    #define HOST_COALESCE_32_BYTE_STATUS_MODE           BIT_8
+    #define HOST_COALESCE_CLEAR_TICKS_ON_RX_BD_EVENT    BIT_9
+    #define HOST_COALESCE_CLEAR_TICKS_ON_TX_BD_EVENT    BIT_10
+    #define HOST_COALESCE_NO_INT_ON_COALESCE_NOW_MODE   BIT_11
+    #define HOST_COALESCE_NO_INT_ON_FORCE_DMAD_MODE     BIT_12
+
+    /* Status. */
+    T3_32BIT_REGISTER Status;
+    #define HOST_COALESCE_ERROR_ATTN                    BIT_2
+
+    /* Receive coalescing ticks. */
+    T3_32BIT_REGISTER RxCoalescingTicks;
+
+    /* Send coalescing ticks. */
+    T3_32BIT_REGISTER TxCoalescingTicks;
+
+    /* Receive max coalesced frames. */
+    T3_32BIT_REGISTER RxMaxCoalescedFrames;
+
+    /* Send max coalesced frames. */
+    T3_32BIT_REGISTER TxMaxCoalescedFrames;
+
+    /* Receive coalescing ticks during interrupt. */
+    T3_32BIT_REGISTER RxCoalescedTickDuringInt;
+
+    /* Send coalescing ticks during interrupt. */
+    T3_32BIT_REGISTER TxCoalescedTickDuringInt;
+
+    /* Receive max coalesced frames during interrupt. */
+    T3_32BIT_REGISTER RxMaxCoalescedFramesDuringInt;
+
+    /* Send max coalesced frames during interrupt. */
+    T3_32BIT_REGISTER TxMaxCoalescedFramesDuringInt;
+
+    /* Statistics tick. */
+    T3_32BIT_REGISTER StatsCoalescingTicks;
+
+    /* Unused space. */
+    LM_UINT8 Unused2[4];
+
+    /* Statistics host address. */
+    T3_64BIT_REGISTER StatsBlkHostAddr;
+
+    /* Status block host address.*/
+    T3_64BIT_REGISTER StatusBlkHostAddr;
+
+    /* Statistics NIC address. */
+    T3_32BIT_REGISTER StatsBlkNicAddr;
+
+    /* Statust block NIC address. */
+    T3_32BIT_REGISTER StatusBlkNicAddr;
+
+    /* Flow attention registers. */
+    T3_32BIT_REGISTER FlowAttn;
+
+    /* Unused space. */
+    LM_UINT8 Unused3[4];
+
+    T3_32BIT_REGISTER NicJumboRcvBdConIdx;
+    T3_32BIT_REGISTER NicStdRcvBdConIdx;
+    T3_32BIT_REGISTER NicMiniRcvBdConIdx;
+
+    /* Unused space. */
+    LM_UINT8 Unused4[36];
+
+    T3_32BIT_REGISTER NicRetProdIdx[16];
+    T3_32BIT_REGISTER NicSndBdConIdx[16];
+
+    /* Unused space. */
+    LM_UINT8 Unused5[768];
+} T3_HOST_COALESCING, *PT3_HOST_COALESCING;
+
+
+
+/******************************************************************************/
+/* Memory arbiter registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+#define T3_MEM_ARBITER_MODE_RESET       BIT_0
+#define T3_MEM_ARBITER_MODE_ENABLE      BIT_1
+
+    T3_32BIT_REGISTER Status;
+
+    T3_32BIT_REGISTER ArbTrapAddrLow;
+    T3_32BIT_REGISTER ArbTrapAddrHigh;
+
+    /* Unused space. */
+    LM_UINT8 Unused[1008];
+} T3_MEM_ARBITER, *PT3_MEM_ARBITER;
+
+
+
+/******************************************************************************/
+/* Buffer manager control register. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define BUFMGR_MODE_RESET                           BIT_0
+    #define BUFMGR_MODE_ENABLE                          BIT_1
+    #define BUFMGR_MODE_ATTN_ENABLE                     BIT_2
+    #define BUFMGR_MODE_BM_TEST                         BIT_3
+    #define BUFMGR_MODE_MBUF_LOW_ATTN_ENABLE            BIT_4
+
+    T3_32BIT_REGISTER Status;
+    #define BUFMGR_STATUS_ERROR                         BIT_2
+    #define BUFMGR_STATUS_MBUF_LOW                      BIT_4
+
+    T3_32BIT_REGISTER MbufPoolAddr;
+    T3_32BIT_REGISTER MbufPoolSize;
+    T3_32BIT_REGISTER MbufReadDmaLowWaterMark;
+    T3_32BIT_REGISTER MbufMacRxLowWaterMark;
+    T3_32BIT_REGISTER MbufHighWaterMark;
+
+    T3_32BIT_REGISTER RxCpuMbufAllocReq;
+    #define BUFMGR_MBUF_ALLOC_BIT                     BIT_31
+    T3_32BIT_REGISTER RxCpuMbufAllocResp;
+    T3_32BIT_REGISTER TxCpuMbufAllocReq;
+    T3_32BIT_REGISTER TxCpuMbufAllocResp;
+
+    T3_32BIT_REGISTER DmaDescPoolAddr;
+    T3_32BIT_REGISTER DmaDescPoolSize;
+    T3_32BIT_REGISTER DmaLowWaterMark;
+    T3_32BIT_REGISTER DmaHighWaterMark;
+
+    T3_32BIT_REGISTER RxCpuDmaAllocReq;
+    T3_32BIT_REGISTER RxCpuDmaAllocResp;
+    T3_32BIT_REGISTER TxCpuDmaAllocReq;
+    T3_32BIT_REGISTER TxCpuDmaAllocResp;
+
+    T3_32BIT_REGISTER Hwdiag[3];
+
+    /* Unused space. */
+    LM_UINT8 Unused[936];
+} T3_BUFFER_MANAGER, *PT3_BUFFER_MANAGER;
+
+
+
+/******************************************************************************/
+/* Read DMA control registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define DMA_READ_MODE_RESET                         BIT_0
+    #define DMA_READ_MODE_ENABLE                        BIT_1
+    #define DMA_READ_MODE_TARGET_ABORT_ATTN_ENABLE      BIT_2
+    #define DMA_READ_MODE_MASTER_ABORT_ATTN_ENABLE      BIT_3
+    #define DMA_READ_MODE_PARITY_ERROR_ATTN_ENABLE      BIT_4
+    #define DMA_READ_MODE_ADDR_OVERFLOW_ATTN_ENABLE     BIT_5
+    #define DMA_READ_MODE_FIFO_OVERRUN_ATTN_ENABLE      BIT_6
+    #define DMA_READ_MODE_FIFO_UNDERRUN_ATTN_ENABLE     BIT_7
+    #define DMA_READ_MODE_FIFO_OVERREAD_ATTN_ENABLE     BIT_8
+    #define DMA_READ_MODE_LONG_READ_ATTN_ENABLE         BIT_9
+    #define DMA_READ_MODE_SPLIT_ENABLE                  BIT_11
+    #define DMA_READ_MODE_SPLIT_RESET                   BIT_12
+
+    T3_32BIT_REGISTER Status;
+    #define DMA_READ_STATUS_TARGET_ABORT_ATTN           BIT_2
+    #define DMA_READ_STATUS_MASTER_ABORT_ATTN           BIT_3
+    #define DMA_READ_STATUS_PARITY_ERROR_ATTN           BIT_4
+    #define DMA_READ_STATUS_ADDR_OVERFLOW_ATTN          BIT_5
+    #define DMA_READ_STATUS_FIFO_OVERRUN_ATTN           BIT_6
+    #define DMA_READ_STATUS_FIFO_UNDERRUN_ATTN          BIT_7
+    #define DMA_READ_STATUS_FIFO_OVERREAD_ATTN          BIT_8
+    #define DMA_READ_STATUS_LONG_READ_ATTN              BIT_9
+
+    /* Unused space. */
+    LM_UINT8 Unused[1016];
+} T3_DMA_READ, *PT3_DMA_READ;
+
+typedef union T3_CPU 
+{
+  struct
+  {
+    T3_32BIT_REGISTER mode;
+    #define CPU_MODE_HALT   BIT_10
+    #define CPU_MODE_RESET  BIT_0 
+    T3_32BIT_REGISTER state;
+    T3_32BIT_REGISTER EventMask;
+    T3_32BIT_REGISTER reserved1[4];
+    T3_32BIT_REGISTER PC;
+    T3_32BIT_REGISTER Instruction;
+    T3_32BIT_REGISTER SpadUnderflow;
+    T3_32BIT_REGISTER WatchdogClear;
+    T3_32BIT_REGISTER WatchdogVector;
+    T3_32BIT_REGISTER WatchdogSavedPC;
+    T3_32BIT_REGISTER HardwareBp;
+    T3_32BIT_REGISTER reserved2[3];
+    T3_32BIT_REGISTER WatchdogSavedState;    
+    T3_32BIT_REGISTER LastBrchAddr;    
+    T3_32BIT_REGISTER SpadUnderflowSet;    
+    T3_32BIT_REGISTER reserved3[(0x200-0x50)/4];
+    T3_32BIT_REGISTER Regs[32];
+    T3_32BIT_REGISTER reserved4[(0x400-0x280)/4];
+  }reg;
+}T3_CPU, *PT3_CPU;
+
+/******************************************************************************/
+/* Write DMA control registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define DMA_WRITE_MODE_RESET                        BIT_0
+    #define DMA_WRITE_MODE_ENABLE                       BIT_1
+    #define DMA_WRITE_MODE_TARGET_ABORT_ATTN_ENABLE     BIT_2
+    #define DMA_WRITE_MODE_MASTER_ABORT_ATTN_ENABLE     BIT_3
+    #define DMA_WRITE_MODE_PARITY_ERROR_ATTN_ENABLE     BIT_4
+    #define DMA_WRITE_MODE_ADDR_OVERFLOW_ATTN_ENABLE    BIT_5
+    #define DMA_WRITE_MODE_FIFO_OVERRUN_ATTN_ENABLE     BIT_6
+    #define DMA_WRITE_MODE_FIFO_UNDERRUN_ATTN_ENABLE    BIT_7
+    #define DMA_WRITE_MODE_FIFO_OVERREAD_ATTN_ENABLE    BIT_8
+    #define DMA_WRITE_MODE_LONG_READ_ATTN_ENABLE        BIT_9
+
+    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_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
+
+    /* Miscellaneous local control register. */
+    T3_32BIT_REGISTER LocalCtrl;
+    #define GRC_MISC_LOCAL_CTRL_INT_ACTIVE              BIT_0
+    #define GRC_MISC_LOCAL_CTRL_CLEAR_INT               BIT_1
+    #define GRC_MISC_LOCAL_CTRL_SET_INT                 BIT_2
+    #define GRC_MISC_LOCAL_CTRL_INT_ON_ATTN             BIT_3
+    #define GRC_MISC_LOCAL_CTRL_GPIO_INPUT0             BIT_8
+    #define GRC_MISC_LOCAL_CTRL_GPIO_INPUT1             BIT_9
+    #define GRC_MISC_LOCAL_CTRL_GPIO_INPUT2             BIT_10
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OE0                BIT_11
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OE1                BIT_12
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OE2                BIT_13
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0            BIT_14
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1            BIT_15
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2            BIT_16
+    #define GRC_MISC_LOCAL_CTRL_ENABLE_EXT_MEMORY       BIT_17
+    #define GRC_MISC_LOCAL_CTRL_BANK_SELECT             BIT_21
+    #define GRC_MISC_LOCAL_CTRL_SSRAM_TYPE              BIT_22
+
+    #define GRC_MISC_MEMSIZE_256K     0
+    #define GRC_MISC_MEMSIZE_512K     (1 << 18)
+    #define GRC_MISC_MEMSIZE_1024K    (2 << 18)
+    #define GRC_MISC_MEMSIZE_2048K    (3 << 18)
+    #define GRC_MISC_MEMSIZE_4096K    (4 << 18)
+    #define GRC_MISC_MEMSIZE_8192K    (5 << 18)
+    #define GRC_MISC_MEMSIZE_16M      (6 << 18)
+    #define GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM            BIT_24
+
+
+    T3_32BIT_REGISTER Timer;
+
+    T3_32BIT_REGISTER RxCpuEvent;
+    T3_32BIT_REGISTER RxTimerRef;
+    T3_32BIT_REGISTER RxCpuSemaphore;
+    T3_32BIT_REGISTER RemoteRxCpuAttn;
+
+    T3_32BIT_REGISTER TxCpuEvent;
+    T3_32BIT_REGISTER TxTimerRef;
+    T3_32BIT_REGISTER TxCpuSemaphore;
+    T3_32BIT_REGISTER RemoteTxCpuAttn;
+
+    T3_64BIT_REGISTER MemoryPowerUp;
+
+    T3_32BIT_REGISTER EepromAddr;
+    #define SEEPROM_ADDR_WRITE       0
+    #define SEEPROM_ADDR_READ        (1 << 31)
+    #define SEEPROM_ADDR_RW_MASK     0x80000000
+    #define SEEPROM_ADDR_COMPLETE    (1 << 30)
+    #define SEEPROM_ADDR_FSM_RESET   (1 << 29)
+    #define SEEPROM_ADDR_DEV_ID(x)   (x << 26)
+    #define SEEPROM_ADDR_DEV_ID_MASK 0x1c000000
+    #define SEEPROM_ADDR_START       (1 << 25)
+    #define SEEPROM_ADDR_CLK_PERD(x) (x << 16)
+    #define SEEPROM_ADDR_ADDRESS(x)  (x & 0xfffc)
+    #define SEEPROM_ADDR_ADDRESS_MASK 0x0000ffff
+
+    #define SEEPROM_CLOCK_PERIOD        60
+    #define SEEPROM_CHIP_SIZE           (64 * 1024)
+
+    T3_32BIT_REGISTER EepromData;
+    T3_32BIT_REGISTER EepromCtrl;
+
+    T3_32BIT_REGISTER MdiCtrl;
+    T3_32BIT_REGISTER SepromDelay;
+
+    /* Unused space. */
+    LM_UINT8 Unused[948];
+} T3_GRC, *PT3_GRC;
+
+
+/******************************************************************************/
+/* NVRAM control registers. */
+/******************************************************************************/
+
+typedef struct
+{
+    T3_32BIT_REGISTER Cmd;
+    #define NVRAM_CMD_RESET                             BIT_0
+    #define NVRAM_CMD_DONE                              BIT_3
+    #define NVRAM_CMD_DO_IT                             BIT_4
+    #define NVRAM_CMD_WR                                BIT_5
+    #define NVRAM_CMD_RD                                BIT_NONE
+    #define NVRAM_CMD_ERASE                             BIT_6
+    #define NVRAM_CMD_FIRST                             BIT_7
+    #define NVRAM_CMD_LAST                              BIT_8
+
+    T3_32BIT_REGISTER Status;
+    T3_32BIT_REGISTER WriteData;
+
+    T3_32BIT_REGISTER Addr;
+    #define NVRAM_ADDRESS_MASK                          0xffffff
+
+    T3_32BIT_REGISTER ReadData;
+
+    /* Flash config 1 register. */
+    T3_32BIT_REGISTER Config1;
+    #define FLASH_INTERFACE_ENABLE                      BIT_0
+    #define FLASH_SSRAM_BUFFERRED_MODE                  BIT_1
+    #define FLASH_PASS_THRU_MODE                        BIT_2
+    #define FLASH_BIT_BANG_MODE                         BIT_3
+    #define FLASH_COMPAT_BYPASS                         BIT_31
+
+    /* Buffered flash (Atmel: AT45DB011B) specific information */
+    #define BUFFERED_FLASH_PAGE_POS         9
+    #define BUFFERED_FLASH_BYTE_ADDR_MASK   ((1<<BUFFERED_FLASH_PAGE_POS) - 1)
+    #define BUFFERED_FLASH_PAGE_SIZE        264
+    #define BUFFERED_FLASH_PHY_PAGE_SIZE    512
+
+    T3_32BIT_REGISTER Config2;
+    T3_32BIT_REGISTER Config3;
+    T3_32BIT_REGISTER SwArb;
+    #define SW_ARB_REQ_SET0                             BIT_0
+    #define SW_ARB_REQ_SET1                             BIT_1
+    #define SW_ARB_REQ_SET2                             BIT_2
+    #define SW_ARB_REQ_SET3                             BIT_3
+    #define SW_ARB_REQ_CLR0                             BIT_4
+    #define SW_ARB_REQ_CLR1                             BIT_5
+    #define SW_ARB_REQ_CLR2                             BIT_6
+    #define SW_ARB_REQ_CLR3                             BIT_7
+    #define SW_ARB_GNT0                                 BIT_8
+    #define SW_ARB_GNT1                                 BIT_9
+    #define SW_ARB_GNT2                                 BIT_10
+    #define SW_ARB_GNT3                                 BIT_11
+    #define SW_ARB_REQ0                                 BIT_12
+    #define SW_ARB_REQ1                                 BIT_13
+    #define SW_ARB_REQ2                                 BIT_14
+    #define SW_ARB_REQ3                                 BIT_15
+
+    /* Unused space. */
+    LM_UINT8 Unused[988];
+} T3_NVRAM, *PT3_NVRAM;
+
+
+/******************************************************************************/
+/* NIC's internal memory. */
+/******************************************************************************/
+
+typedef struct {
+    /* Page zero for the internal CPUs. */
+    LM_UINT8 PageZero[0x100];               /* 0x0000 */
+
+    /* Send RCBs. */
+    T3_RCB SendRcb[16];                     /* 0x0100 */
+
+    /* Receive Return RCBs. */
+    T3_RCB RcvRetRcb[16];                   /* 0x0200 */
+
+    /* Statistics block. */
+    T3_STATS_BLOCK StatsBlk;                /* 0x0300 */
+
+    /* Status block. */
+    T3_STATUS_BLOCK StatusBlk;              /* 0x0b00 */
+
+    /* Reserved for software. */
+    LM_UINT8 Reserved[1200];                /* 0x0b50 */
+
+    /* Unmapped region. */
+    LM_UINT8 Unmapped[4096];                /* 0x1000 */
+
+    /* DMA descriptors. */
+    LM_UINT8 DmaDesc[8192];                 /* 0x2000 */
+
+    /* Buffer descriptors. */
+    LM_UINT8 BufferDesc[16384];             /* 0x4000 */
+} T3_FIRST_32K_SRAM, *PT3_FIRST_32K_SRAM;
+
+
+
+/******************************************************************************/
+/* Memory layout. */
+/******************************************************************************/
+
+typedef struct {
+    /* PCI configuration registers. */
+    T3_PCI_CONFIGURATION PciCfg;
+
+    /* Unused. */
+    LM_UINT8 Unused1[0x100];                            /* 0x0100 */
+
+    /* Mailbox . */
+    T3_MAILBOX Mailbox;                                 /* 0x0200 */
+
+    /* MAC control registers. */
+    T3_MAC_CONTROL MacCtrl;                             /* 0x0400 */
+
+    /* Send data initiator control registers. */
+    T3_SEND_DATA_INITIATOR SndDataIn;                   /* 0x0c00 */
+
+    /* Send data completion Control registers. */
+    T3_SEND_DATA_COMPLETION SndDataComp;                /* 0x1000 */
+
+    /* Send BD ring selector. */
+    T3_SEND_BD_SELECTOR SndBdSel;                       /* 0x1400 */
+
+    /* Send BD initiator control registers. */
+    T3_SEND_BD_INITIATOR SndBdIn;                       /* 0x1800 */
+
+    /* Send BD completion control registers. */
+    T3_SEND_BD_COMPLETION SndBdComp;                    /* 0x1c00 */
+
+    /* Receive list placement control registers. */
+    T3_RCV_LIST_PLACEMENT RcvListPlmt;                  /* 0x2000 */
+
+    /* Receive Data and Receive BD Initiator Control. */
+    T3_RCV_DATA_BD_INITIATOR RcvDataBdIn;               /* 0x2400 */
+
+    /* Receive Data Completion Control */
+    T3_RCV_DATA_COMPLETION RcvDataComp;                 /* 0x2800 */
+
+    /* Receive BD Initiator Control Registers. */
+    T3_RCV_BD_INITIATOR RcvBdIn;                        /* 0x2c00 */
+
+    /* Receive BD Completion Control Registers. */
+    T3_RCV_BD_COMPLETION RcvBdComp;                     /* 0x3000 */
+
+    /* Receive list selector control registers. */
+    T3_RCV_LIST_SELECTOR RcvListSel;                    /* 0x3400 */
+
+    /* Mbuf cluster free registers. */
+    T3_MBUF_CLUSTER_FREE MbufClusterFree;               /* 0x3800 */
+
+    /* Host coalescing control registers. */
+    T3_HOST_COALESCING HostCoalesce;                    /* 0x3c00 */
+
+    /* Memory arbiter control registers. */
+    T3_MEM_ARBITER MemArbiter;                          /* 0x4000 */
+    
+    /* Buffer manger control registers. */
+    T3_BUFFER_MANAGER BufMgr;                           /* 0x4400 */
+
+    /* Read DMA control registers. */
+    T3_DMA_READ DmaRead;                                /* 0x4800 */
+
+    /* Write DMA control registers. */
+    T3_DMA_WRITE DmaWrite;                              /* 0x4c00 */
+
+    T3_CPU rxCpu;                                       /* 0x5000 */
+    T3_CPU txCpu;                                       /* 0x5400 */
+
+    /* Mailboxes. */
+    T3_GRC_MAILBOX GrcMailbox;                          /* 0x5800 */
+
+    /* Flow Through queues. */
+    T3_FTQ Ftq;                                         /* 0x5c00 */
+
+    /* Message signaled interrupt registes. */
+    T3_MSG_SIGNALED_INT Msi;                            /* 0x6000 */
+
+    /* DMA completion registers. */
+    T3_DMA_COMPLETION DmaComp;                          /* 0x6400 */
+
+    /* GRC registers. */
+    T3_GRC Grc;                                         /* 0x6800 */
+
+    /* Unused space. */
+    LM_UINT8 Unused2[1024];                             /* 0x6c00 */
+
+    /* NVRAM registers. */
+    T3_NVRAM Nvram;                                     /* 0x7000 */
+
+    /* Unused space. */
+    LM_UINT8 Unused3[3072];                             /* 0x7400 */
+    
+    /* The 32k memory window into the NIC's */
+    /* internal memory.  The memory window is */
+    /* controlled by the Memory Window Base */
+    /* Address register.  This register is located */
+    /* in the PCI configuration space. */
+    union {                                             /* 0x8000 */
+        T3_FIRST_32K_SRAM First32k;
+
+        /* Use the memory window base address register to determine the */
+        /* MBUF segment. */
+        LM_UINT32 Mbuf[32768/4];
+        LM_UINT32 MemBlock32K[32768/4];
+    } uIntMem;
+} T3_STD_MEM_MAP, *PT3_STD_MEM_MAP;
+
+
+/******************************************************************************/
+/* Adapter info. */
+/******************************************************************************/
+
+typedef struct
+{
+    LM_UINT16 Svid;
+    LM_UINT16 Ssid;
+    LM_UINT32 PhyId;
+    LM_UINT32 Serdes;   /* 0 = copper PHY, 1 = Serdes */
+} LM_ADAPTER_INFO, *PLM_ADAPTER_INFO;
+
+
+/******************************************************************************/
+/* Packet queues. */
+/******************************************************************************/
+
+DECLARE_QUEUE_TYPE(LM_RX_PACKET_Q, MAX_RX_PACKET_DESC_COUNT);
+DECLARE_QUEUE_TYPE(LM_TX_PACKET_Q, MAX_TX_PACKET_DESC_COUNT);
+
+
+
+/******************************************************************************/
+/* Tx counters. */
+/******************************************************************************/
+
+typedef struct {
+    LM_COUNTER TxPacketGoodCnt;
+    LM_COUNTER TxBytesGoodCnt;
+    LM_COUNTER TxPacketAbortedCnt;
+    LM_COUNTER NoSendBdLeftCnt;
+    LM_COUNTER NoMapRegisterLeftCnt;
+    LM_COUNTER TooManyFragmentsCnt;
+    LM_COUNTER NoTxPacketDescCnt;
+} LM_TX_COUNTERS, *PLM_TX_COUNTERS;
+
+
+
+/******************************************************************************/
+/* Rx counters. */
+/******************************************************************************/
+
+typedef struct {
+    LM_COUNTER RxPacketGoodCnt;
+    LM_COUNTER RxBytesGoodCnt;
+    LM_COUNTER RxPacketErrCnt;
+    LM_COUNTER RxErrCrcCnt;
+    LM_COUNTER RxErrCollCnt;
+    LM_COUNTER RxErrLinkLostCnt;
+    LM_COUNTER RxErrPhyDecodeCnt;
+    LM_COUNTER RxErrOddNibbleCnt;
+    LM_COUNTER RxErrMacAbortCnt;
+    LM_COUNTER RxErrShortPacketCnt;
+    LM_COUNTER RxErrNoResourceCnt;
+    LM_COUNTER RxErrLargePacketCnt;
+} LM_RX_COUNTERS, *PLM_RX_COUNTERS;
+
+
+
+/******************************************************************************/
+/* Receive producer rings. */
+/******************************************************************************/
+
+typedef enum {
+    T3_UNKNOWN_RCV_PROD_RING    = 0,
+    T3_STD_RCV_PROD_RING        = 1,
+    T3_MINI_RCV_PROD_RING       = 2,
+    T3_JUMBO_RCV_PROD_RING      = 3
+} T3_RCV_PROD_RING, *PT3_RCV_PROD_RING;
+
+
+
+/******************************************************************************/
+/* Packet descriptor. */
+/******************************************************************************/
+
+#define LM_PACKET_SIGNATURE_TX              0x6861766b
+#define LM_PACKET_SIGNATURE_RX              0x6b766168
+
+typedef struct _LM_PACKET {
+    /* Set in LM. */
+    LM_STATUS PacketStatus;
+
+    /* Set in LM for Rx, in UM for Tx. */
+    LM_UINT32 PacketSize;
+
+    LM_UINT16 Flags;
+
+    LM_UINT16 VlanTag;
+
+    union {
+        /* Send info. */
+        struct {
+            /* Set up by UM. */
+            LM_UINT32 FragCount;
+
+        } Tx;
+
+        /* Receive info. */
+        struct {
+            /* This descriptor belongs to either Std, Mini, or Jumbo ring. */
+            T3_RCV_PROD_RING RcvProdRing;
+
+            /* Receive buffer size */
+            LM_UINT32 RxBufferSize;
+
+            /* Checksum information. */
+            LM_UINT16 IpChecksum;
+            LM_UINT16 TcpUdpChecksum;
+
+        } Rx;
+    } u;
+} LM_PACKET;
+
+
+
+/******************************************************************************/
+/* Tigon3 device block. */
+/******************************************************************************/
+
+typedef struct _LM_DEVICE_BLOCK {
+    int index; /* Device ID */
+    /* 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;
+
+    /* Rx info */
+    LM_UINT32 RxStdDescCnt;
+    LM_UINT32 RxStdQueuedCnt;
+    LM_UINT32 RxStdProdIdx;
+
+    PT3_RCV_BD pRxStdBdVirt;
+    LM_PHYSICAL_ADDRESS RxStdBdPhy;
+
+    LM_UINT32 RxPacketDescCnt;
+    LM_RX_PACKET_Q RxPacketFreeQ;
+    LM_RX_PACKET_Q RxPacketReceivedQ;
+
+    /* Receive info. */
+    PT3_RCV_BD pRcvRetBdVirt;
+    LM_PHYSICAL_ADDRESS RcvRetBdPhy;
+    LM_UINT32 RcvRetConIdx;
+
+#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. */
+
+    /* We need to shadow the EMAC, Rx, Tx mode registers.  With B0 silicon, */
+    /* we may have problems reading any MAC registers in 10mb mode. */
+    LM_UINT32 MacMode;
+    LM_UINT32 RxMode;
+    LM_UINT32 TxMode;
+
+    /* MiMode register. */
+    LM_UINT32 MiMode;
+
+    /* Host coalesce mode register. */
+    LM_UINT32 CoalesceMode;
+
+    /* Send info. */
+    LM_UINT32 TxPacketDescCnt;
+
+    /* Tx info. */
+    LM_TX_PACKET_Q TxPacketFreeQ;
+    LM_TX_PACKET_Q TxPacketActiveQ;
+    LM_TX_PACKET_Q TxPacketXmittedQ;
+
+    /* Pointers to SendBd. */
+    PT3_SND_BD pSendBdVirt;
+    LM_PHYSICAL_ADDRESS SendBdPhy;  /* Only valid for Host based Send BD. */
+
+    /* Send producer and consumer indices. */
+    LM_UINT32 SendProdIdx;
+    LM_UINT32 SendConIdx;
+
+    /* Number of BD left. */
+    atomic_t SendBdLeft;
+
+    T3_SND_BD ShadowSendBd[T3_SEND_RCB_ENTRY_COUNT];
+
+    /* Counters. */
+    LM_RX_COUNTERS RxCounters;
+    LM_TX_COUNTERS TxCounters;
+
+    /* Host coalescing parameters. */
+    LM_UINT32 RxCoalescingTicks;
+    LM_UINT32 TxCoalescingTicks;
+    LM_UINT32 RxMaxCoalescedFrames;
+    LM_UINT32 TxMaxCoalescedFrames;
+    LM_UINT32 StatsCoalescingTicks;
+    LM_UINT32 RxCoalescingTicksDuringInt;
+    LM_UINT32 TxCoalescingTicksDuringInt;
+    LM_UINT32 RxMaxCoalescedFramesDuringInt;
+    LM_UINT32 TxMaxCoalescedFramesDuringInt;
+
+    /* DMA water marks. */
+    LM_UINT32 DmaMbufLowMark;
+    LM_UINT32 RxMacMbufLowMark;
+    LM_UINT32 MbufHighMark;
+
+    /* Status block. */
+    PT3_STATUS_BLOCK pStatusBlkVirt;
+    LM_PHYSICAL_ADDRESS StatusBlkPhy;
+
+    /* Statistics block. */
+    PT3_STATS_BLOCK pStatsBlkVirt;
+    LM_PHYSICAL_ADDRESS StatsBlkPhy;
+
+    /* Current receive mask. */
+    LM_UINT32 ReceiveMask;
+
+    /* Task offload capabilities. */
+    LM_TASK_OFFLOAD TaskOffloadCap;
+
+    /* Task offload selected. */
+    LM_TASK_OFFLOAD TaskToOffload;
+
+    /* Wake up capability. */
+    LM_WAKE_UP_MODE WakeUpModeCap;
+
+    /* Wake up capability. */
+    LM_WAKE_UP_MODE WakeUpMode;
+
+    /* Flow control. */
+    LM_FLOW_CONTROL FlowControlCap;
+    LM_FLOW_CONTROL FlowControl;
+
+    /* Enable or disable PCI MWI. */
+    LM_UINT32 EnableMWI;
+
+    /* Enable 5701 tagged status mode. */
+    LM_UINT32 UseTaggedStatus;
+
+    /* NIC will not compute the pseudo header checksum.  The driver or OS */
+    /* must seed the checksum field with the pseudo checksum. */
+    LM_UINT32 NoTxPseudoHdrChksum;
+
+    /* The receive checksum in the BD does not include the pseudo checksum. */
+    /* The OS or the driver must calculate the pseudo checksum and add it to */
+    /* the checksum in the BD. */
+    LM_UINT32 NoRxPseudoHdrChksum;
+
+    /* Current node address. */
+    LM_UINT8 NodeAddress[8];
+
+    /* The adapter's node address. */
+    LM_UINT8 PermanentNodeAddress[8];
+
+    /* Adapter info. */
+    LM_UINT16 BusNum;               
+    LM_UINT8 DevNum;                
+    LM_UINT8 FunctNum;              
+    LM_UINT16 PciVendorId;
+    LM_UINT16 PciDeviceId;
+    LM_UINT32 BondId;
+    LM_UINT8 Irq;
+    LM_UINT8 IntPin;
+    LM_UINT8 CacheLineSize;
+    LM_UINT8 PciRevId;
+#if PCIX_TARGET_WORKAROUND
+       LM_UINT32 EnablePciXFix;
+#endif
+    LM_UINT32 UndiFix;   /* new, jimmy */
+    LM_UINT32 PciCommandStatusWords;
+    LM_UINT32 ChipRevId;
+    LM_UINT16 SubsystemVendorId;
+    LM_UINT16 SubsystemId;
+#if 0  /* Jimmy, deleted in new driver */
+    LM_UINT32 MemBaseLow;
+    LM_UINT32 MemBaseHigh;
+    LM_UINT32 MemBaseSize;
+#endif
+    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_REQUESTED_MEDIA_TYPE RequestedMediaType;
+
+    /* Disable auto-negotiation. */
+    LM_UINT32 DisableAutoNeg;
+
+    /* Ways for the MAC to get link change interrupt. */
+    LM_UINT32 PhyIntMode;
+    #define T3_PHY_INT_MODE_AUTO                        0
+    #define T3_PHY_INT_MODE_MI_INTERRUPT                1
+    #define T3_PHY_INT_MODE_LINK_READY                  2
+    #define T3_PHY_INT_MODE_AUTO_POLLING                3
+
+    /* Ways to determine link change status. */
+    LM_UINT32 LinkChngMode;
+    #define T3_LINK_CHNG_MODE_AUTO                      0
+    #define T3_LINK_CHNG_MODE_USE_STATUS_REG            1
+    #define T3_LINK_CHNG_MODE_USE_STATUS_BLOCK          2
+
+
+    /* LED mode. */
+    LM_UINT32 LedMode;
+
+    #define LED_MODE_AUTO                               0
+
+    /* 5700/01 LED mode. */
+    #define LED_MODE_THREE_LINK                         1
+    #define LED_MODE_LINK10                             2
+
+    /* 5703/02/04 LED mode. */
+    #define LED_MODE_OPEN_DRAIN                         1
+    #define LED_MODE_OUTPUT                             2
+    
+    /* WOL Speed */
+    LM_UINT32 WolSpeed;
+    #define WOL_SPEED_10MB                              1
+    #define WOL_SPEED_100MB                             2
+
+    /* Reset the PHY on initialization. */
+    LM_UINT32 ResetPhyOnInit;
+
+    LM_UINT32 RestoreOnWakeUp;
+    LM_REQUESTED_MEDIA_TYPE WakeUpRequestedMediaType;
+    LM_UINT32 WakeUpDisableAutoNeg;
+
+    /* Current phy settings. */
+    LM_MEDIA_TYPE MediaType;
+    LM_LINE_SPEED LineSpeed;
+    LM_LINE_SPEED OldLineSpeed;
+    LM_DUPLEX_MODE DuplexMode;
+    LM_STATUS LinkStatus;
+    LM_UINT32 advertising;     /* Jimmy, new! */
+    LM_UINT32 advertising1000; /* Jimmy, new! */
+
+    /* Multicast address list. */
+    LM_UINT32 McEntryCount;
+    LM_UINT8 McTable[LM_MAX_MC_TABLE_SIZE][LM_MC_ENTRY_SIZE];
+
+    /* Use NIC or Host based send BD. */
+    LM_UINT32 NicSendBd;
+
+    /* Athlon fix. */
+    LM_UINT32 DelayPciGrant;
+
+    /* Enable OneDmaAtOnce */
+    LM_UINT32 OneDmaAtOnce;
+
+    /* Split Mode flags, Jimmy new */
+    LM_UINT32 SplitModeEnable;
+    LM_UINT32 SplitModeMaxReq;
+
+    /* Init flag. */
+    LM_BOOL InitDone;
+
+    /* Shutdown flag.  Set by the upper module. */
+    LM_BOOL ShuttingDown;
+
+    /* Flag to determine whether to call LM_QueueRxPackets or not in */
+    /* LM_ResetAdapter routine. */
+    LM_BOOL QueueRxPackets;
+
+    LM_UINT32 MbufBase;
+    LM_UINT32 MbufSize;
+
+    /* TRUE if we have a SERDES PHY. */
+    LM_UINT32 EnableTbi;
+
+    /* Ethernet@WireSpeed. */
+    LM_UINT32 EnableWireSpeed;
+
+    LM_UINT32 EepromWp;
+
+#if INCLUDE_TBI_SUPPORT
+    /* Autoneg state info. */
+    AN_STATE_INFO AnInfo;
+    LM_UINT32 PollTbiLink;
+    LM_UINT32 IgnoreTbiLinkChange;
+#endif
+    char PartNo[24];
+    char BootCodeVer[16];
+    char BusSpeedStr[24]; /* Jimmy, new! */
+    LM_UINT32 PhyCrcCount;
+} LM_DEVICE_BLOCK;
+
+
+#define T3_REG_CPU_VIEW               0xc0000000
+
+#define T3_BLOCK_DMA_RD               (1 << 0)
+#define T3_BLOCK_DMA_COMP             (1 << 1)
+#define T3_BLOCK_RX_BD_INITIATOR      (1 << 2)
+#define T3_BLOCK_RX_BD_COMP           (1 << 3)
+#define T3_BLOCK_DMA_WR               (1 << 4)
+#define T3_BLOCK_MSI_HANDLER          (1 << 5)
+#define T3_BLOCK_RX_LIST_PLMT         (1 << 6)
+#define T3_BLOCK_RX_LIST_SELECTOR     (1 << 7)
+#define T3_BLOCK_RX_DATA_INITIATOR    (1 << 8)
+#define T3_BLOCK_RX_DATA_COMP         (1 << 9)
+#define T3_BLOCK_HOST_COALESING       (1 << 10)
+#define T3_BLOCK_MAC_RX_ENGINE        (1 << 11)
+#define T3_BLOCK_MBUF_CLUSTER_FREE    (1 << 12)
+#define T3_BLOCK_SEND_BD_INITIATOR    (1 << 13)
+#define T3_BLOCK_SEND_BD_COMP         (1 << 14)
+#define T3_BLOCK_SEND_BD_SELECTOR     (1 << 15)
+#define T3_BLOCK_SEND_DATA_INITIATOR  (1 << 16)
+#define T3_BLOCK_SEND_DATA_COMP       (1 << 17)
+#define T3_BLOCK_MAC_TX_ENGINE        (1 << 18)
+#define T3_BLOCK_MEM_ARBITOR          (1 << 19)
+#define T3_BLOCK_MBUF_MANAGER         (1 << 20)
+#define T3_BLOCK_MAC_GLOBAL           (1 << 21)
+
+#define LM_ENABLE               1
+#define LM_DISABLE              2
+
+#define RX_CPU_EVT_SW0              0
+#define RX_CPU_EVT_SW1              1
+#define RX_CPU_EVT_RLP              2
+#define RX_CPU_EVT_SW3              3
+#define RX_CPU_EVT_RLS              4
+#define RX_CPU_EVT_SW4              5
+#define RX_CPU_EVT_RX_BD_COMP       6
+#define RX_CPU_EVT_SW5              7
+#define RX_CPU_EVT_RDI              8
+#define RX_CPU_EVT_DMA_WR           9
+#define RX_CPU_EVT_DMA_RD           10
+#define RX_CPU_EVT_SWQ              11
+#define RX_CPU_EVT_SW6              12
+#define RX_CPU_EVT_RDC              13
+#define RX_CPU_EVT_SW7              14
+#define RX_CPU_EVT_HOST_COALES      15
+#define RX_CPU_EVT_SW8              16
+#define RX_CPU_EVT_HIGH_DMA_WR      17
+#define RX_CPU_EVT_HIGH_DMA_RD      18
+#define RX_CPU_EVT_SW9              19
+#define RX_CPU_EVT_DMA_ATTN         20
+#define RX_CPU_EVT_LOW_P_MBOX       21
+#define RX_CPU_EVT_HIGH_P_MBOX      22
+#define RX_CPU_EVT_SW10             23
+#define RX_CPU_EVT_TX_CPU_ATTN      24
+#define RX_CPU_EVT_MAC_ATTN         25
+#define RX_CPU_EVT_RX_CPU_ATTN      26
+#define RX_CPU_EVT_FLOW_ATTN        27
+#define RX_CPU_EVT_SW11             28
+#define RX_CPU_EVT_TIMER            29
+#define RX_CPU_EVT_SW12             30
+#define RX_CPU_EVT_SW13             31
+
+/* RX-CPU event */
+#define RX_CPU_EVENT_SW_EVENT0      (1 << RX_CPU_EVT_SW0)
+#define RX_CPU_EVENT_SW_EVENT1      (1 << RX_CPU_EVT_SW1)
+#define RX_CPU_EVENT_RLP            (1 << RX_CPU_EVT_RLP)
+#define RX_CPU_EVENT_SW_EVENT3      (1 << RX_CPU_EVT_SW3)
+#define RX_CPU_EVENT_RLS            (1 << RX_CPU_EVT_RLS)
+#define RX_CPU_EVENT_SW_EVENT4      (1 << RX_CPU_EVT_SW4)
+#define RX_CPU_EVENT_RX_BD_COMP     (1 << RX_CPU_EVT_RX_BD_COMP)
+#define RX_CPU_EVENT_SW_EVENT5      (1 << RX_CPU_EVT_SW5)
+#define RX_CPU_EVENT_RDI            (1 << RX_CPU_EVT_RDI)
+#define RX_CPU_EVENT_DMA_WR         (1 << RX_CPU_EVT_DMA_WR)
+#define RX_CPU_EVENT_DMA_RD         (1 << RX_CPU_EVT_DMA_RD)
+#define RX_CPU_EVENT_SWQ            (1 << RX_CPU_EVT_SWQ)
+#define RX_CPU_EVENT_SW_EVENT6      (1 << RX_CPU_EVT_SW6)
+#define RX_CPU_EVENT_RDC            (1 << RX_CPU_EVT_RDC)
+#define RX_CPU_EVENT_SW_EVENT7      (1 << RX_CPU_EVT_SW7)
+#define RX_CPU_EVENT_HOST_COALES    (1 << RX_CPU_EVT_HOST_COALES)
+#define RX_CPU_EVENT_SW_EVENT8      (1 << RX_CPU_EVT_SW8)
+#define RX_CPU_EVENT_HIGH_DMA_WR    (1 << RX_CPU_EVT_HIGH_DMA_WR)
+#define RX_CPU_EVENT_HIGH_DMA_RD    (1 << RX_CPU_EVT_HIGH_DMA_RD)
+#define RX_CPU_EVENT_SW_EVENT9      (1 << RX_CPU_EVT_SW9)
+#define RX_CPU_EVENT_DMA_ATTN       (1 << RX_CPU_EVT_DMA_ATTN)
+#define RX_CPU_EVENT_LOW_P_MBOX     (1 << RX_CPU_EVT_LOW_P_MBOX)
+#define RX_CPU_EVENT_HIGH_P_MBOX    (1 << RX_CPU_EVT_HIGH_P_MBOX)
+#define RX_CPU_EVENT_SW_EVENT10     (1 << RX_CPU_EVT_SW10)
+#define RX_CPU_EVENT_TX_CPU_ATTN    (1 << RX_CPU_EVT_TX_CPU_ATTN)
+#define RX_CPU_EVENT_MAC_ATTN       (1 << RX_CPU_EVT_MAC_ATTN)
+#define RX_CPU_EVENT_RX_CPU_ATTN    (1 << RX_CPU_EVT_RX_CPU_ATTN)
+#define RX_CPU_EVENT_FLOW_ATTN      (1 << RX_CPU_EVT_FLOW_ATTN)
+#define RX_CPU_EVENT_SW_EVENT11     (1 << RX_CPU_EVT_SW11)
+#define RX_CPU_EVENT_TIMER          (1 << RX_CPU_EVT_TIMER)
+#define RX_CPU_EVENT_SW_EVENT12     (1 << RX_CPU_EVT_SW12)
+#define RX_CPU_EVENT_SW_EVENT13     (1 << RX_CPU_EVT_SW13)
+
+#define RX_CPU_MASK (RX_CPU_EVENT_SW_EVENT0 | \
+                    RX_CPU_EVENT_RLP | \
+                    RX_CPU_EVENT_RDI | \
+                    RX_CPU_EVENT_RDC)
+
+#define TX_CPU_EVT_SW0              0
+#define TX_CPU_EVT_SW1              1
+#define TX_CPU_EVT_SW2              2
+#define TX_CPU_EVT_SW3              3
+#define TX_CPU_EVT_TX_MAC           4
+#define TX_CPU_EVT_SW4              5
+#define TX_CPU_EVT_SBDC             6
+#define TX_CPU_EVT_SW5              7
+#define TX_CPU_EVT_SDI              8
+#define TX_CPU_EVT_DMA_WR           9
+#define TX_CPU_EVT_DMA_RD           10
+#define TX_CPU_EVT_SWQ              11
+#define TX_CPU_EVT_SW6              12
+#define TX_CPU_EVT_SDC              13
+#define TX_CPU_EVT_SW7              14
+#define TX_CPU_EVT_HOST_COALES      15
+#define TX_CPU_EVT_SW8              16
+#define TX_CPU_EVT_HIGH_DMA_WR      17
+#define TX_CPU_EVT_HIGH_DMA_RD      18
+#define TX_CPU_EVT_SW9              19
+#define TX_CPU_EVT_DMA_ATTN         20
+#define TX_CPU_EVT_LOW_P_MBOX       21
+#define TX_CPU_EVT_HIGH_P_MBOX      22
+#define TX_CPU_EVT_SW10             23
+#define TX_CPU_EVT_RX_CPU_ATTN      24
+#define TX_CPU_EVT_MAC_ATTN         25
+#define TX_CPU_EVT_TX_CPU_ATTN      26
+#define TX_CPU_EVT_FLOW_ATTN        27
+#define TX_CPU_EVT_SW11             28
+#define TX_CPU_EVT_TIMER            29
+#define TX_CPU_EVT_SW12             30
+#define TX_CPU_EVT_SW13             31
+
+
+/* TX-CPU event */
+#define TX_CPU_EVENT_SW_EVENT0      (1 << TX_CPU_EVT_SW0)
+#define TX_CPU_EVENT_SW_EVENT1      (1 << TX_CPU_EVT_SW1)
+#define TX_CPU_EVENT_SW_EVENT2      (1 << TX_CPU_EVT_SW2)
+#define TX_CPU_EVENT_SW_EVENT3      (1 << TX_CPU_EVT_SW3)
+#define TX_CPU_EVENT_TX_MAC         (1 << TX_CPU_EVT_TX_MAC)
+#define TX_CPU_EVENT_SW_EVENT4      (1 << TX_CPU_EVT_SW4)
+#define TX_CPU_EVENT_SBDC           (1 << TX_CPU_EVT_SBDC)
+#define TX_CPU_EVENT_SW_EVENT5      (1 << TX_CPU_EVT_SW5)
+#define TX_CPU_EVENT_SDI            (1 << TX_CPU_EVT_SDI)
+#define TX_CPU_EVENT_DMA_WR         (1 << TX_CPU_EVT_DMA_WR)
+#define TX_CPU_EVENT_DMA_RD         (1 << TX_CPU_EVT_DMA_RD)
+#define TX_CPU_EVENT_SWQ            (1 << TX_CPU_EVT_SWQ)
+#define TX_CPU_EVENT_SW_EVENT6      (1 << TX_CPU_EVT_SW6)
+#define TX_CPU_EVENT_SDC            (1 << TX_CPU_EVT_SDC)
+#define TX_CPU_EVENT_SW_EVENT7      (1 << TX_CPU_EVT_SW7)
+#define TX_CPU_EVENT_HOST_COALES    (1 << TX_CPU_EVT_HOST_COALES)
+#define TX_CPU_EVENT_SW_EVENT8      (1 << TX_CPU_EVT_SW8)
+#define TX_CPU_EVENT_HIGH_DMA_WR    (1 << TX_CPU_EVT_HIGH_DMA_WR)
+#define TX_CPU_EVENT_HIGH_DMA_RD    (1 << TX_CPU_EVT_HIGH_DMA_RD)
+#define TX_CPU_EVENT_SW_EVENT9      (1 << TX_CPU_EVT_SW9)
+#define TX_CPU_EVENT_DMA_ATTN       (1 << TX_CPU_EVT_DMA_ATTN)
+#define TX_CPU_EVENT_LOW_P_MBOX     (1 << TX_CPU_EVT_LOW_P_MBOX)
+#define TX_CPU_EVENT_HIGH_P_MBOX    (1 << TX_CPU_EVT_HIGH_P_MBOX)
+#define TX_CPU_EVENT_SW_EVENT10     (1 << TX_CPU_EVT_SW10)
+#define TX_CPU_EVENT_RX_CPU_ATTN    (1 << TX_CPU_EVT_RX_CPU_ATTN)
+#define TX_CPU_EVENT_MAC_ATTN       (1 << TX_CPU_EVT_MAC_ATTN)
+#define TX_CPU_EVENT_TX_CPU_ATTN    (1 << TX_CPU_EVT_TX_CPU_ATTN)
+#define TX_CPU_EVENT_FLOW_ATTN      (1 << TX_CPU_EVT_FLOW_ATTN)
+#define TX_CPU_EVENT_SW_EVENT11     (1 << TX_CPU_EVT_SW11)
+#define TX_CPU_EVENT_TIMER          (1 << TX_CPU_EVT_TIMER)
+#define TX_CPU_EVENT_SW_EVENT12     (1 << TX_CPU_EVT_SW12)
+#define TX_CPU_EVENT_SW_EVENT13     (1 << TX_CPU_EVT_SW13)
+
+
+#define TX_CPU_MASK (TX_CPU_EVENT_SW_EVENT0 | \
+                    TX_CPU_EVENT_SDI  | \
+                    TX_CPU_EVENT_SDC)
+
+
+#define T3_FTQ_TYPE1_UNDERFLOW_BIT   (1 << 29)
+#define T3_FTQ_TYPE1_PASS_BIT        (1 << 30)
+#define T3_FTQ_TYPE1_SKIP_BIT        (1 << 31)
+
+#define T3_FTQ_TYPE2_UNDERFLOW_BIT   (1 << 13)
+#define T3_FTQ_TYPE2_PASS_BIT        (1 << 14)
+#define T3_FTQ_TYPE2_SKIP_BIT        (1 << 15)
+
+#define T3_QID_DMA_READ               1
+#define T3_QID_DMA_HIGH_PRI_READ      2
+#define T3_QID_DMA_COMP_DX            3
+#define T3_QID_SEND_BD_COMP           4
+#define T3_QID_SEND_DATA_INITIATOR    5
+#define T3_QID_DMA_WRITE              6
+#define T3_QID_DMA_HIGH_PRI_WRITE     7
+#define T3_QID_SW_TYPE_1              8
+#define T3_QID_SEND_DATA_COMP         9
+#define T3_QID_HOST_COALESCING        10
+#define T3_QID_MAC_TX                 11
+#define T3_QID_MBUF_CLUSTER_FREE      12
+#define T3_QID_RX_BD_COMP             13
+#define T3_QID_RX_LIST_PLM            14
+#define T3_QID_RX_DATA_BD_INITIATOR   15
+#define T3_QID_RX_DATA_COMP           16
+#define T3_QID_SW_TYPE2               17
+
+LM_STATUS LM_LoadFirmware(PLM_DEVICE_BLOCK pDevice,
+                          PT3_FWIMG_INFO pFwImg,
+                          LM_UINT32 LoadCpu,
+                          LM_UINT32 StartCpu);
+
+/******************************************************************************/
+/* NIC register read/write macros. */
+/******************************************************************************/
+
+#if 0  /* Jimmy */
+/* MAC register access. */
+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);
+
+#if PCIX_TARGET_WORKAROUND
+
+/* use memory-mapped accesses for mailboxes and reads, UNDI accesses
+   for writes to all other registers */
+#define REG_RD(pDevice, OffsetName)                              \
+    readl(&((pDevice)->pMemView->OffsetName))
+
+#define REG_WR(pDevice, OffsetName, Value32)                     \
+    (((OFFSETOF(T3_STD_MEM_MAP, OffsetName) >=0x200 ) &&         \
+      (OFFSETOF(T3_STD_MEM_MAP, OffsetName) <0x400)) ||                 \
+        ((pDevice)->EnablePciXFix == FALSE)) ?                  \
+    (void) writel(Value32, &((pDevice)->pMemView->OffsetName)) : \
+    LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName), Value32)
+
+#define MB_REG_RD(pDevice, OffsetName)                           \
+    readl(&((pDevice)->pMemView->OffsetName))
+
+#define MB_REG_WR(pDevice, OffsetName, Value32)                  \
+    writel(Value32, &((pDevice)->pMemView->OffsetName))
+
+#define REG_RD_OFFSET(pDevice, Offset)                           \
+    readl(&((LM_UINT8 *) (pDevice)->pMemView + Offset))
+
+#define REG_WR_OFFSET(pDevice, Offset, Value32)                  \
+       (((Offset >=0x200 ) && (Offset < 0x400)) ||              \
+        ((pDevice)->EnablePciXFix == FALSE)) ?                  \
+    (void) writel(Value32, ((LM_UINT8 *) (pDevice)->pMemView + Offset)) : \
+    LM_RegWrInd(pDevice, 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)
+                               
+#else /* normal target access path below */
+
+/* Register access. */
+#define REG_RD(pDevice, OffsetName)                                         \
+    readl(&((pDevice)->pMemView->OffsetName))
+#define REG_WR(pDevice, OffsetName, Value32)                                \
+    writel(Value32, &((pDevice)->pMemView->OffsetName))
+
+#define REG_RD_OFFSET(pDevice, Offset)                                      \
+    readl(((LM_UINT8 *) (pDevice)->pMemView + Offset))
+#define REG_WR_OFFSET(pDevice, Offset, Value32)                             \
+    writel(Value32, ((LM_UINT8 *) (pDevice)->pMemView + Offset))
+
+
+/* There could be problem access the memory window directly.  For now, */
+/* we have to go through the PCI configuration register. */
+#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  /* PCIX_TARGET_WORKAROUND */
+
+#endif  /* Jimmy, merging */
+
+  /* Jimmy...rest of file is new stuff! */
+/******************************************************************************/
+/* NIC register read/write macros. */
+/******************************************************************************/
+
+/* MAC register access. */
+LM_UINT32 LM_RegRdInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register);
+LM_VOID LM_RegWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register,
+    LM_UINT32 Value32);
+
+/* MAC memory access. */
+LM_UINT32 LM_MemRdInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr);
+LM_VOID LM_MemWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr,
+    LM_UINT32 Value32);
+
+#define MB_REG_WR(pDevice, OffsetName, Value32)                               \
+    ((pDevice)->UndiFix) ?                                                    \
+        LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)+0x5600,     \
+            Value32) :                                                        \
+        (void) __raw_writel(Value32, &((pDevice)->pMemView->OffsetName))
+
+#define MB_REG_RD(pDevice, OffsetName)                                        \
+    (((pDevice)->UndiFix) ?                                                   \
+        LM_RegRdInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)+0x5600) :   \
+        __raw_readl(&((pDevice)->pMemView->OffsetName)))
+
+#define REG_RD(pDevice, OffsetName)                                           \
+    (((pDevice)->UndiFix) ?                                                   \
+        LM_RegRdInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)) :          \
+        __raw_readl(&((pDevice)->pMemView->OffsetName)))
+
+#if PCIX_TARGET_WORKAROUND
+
+#define REG_WR(pDevice, OffsetName, Value32)                                \
+        ((pDevice)->EnablePciXFix == FALSE) ?                              \
+    (void) __raw_writel(Value32, &((pDevice)->pMemView->OffsetName)) :      \
+    LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName), Value32)
+
+#else
+
+#define REG_WR(pDevice, OffsetName, Value32)                                \
+    __raw_writel(Value32, &((pDevice)->pMemView->OffsetName))
+
+#endif
+
+#define MEM_RD(pDevice, AddrName)                                           \
+    LM_MemRdInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName))
+#define MEM_WR(pDevice, AddrName, Value32)                                  \
+    LM_MemWrInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName), Value32)
+
+#define MEM_RD_OFFSET(pDevice, Offset)                                      \
+    LM_MemRdInd(pDevice, Offset)
+#define MEM_WR_OFFSET(pDevice, Offset, Value32)                             \
+    LM_MemWrInd(pDevice, Offset, Value32)
+                               
+#endif /* TIGON3_H */
+
diff --git a/include/configs/BMW.h b/include/configs/BMW.h
new file mode 100644 (file)
index 0000000..e39d1d3
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ *
+ * Configuration settings for the CU824 board.
+ *
+ */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC824x         1
+#define CONFIG_MPC8245         1
+#define CONFIG_BMW             1
+
+#define CONFIG_BCM570x         1 /* Use Broadcom BCM570x Ethernet Driver */
+
+#define CONFIG_CONS_INDEX      1
+#define CONFIG_BAUDRATE                9600
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
+
+#define CONFIG_CLOCKS_IN_MHZ   1       /* clocks passsed to Linux in MHz       */
+
+#define CONFIG_BOOTCOMMAND     "bootm FF820000"        /* autoboot command     */
+#define CONFIG_BOOTDELAY       5
+
+#define CFG_MAX_DOC_DEVICE      1 /* Only use Onboard TSOP-16MB device */
+#define DOC_PASSIVE_PROBE       1 
+#define CFG_DOC_SUPPORT_2000    1
+#define CFG_DOC_SUPPORT_MILLENNIUM 1
+#define CFG_DOC_SHORT_TIMEOUT    1
+#define CONFIG_COMMANDS                (CONFIG_CMD_DFL | \
+                               CFG_CMD_DATE    | \
+                               CFG_CMD_DOC     | \
+                               CFG_CMD_ELF     | \
+                               0 )
+#if 0
+#define CONFIG_COMMANDS                (CONFIG_CMD_DFL | CFG_CMD_DHCP | \
+                                CFG_CMD_PCI | CFG_CMD_DOC | CFG_CMD_DATE)
+
+#define CONFIG_PCI             1
+#define CONFIG_PCI_PNP         1       /* PCI plug-and-play */
+#endif
+
+/* This must be included AFTER the definition of CONFIG_COMMANDS (if any)
+ */
+#include <cmd_confdefs.h>
+
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP                   /* undef to save memory         */
+#define CFG_PROMPT     "=>"            /* Monitor Command Prompt       */
+#define CFG_CBSIZE     256             /* Console I/O Buffer Size      */
+
+/* Print Buffer Size
+ */
+#define CFG_PBSIZE     (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16)
+
+#define CFG_MAXARGS    8               /* Max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+#define CFG_LOAD_ADDR  0x00100000      /* Default load address         */
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE     0x00000000
+
+#define CFG_FLASH_BASE0_PRELIM      0xFFF00000      /* FLASH bank on RCS#0 */
+#define CFG_FLASH_BASE1_PRELIM      0xFF800000      /* FLASH bank on RCS#1 */
+#define CFG_FLASH_BASE  CFG_MONITOR_BASE
+#define CFG_FLASH_BANKS                { CFG_FLASH_BASE0_PRELIM , CFG_FLASH_BASE1_PRELIM }
+
+/* even though FLASHP_BASE is FF800000, with 4MB is RCS0, the
+ * reset vector is actually located at FFB00100, but the 8245
+ * takes care of us.
+ */
+#define CFG_RESET_ADDRESS   0xFFF00100
+
+#define CFG_EUMB_ADDR      0xFC000000
+
+#define CFG_MONITOR_BASE    TEXT_BASE
+
+#define CFG_MONITOR_LEN            (256 << 10) /* Reserve 256 kB for Monitor   */
+#define CFG_MALLOC_LEN     (2048 << 10) /* Reserve 2MB for malloc()    */
+
+#define CFG_MEMTEST_START   0x00004000 /* memtest works on             */
+#define CFG_MEMTEST_END            0x04000000  /* 0 ... 32 MB in DRAM          */
+
+       /* Maximum amount of RAM.
+        */
+#define CFG_MAX_RAM_SIZE    0x04000000 /* 0 .. 64 MB of (S)DRAM */
+
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+#undef CFG_RAMBOOT
+#else
+#define CFG_RAMBOOT
+#endif
+
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area
+ */
+#define CFG_INIT_RAM_ADDR CFG_SDRAM_BASE + CFG_MONITOR_LEN
+#define CFG_INIT_RAM_END   0x2F00  /* End of used area in DPRAM  */
+#define CFG_INIT_DATA_SIZE  128  /* size in bytes reserved for initial data */
+#define CFG_INIT_DATA_OFFSET  (CFG_INIT_RAM_END - CFG_INIT_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET  CFG_INIT_DATA_OFFSET
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ * For the detail description refer to the MPC8240 user's manual.
+ */
+
+#define CONFIG_SYS_CLK_FREQ  33000000  /* external frequency to pll */
+#define CFG_HZ              1000
+
+#define CFG_ETH_DEV_FN      0x7800
+#define CFG_ETH_IOBASE      0x00104000
+
+       /* Bit-field values for MCCR1.
+        */
+#define CFG_ROMNAL         0xf
+#define CFG_ROMFAL         0x1f
+#define CFG_DBUS_SIZE       0x3
+
+       /* Bit-field values for MCCR2.
+        */
+#define CFG_TSWAIT         0x5             /* Transaction Start Wait States timer */
+#define CFG_REFINT         0x400           /* Refresh interval FIXME: was 0t430                */
+
+       /* Burst To Precharge. Bits of this value go to MCCR3 and MCCR4.
+        */
+#define CFG_BSTOPRE        0           /* FIXME: was 192 */
+
+       /* Bit-field values for MCCR3.
+        */
+#define CFG_REFREC         2       /* Refresh to activate interval */
+
+       /* Bit-field values for MCCR4.
+        */
+#define CFG_PRETOACT       2       /* Precharge to activate interval FIXME: was 2      */
+#define CFG_ACTTOPRE       5       /* Activate to Precharge interval FIXME: was 5      */
+#define CFG_SDMODE_CAS_LAT  3      /* SDMODE CAS latancy */
+#define CFG_SDMODE_WRAP            0       /* SDMODE wrap type */
+#define CFG_SDMODE_BURSTLEN 3      /* SDMODE Burst length */
+#define CFG_ACTORW         0xa         /* FIXME was 2 */
+#define CFG_REGISTERD_TYPE_BUFFER 1
+
+#define CFG_PGMAX           0x0 /* how long the 8240 reatins the currently accessed page in memory FIXME: was 0x32*/
+
+#define CFG_SDRAM_DSCD 0x20    /* SDRAM data in sample clock delay - note bottom 3 bits MUST be 0 */
+
+/* Memory bank settings.
+ * Only bits 20-29 are actually used from these vales to set the
+ * start/end addresses. The upper two bits will always be 0, and the lower
+ * 20 bits will be 0x00000 for a start address, or 0xfffff for an end
+ * address. Refer to the MPC8240 book.
+ */
+
+#define CFG_BANK0_START            0x00000000
+#define CFG_BANK0_END      (CFG_MAX_RAM_SIZE - 1)
+#define CFG_BANK0_ENABLE    1
+#define CFG_BANK1_START            0x3ff00000
+#define CFG_BANK1_END      0x3fffffff
+#define CFG_BANK1_ENABLE    0
+#define CFG_BANK2_START            0x3ff00000
+#define CFG_BANK2_END      0x3fffffff
+#define CFG_BANK2_ENABLE    0
+#define CFG_BANK3_START            0x3ff00000
+#define CFG_BANK3_END      0x3fffffff
+#define CFG_BANK3_ENABLE    0
+#define CFG_BANK4_START            0x3ff00000
+#define CFG_BANK4_END      0x3fffffff
+#define CFG_BANK4_ENABLE    0
+#define CFG_BANK5_START            0x3ff00000
+#define CFG_BANK5_END      0x3fffffff
+#define CFG_BANK5_ENABLE    0
+#define CFG_BANK6_START            0x3ff00000
+#define CFG_BANK6_END      0x3fffffff
+#define CFG_BANK6_ENABLE    0
+#define CFG_BANK7_START            0x3ff00000
+#define CFG_BANK7_END      0x3fffffff
+#define CFG_BANK7_ENABLE    0
+
+#define CFG_ODCR           0xff
+
+#define CONFIG_PCI              1 /* Include PCI support */
+#undef CONFIG_PCI_PNP
+
+/* PCI Memory space(s) */
+#define PCI_MEM_SPACE1_START   0x80000000
+#define PCI_MEM_SPACE2_START   0xfd000000
+
+/* ROM Spaces */
+#include "../board/bmw/bmw.h"
+
+/* BAT configuration */
+#define CFG_IBAT0L  (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT0U  (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_IBAT1L  (0x70000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT1U  (0x70000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_IBAT2L  (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT2U  (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_IBAT3L  (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT3U  (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_DBAT0L  CFG_IBAT0L
+#define CFG_DBAT0U  CFG_IBAT0U
+#define CFG_DBAT1L  CFG_IBAT1L
+#define CFG_DBAT1U  CFG_IBAT1U
+#define CFG_DBAT2L  CFG_IBAT2L
+#define CFG_DBAT2U  CFG_IBAT2U
+#define CFG_DBAT3L  CFG_IBAT3L
+#define CFG_DBAT3U  CFG_IBAT3U
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ      (8 << 20)   /* Initial Memory map for Linux */
+
+/*
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    0       /* Max number of flash banks        */
+#define CFG_MAX_FLASH_SECT     64      /* Max number of sectors per  flash */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms) */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms) */
+
+/*
+ * Warining: environment is not EMBEDDED in the ppcboot code.
+ * It's stored in flash separately.
+ */
+#define CFG_ENV_IS_IN_NVRAM      1
+#define CONFIG_ENV_OVERWRITE     1
+#define CFG_NVRAM_ACCESS_ROUTINE 1
+#define CFG_ENV_ADDR           0x7c004000 /* right at the start of NVRAM  */
+#define CFG_ENV_SIZE           0x1ff0  /* Size of the Environment - 8K    */
+#define CFG_ENV_OFFSET         0       /* starting right at the beginning */
+
+/*
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE     32
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#  define CFG_CACHELINE_SHIFT  5       /* log base 2 of the above value   */
+#endif
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD          0x01    /* Normal Power-On: Boot from FLASH */
+#define BOOTFLAG_WARM          0x02    /* Software reboot                  */
+
+
+#endif /* __CONFIG_H */
index 09ccfec2d85b40dfb1c63cc6460d19ba3d4599b2..ae21dc855320d57dd0312965d7c8080f944beb1a 100644 (file)
@@ -54,6 +54,7 @@
 /* Kahlua/MPC8240 defines */
 #define VEN_DEV_ID             0x00021057      /* Vendor and Dev. ID for MPC106 */
 #define KAHLUA_ID              0x00031057      /* Vendor & Dev Id for Kahlua's PCI */
+#define KAHLUA2_ID             0x00061057      /* 8245 is aka Kahlua-2 */
 #define BMC_BASE               0x80000000      /* Kahlua ID in PCI Memory space */
 #define CHRP_REG_ADDR          0xfec00000      /* MPC107 Config, Map B */
 #define CHRP_REG_DATA          0xfee00000      /* MPC107 Config, Map B */
 #elif defined(CONFIG_MPC8245) || defined(CONFIG_MPC8241)
 #define PICR1_NO_BUSW_CK       0x00000080 /* no bus width check for flash writes */
 #define PICR1_DEC              0x00000100 /* Time Base enable on 8245/8241 */
+#define ERCR1                  0x800000d0  /* Extended ROM Configuration Register 1 */
+#define ERCR2                  0x800000d4  /* Extended ROM Configuration Register 2 */
+#define ERCR3                  0x800000d8  /* Extended ROM Configuration Register 3 */
+#define ERCR4                  0x800000dc  /* Extended ROM Configuration Register 4 */
+#define MIOCR1                 0x80000076  /* Miscellaneous I/O Control Register 1 */
+#define MIOCR1_ADR_X           0x80000074  /* Miscellaneous I/O Control Register 1 */
+#define MIOCR1_SHIFT           2
+#define MIOCR2                 0x80000077  /* Miscellaneous I/O Control Register 2 */
+#define MIOCR2_ADR_X           0x80000074  /* Miscellaneous I/O Control Register 1 */
+#define MIOCR2_SHIFT           3
+#define ODCR_ADR_X             0x80000070      /* Output Driver Control register */
+#define ODCR_SHIFT              3
+#define PMCR2_ADR              0x80000072      /* Power Mgmnt Cfg 2 register */
+#define PMCR2_ADR_X            0x80000070      
+#define PMCR2_SHIFT             3
+#define PMCR1_ADR              0x80000070      /* Power Mgmnt Cfg 1 reister */
 #else
 #error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240)
 #endif
index a48e2f01c7b5337b2f9d2ecf63dd4139421cf16c..4dbdc7643b8e9589a8c5faa2de8f4e65e0a9b7f7 100644 (file)
@@ -219,11 +219,12 @@ void    pci_init      (bd_t *);
 void    pciinfo       (int, int);
 #endif
 
-#if defined(CONFIG_CCM)                || defined(CONFIG_COGENT)       || \
-    defined(CONFIG_CPCI405)    || defined(CONFIG_HYMOD)        || \
-    defined(CONFIG_LWMON)      || defined(CONFIG_MISC_INIT_R)  || \
-    defined(CONFIG_PCU_E)      || defined(CONFIG_RSD_PROTO)    || \
-    defined(CONFIG_SXNI855T)   || defined(CONFIG_W7O)
+#if defined(CONFIG_BMW)                || defined(CONFIG_CCM)          || \
+    defined(CONFIG_COGENT)     || defined(CONFIG_CPCI405)      || \
+    defined(CONFIG_HYMOD)      || defined(CONFIG_LWMON)        || \
+    defined(CONFIG_MISC_INIT_R)        || defined(CONFIG_PCU_E)        || \
+    defined(CONFIG_RSD_PROTO)  || defined(CONFIG_SXNI855T)     || \
+    defined(CONFIG_W7O)
 
 /* cogent - $(BOARD)/mb.c */
 /* SXNI855T, HYMOD, and W7O - $(BOARD)/$(BOARD).c */