summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2007-09-14 15:43:37 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2007-09-14 15:43:37 +0000
commitb0471864737545dcce55c30a784277ef9c5f9c44 (patch)
treed1b501de34dc703abc6bd8e5d2bb0a85ccfd176f
parent2007-09-14 Joel Sherrill <joel.sherrill@OARcorp.com> (diff)
downloadrtems-b0471864737545dcce55c30a784277ef9c5f9c44.tar.bz2
2007-09-14 Kate Feng <feng1@bnl.gov>
* Makefile.am, README, README.booting, README.irq, preinstall.am, GT64260/MVME5500I2C.c, include/bsp.h, irq/irq.c, irq/irq.h, irq/irq_init.c, pci/pci.c, pci/pci_interface.c, pci/pcifinddevice.c, start/preload.S, startup/bspclean.c, startup/bspstart.c, startup/pgtbl_activate.c, startup/reboot.c: Merge my improvements in this BSP including a new network driver for the 1GHz NIC. * network/if_100MHz/GT64260eth.c, network/if_100MHz/GT64260eth.h, network/if_100MHz/GT64260ethreg.h, network/if_100MHz/Makefile.am, network/if_1GHz/Makefile.am, network/if_1GHz/POSSIBLEBUG, network/if_1GHz/if_wm.c, network/if_1GHz/if_wmreg.h, network/if_1GHz/pci_map.c, network/if_1GHz/pcireg.h: New files.
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/ChangeLog15
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/GT64260/MVME5500I2C.c9
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/Makefile.am33
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/README38
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/README.booting26
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/README.irq60
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/include/bsp.h30
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/irq/irq.c683
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/irq/irq.h32
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/irq/irq_init.c144
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/GT64260eth.c1575
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/GT64260eth.h140
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/GT64260ethreg.h880
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/Makefile.am46
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/Makefile.am45
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/POSSIBLEBUG4
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/if_wm.c1556
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/if_wmreg.h737
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/pci_map.c131
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/pcireg.h384
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/pci/pci.c9
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/pci/pci_interface.c69
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/pci/pcifinddevice.c47
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/preinstall.am28
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/start/preload.S70
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/startup/bspclean.c2
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/startup/bspstart.c254
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/startup/pgtbl_activate.c48
-rw-r--r--c/src/lib/libbsp/powerpc/mvme5500/startup/reboot.c4
29 files changed, 6197 insertions, 902 deletions
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/ChangeLog b/c/src/lib/libbsp/powerpc/mvme5500/ChangeLog
index b95243e776..bf9d1c1454 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/ChangeLog
+++ b/c/src/lib/libbsp/powerpc/mvme5500/ChangeLog
@@ -1,3 +1,18 @@
+2007-09-14 Kate Feng <feng1@bnl.gov>
+
+ * Makefile.am, README, README.booting, README.irq,
+ preinstall.am, GT64260/MVME5500I2C.c, include/bsp.h, irq/irq.c,
+ irq/irq.h, irq/irq_init.c, pci/pci.c, pci/pci_interface.c,
+ pci/pcifinddevice.c, start/preload.S, startup/bspclean.c,
+ startup/bspstart.c, startup/pgtbl_activate.c, startup/reboot.c:
+ Merge my improvements in this BSP including a new network
+ driver for the 1GHz NIC.
+ * network/if_100MHz/GT64260eth.c, network/if_100MHz/GT64260eth.h,
+ network/if_100MHz/GT64260ethreg.h, network/if_100MHz/Makefile.am,
+ network/if_1GHz/Makefile.am, network/if_1GHz/POSSIBLEBUG,
+ network/if_1GHz/if_wm.c, network/if_1GHz/if_wmreg.h,
+ network/if_1GHz/pci_map.c, network/if_1GHz/pcireg.h: New files.
+
2007-04-06 Ralf Corsépius <ralf.corsepius@rtems.org>
* bsp_specs: Remove lib (Now expected to exist in GCC).
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/GT64260/MVME5500I2C.c b/c/src/lib/libbsp/powerpc/mvme5500/GT64260/MVME5500I2C.c
index ddfae32783..ff64924485 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/GT64260/MVME5500I2C.c
+++ b/c/src/lib/libbsp/powerpc/mvme5500/GT64260/MVME5500I2C.c
@@ -12,23 +12,24 @@
*/
#include <rtems/bspIo.h> /* printk */
-#include <rtems/stdint.h>
#include "bsp/GT64260TWSI.h"
/* #define I2C_DEBUG*/
+typedef unsigned int u32;
+typedef unsigned char unchar;
-unsigned char I2cAddrPack(unsigned char busAddr,uint32_t offset)
+unchar I2cAddrPack(unchar busAddr,u32 offset)
{
return(busAddr | ((offset & 0x700) >> 7));
}
-unsigned char I2cDevByteAddr(uint32_t devA2A1A0, unsigned char byteNum)
+unchar I2cDevByteAddr(u32 devA2A1A0, unchar byteNum)
{
return(( devA2A1A0 >>(byteNum*8)) & 0xff);
}
/****************************************************************************
* I2Cread_eeprom - read EEPROM VPD from the I2C
*/
-int I2Cread_eeprom(unsigned char I2cBusAddr,uint32_t devA2A1A0,uint32_t AddrBytes,unsigned char *pBuff,uint32_t numBytes)
+int I2Cread_eeprom(unchar I2cBusAddr,u32 devA2A1A0,u32 AddrBytes,unchar *pBuff,u32 numBytes)
{
int status=0, lastByte=0;
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/Makefile.am b/c/src/lib/libbsp/powerpc/mvme5500/Makefile.am
index 5476dcd93f..77f19d1c7b 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/Makefile.am
+++ b/c/src/lib/libbsp/powerpc/mvme5500/Makefile.am
@@ -7,6 +7,9 @@ ACLOCAL_AMFLAGS = -I ../../../../aclocal
include $(top_srcdir)/../../../../automake/compile.am
include $(top_srcdir)/../../bsp.am
+#prevent the compiler from generating FP instructions
+AM_CFLAGS += -msoft-float
+
dist_project_lib_DATA = bsp_specs
include_HEADERS = include/bsp.h
@@ -29,6 +32,7 @@ EXTRA_DIST = startup/bootpstuff.c
noinst_PROGRAMS += startup.rel
startup_rel_SOURCES = startup/bspstart.c \
../../powerpc/shared/startup/pgtbl_setup.c startup/pgtbl_activate.c \
+ ../../powerpc/shared/startup/pretaskinghook.c \
../../powerpc/shared/startup/sbrk.c ../../shared/bootcard.c \
startup/bspclean.c ../../shared/bsplibc.c ../../shared/bsppost.c \
../../shared/main.c ../../shared/gnatinstallhandler.c startup/reboot.c
@@ -42,8 +46,8 @@ pclock_rel_CPPFLAGS = $(AM_CPPFLAGS)
pclock_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
###
-include_bsp_HEADERS = ../../powerpc/shared/console/uart.h \
- ../../shared/vmeUniverse/vme_am_defs.h
+include_bsp_HEADERS = ../../powerpc/shared/console/uart.h
+include_bsp_HEADERS += ../../powerpc/shared/console/consoleIo.h
noinst_PROGRAMS += console.rel
console_rel_SOURCES = ../../powerpc/shared/console/uart.c \
@@ -64,7 +68,7 @@ pci_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
include_bsp_HEADERS += irq/irq.h
noinst_PROGRAMS += irq.rel
-irq_rel_SOURCES = irq/irq_init.c irq/GT64260Int.c irq/irq.c \
+irq_rel_SOURCES = irq/irq_init.c irq/irq.c \
../../powerpc/shared/irq/irq_asm.S
irq_rel_CPPFLAGS = $(AM_CPPFLAGS)
irq_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
@@ -97,27 +101,28 @@ GT64260_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
##
if HAS_NETWORKING
-include_bsp_HEADERS += network/GT64260eth.h network/GT64260ethreg.h
+include_bsp_HEADERS += network/if_100MHz/GT64260eth.h network/if_100MHz/GT64260ethreg.h \
+ network/if_1GHz/if_wmreg.h network/if_1GHz/pcireg.h
network_CPPFLAGS = -D_KERNEL
noinst_PROGRAMS += network.rel
-network_rel_SOURCES = network/GT64260eth.c
+network_rel_SOURCES = network/if_100MHz/GT64260eth.c \
+ network/if_1GHz/if_wm.c network/if_1GHz/pci_map.c
network_rel_CPPFLAGS = $(AM_CPPFLAGS) $(network_CPPFLAGS)
network_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
endif
-##
-include_bsp_HEADERS += ../../shared/vmeUniverse/VME.h vme/VMEConfig.h
-include_bsp_HEADERS += ../../shared/vmeUniverse/vmeUniverse.h \
+##vme
+include_bsp_HEADERS += ../../shared/vmeUniverse/VME.h vme/VMEConfig.h \
+ ../../shared/vmeUniverse/vmeUniverse.h \
../../shared/vmeUniverse/vmeUniverseDMA.h\
../../shared/vmeUniverse/bspVmeDmaList.h\
- ../../shared/vmeUniverse/VMEDMA.h
+ ../../shared/vmeUniverse/VMEDMA.h \
+ ../../shared/vmeUniverse/vme_am_defs.h
noinst_PROGRAMS += vme.rel
-vme_rel_SOURCES = ../../shared/vmeUniverse/vmeUniverse.c
-vme_rel_SOURCES+= ../../shared/vmeUniverse/bspVmeDmaList.c
-vme_rel_SOURCES+= ../shared/vme/vmeconfig.c
-vme_rel_SOURCES+= ../shared/vme/vme_universe.c
-vme_rel_SOURCES+= ../shared/vme/vme_universe_dma.c
+vme_rel_SOURCES = ../../shared/vmeUniverse/vmeUniverse.c\
+ ../shared/vme/vmeconfig.c ../../shared/vmeUniverse/bspVmeDmaList.c\
+ ../shared/vme/vme_universe.c ../shared/vme/vme_universe_dma.c
vme_rel_CPPFLAGS = $(AM_CPPFLAGS)
vme_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/README b/c/src/lib/libbsp/powerpc/mvme5500/README
index 7d8b915fa4..75da1b6aa9 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/README
+++ b/c/src/lib/libbsp/powerpc/mvme5500/README
@@ -1,7 +1,40 @@
#
-# $Id$
+# $Id: README,v 1.3.1 Shuchen Kate Feng, NSLS, BNL (08/27/07)
#
+Please reference README.booting for the boot/load process.
+
+For the priority setting of the Interrupt Requests (IRQs), please
+reference README.irq
+
+The BSP is built and tested on the 4.7.1 and 4.7.99.2 CVS RTEMS release.
+
+I believe in valuable real-time programming, where technical neatness,
+performance and truth are. Any suggestion, bug reports, or even bug
+fixes (great!) are welcome so that I still believe what I believe.
+
+
+ACKNOWLEDGEMENTS
+----------------
+Acknowledgements:
+
+Valuable information was obtained from the following:
+1) Marvell NDA document for the discovery system controller.
+Other related documents are listed at :
+http://www.aps.anl.gov/epics/meetings/2006-06/RTEMS_Primer_SIG/RTEMS_BSP_MVME5500.pdf
+2) netBSD: For the two NICS and some headers :
+ Allegro Networks, Inc., Wasabi Systems, Inc.
+3) RTEMS: For the SVGM5 BSP
+ Stanford Linear Accelerator Center, Till Straumann
+
+ This BSP also builds on top of the work of others who have contributed
+ to similar RTEMS powerpc shared and motorola_powerpc BSPs, most notably
+ Eric Valette, Till Straumann, Eric Norum and others.
+
+LICENSE
+-------
+See ./LICENSE file.
+
BSP NAME: mvme5500
BOARD: MVME5500 by Motorola
BUS: PCI
@@ -12,9 +45,6 @@ MODE: 32/64 bit mode (support 32 bit for now)
DEBUG MONITOR: MOTLoad
SYSTEM CONTROLLER: GT64260B
-OTHER README FILES: README.booting,README.rtems-4.6.0-patch,README.VME,
- README.irq
-
PERIPHERALS
===========
TIMERS: Eight, 32 bit programmable
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/README.booting b/c/src/lib/libbsp/powerpc/mvme5500/README.booting
index 4a33d7fcc7..19e9567908 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/README.booting
+++ b/c/src/lib/libbsp/powerpc/mvme5500/README.booting
@@ -1,18 +1,15 @@
-README.booting: written by S. Kate Feng <feng1@bnl.gov>, 2004/10/11
+README.booting: written by S. Kate Feng <feng1@bnl.gov>, Aug. 28, 2007
The bootloader is adapted from Till Straumann's Generic Mini-loader,
-which he wrote originally for the SVGM powerpc board. Part of the
-BSP was derived from the "RTEMS-PowerPC BSPs" and the NetBSD projects.
-As of today, the BSP is built and tested on the RTEMS-4.6.0
-release with small patches I added (see README.rtems-4.6.0-patch
-and rtems-4.6.0-patch/ directory).
-
+which he wrote originally for the SVGM powerpc board.
+The BSP is built and tested on the 4.7 CVS RTEMS release.
Booting requirement :
-------------------------
-1) One needs to setup BOOTP/DHCP and TFTP servers and /etc/bootptab
- properly to boot the system. (Note : EPICS needs a NTP server).
+1) One needs to setup BOOTP/DHCP and TFTP servers and /etc/bootptab(BOOTP)
+ or /etc/dhcpd.conf (DHCP) properly to boot the system.
+ (Note : EPICS needs a NTP server).
2) Please copy the prebuilt RTEMS binary (e.g. misc/rtems5500-cexp.bin)
and perhaps others (e.g. misc/st.sys) to the /tftpboot/epics/hostname/bin/
@@ -35,8 +32,10 @@ MVME5500>
Note : (cxx.xx.xx.xx is the client IP address and
sxx.xx.xx.xx is the server IP address)
-4) Other reference web sites:
+4) Other reference web sites for mvme5500 BSP:
http://lansce.lanl.gov/EPICS/presentations/KateFeng%20RTEMS-mvme55001.ppt
+http://www.nsls.bnl.gov/facility/expsys/software/EPICS/
+http://www.nsls.bnl.gov/facility/expsys/software/EPICS/FAQ.txt
5) When generating code (especially C++) for this system, one should
use at least gcc-3.2 (preferrably a copy downloaded from the RTEMS
@@ -53,10 +52,3 @@ other useful utilities such as telnet, nfs, and so on.
tools and BSP, I would recommend one to reference
http://www.aps.anl.gov/epics/base/RTEMS/tutorial/
in additional to the RTEMS document.
-
-
-TODO lists:
-1) 1 GHZ ethernet ( work in progress, to be released soon)
-2) To measure the interrupt latency and context switching.
-3) To implement the watchdog timer.
-
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/README.irq b/c/src/lib/libbsp/powerpc/mvme5500/README.irq
index 3ebf672b3f..fb31c4a5c3 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/README.irq
+++ b/c/src/lib/libbsp/powerpc/mvme5500/README.irq
@@ -1,52 +1,20 @@
-README.irq : Shuchen Kate Feng <feng1@bnl.gov>, 10/10/04
+README.irq : Shuchen Kate Feng <feng1@bnl.gov>, Sept. 2, 2007
-
-The BSPirqPrioTable[] listed in irq_init.c is where the
+As per implementation in shared PPC code,
+the BSPirqPrioTable[96] listed in irq_init.c is where the
software developers can change the levels of priority
-for main interrupts based on the need of their
-applications.
-
-
-Presently, a dynamic IRQ table (e.g. mainIrqTbl[64]), which is
-arranged dynamically based on the priority levels of enabled
-main interrupts, is used in C_dispatch_irq_handler() to
-incorporate the handling of the software priority levels.
-
-
-The valid entries listed in mainIrqTbl[64] by the BSP are:
-
-1. Main interrupt 59 (GPP31_24 : no enabled IRQ yet,
- to enable 'watchdog timer' if needed)
-2. Main interrupt 57 (GPP15_8 : VME interrupt enabled,
- to enable 'PMC1' if needed)
-3. Main interrupt 58 (GPP23_16 : no enabled IRQ yet,
- to enable '1 GHZ ethernet' or 'PMC2'
- if needed)
-4. Main interrupt 32 (10/100 MHZ ethernet)
-5. Main interrupt 56 (GPP7_0 : presently only COM1/COM2 enabled)
-
-
-The main IRQs can be added to the mainIrqTbl[] dynamically
-via the BSP_enable_main_irq(), or removed from the mainIrqTbl[]
-dynamically via the BSP_disable_main_irq().
-
-
-Regarding other GPP interrupts not listed in the GPP7_0IrqTbl[8],
-GPP15_8IrqTbl[8], GPP23_16IrqTbl[8], or GPP31_24IrqTbl[8], they
-could be enabled by being added to the correspondent of
-the four aforementioned tables listed in the irq_init.c.
-
+for all the interrupts based on the need of their
+applications. The IRQs can be eanbled dynamically via the
+BSP_enable_pic_irq(), or disbaled dynamically via the
+BSP_disable_pic_irq().
-Caveat: Presently, the eight GPP IRQs for each BSP_MAIN_GPPx_y_IRQ group
-are set at the same main priority in the BSPirqPrioTable[], while the
-sub-priority levels for the eight GPP in each group are sorted
-statically by developers in the GPPx_yIrqTbl[8] from the highest
-priority to the lowest one.
+Support for run-time priority setup could be
+added easily, but there is no action taken yet due to concerns
+over computer security at VME CPU level.
-Note :
-1. GPP7-0 (Main interrupt high cause, bit 24)
-2. GPP15-8 (Main interrupt high cause, bit 25)
-3. GPP23-16 (Main interrupt high cause, bit 26)
-4. GPP31-24 (Main interrupt high cause, bit 27)
+The software developers are forbidden to setup picIsrTable[],
+as it is a powerful engine for the BSP to find the pending
+highest priority IRQ at run time. It ensures the fastest/faster
+interrupt service to the highest/higher priority IRQ, if pending.
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/include/bsp.h b/c/src/lib/libbsp/powerpc/mvme5500/include/bsp.h
index e119615e56..847b4a59e4 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/include/bsp.h
+++ b/c/src/lib/libbsp/powerpc/mvme5500/include/bsp.h
@@ -7,7 +7,7 @@
* found in found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
- * S. Kate Feng 12/03 : Modified it to support the MVME5500 board.
+ * S. Kate Feng 2003-2007 : Modified it to support the mvme5500 BSP.
*
*/
@@ -53,14 +53,13 @@
#define BSP_MAX_PCI_BUS (BSP_MAX_PCI_BUS_ON_PCI0+BSP_MAX_PCI_BUS_ON_PCI1)
-#if 0
-/* T.S, 2007/1: in order to let the universe acknowledge the interrupt
- * (this allows for VME software priorities) corresponding support
- * **MUST** be present in the interrupt controller driver
- * Unless that's implemented DO NOT define BSP_PIC_DO_EOI.
+/* The glues to Till's vmeUniverse, although the name does not
+ * actually reflect the relevant architect of the MVME5500.
+ * Till TODO ? : BSP_PCI_DO_EOI instead ?
+ * BSP_EXT_IRQ0 instead of BSP_PCI_IRQ0 ?
+ *
*/
#define BSP_PIC_DO_EOI inl(0xc34) /* PCI IACK */
-#endif
#define BSP_PCI_IRQ0 BSP_GPP_IRQ_LOWEST_OFFSET
/*
@@ -111,11 +110,28 @@ extern int BSP_connect_clock_handler (void);
extern unsigned long _BSP_clear_hostbridge_errors();
+extern unsigned int BSP_heap_start;
+
+#if 1
#define RTEMS_BSP_NETWORK_DRIVER_NAME "gt1"
#define RTEMS_BSP_NETWORK_DRIVER_ATTACH rtems_GT64260eth_driver_attach
+#else
+#define RTEMS_BSP_NETWORK_DRIVER_NAME "wmG1"
+#define RTEMS_BSP_NETWORK_DRIVER_ATTACH rtems_i82544EI_driver_attach
+#endif
extern int
RTEMS_BSP_NETWORK_DRIVER_ATTACH(/* struct rtems_bsdnet_ifconfig * */);
+#define gccMemBar() RTEMS_COMPILER_MEMORY_BARRIER()
+
+static inline void memBar()
+{
+ asm volatile("sync":::"memory");
+}
+static inline void ioBar()
+{
+ asm volatile("eieio":::"memory");
+}
#endif
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/irq/irq.c b/c/src/lib/libbsp/powerpc/mvme5500/irq/irq.c
index 9c22dcb167..a4a82448f4 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/irq/irq.c
+++ b/c/src/lib/libbsp/powerpc/mvme5500/irq/irq.c
@@ -6,14 +6,20 @@
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
+ * http://www.OARcorp.com/rtems/license.html.
*
- * Special acknowledgement to Till Straumann <strauman@slac.stanford.edu>
- * for providing inputs to the IRQ handling and optimization.
+ * Acknowledgement May 2004 : to Till Straumann <strauman@slac.stanford.edu>
+ * for some inputs.
*
- * Modified and added support for the MVME5500 board
- * Copyright 2003, 2004, Shuchen Kate Feng <feng1@bnl.gov>,
+ * Copyright 2003, 2004, 2005, 2007 Shuchen Kate Feng <feng1@bnl.gov>,
* NSLS,Brookhaven National Laboratory
+ * 1) Modified and added support for the MVME5500 board.
+ * 2) The implementation of picIsrTable[] is an original work by the
+ * author to optimize the software IRQ priority scheduling because
+ * Discovery controller does not provide H/W IRQ priority schedule.
+ * It ensures the fastest/faster interrupt service to the
+ * highest/higher priority IRQ, if pendig.
+ * 3) _CPU_MSR_SET() needs RTEMS_COMPILER_MEMORY_BARRIER()
*
*/
@@ -23,7 +29,9 @@
#include <rtems/score/thread.h>
#include <rtems/score/apiext.h>
#include <libcpu/raw_exception.h>
+#include <rtems/rtems/intr.h>
#include <libcpu/io.h>
+#include <libcpu/byteorder.h>
#include <bsp/vectors.h>
#include <rtems/bspIo.h> /* for printk */
@@ -31,20 +39,35 @@
#define HI_INT_CAUSE 0x40000000
-/*#define DEBUG*/
+#define MAX_IRQ_LOOP 30
-int gpp_int_error =0;
+#define EDGE_TRIGGER
+
+#define _MSR_GET( _mask) \
+ do { \
+ RTEMS_COMPILER_MEMORY_BARRIER(); \
+ _CPU_MSR_GET( _mask); \
+ RTEMS_COMPILER_MEMORY_BARRIER(); \
+ } while (0);
+
+#define _MSR_SET( _mask) \
+ do { \
+ RTEMS_COMPILER_MEMORY_BARRIER(); \
+ _CPU_MSR_SET( _mask); \
+ RTEMS_COMPILER_MEMORY_BARRIER(); \
+ } while (0);
+
+/* #define DEBUG_IRQ*/
/*
* pointer to the mask representing the additionnal irq vectors
* that must be disabled when a particular entry is activated.
- * They will be dynamically computed from teh prioruty table given
+ * They will be dynamically computed from the table given
* in BSP_rtems_irq_mngt_set();
* CAUTION : this table is accessed directly by interrupt routine
* prologue.
*/
-static unsigned int irq_prio_maskLO_tbl[BSP_MAIN_IRQ_NUMBER];
-static unsigned int irq_prio_maskHI_tbl[BSP_MAIN_IRQ_NUMBER];
+static unsigned int BSP_irq_prio_mask_tbl[3][BSP_PIC_IRQ_NUMBER];
/*
* default handler connected on each irq after bsp initialization
@@ -58,26 +81,55 @@ static rtems_irq_connect_data default_rtems_entry;
static rtems_irq_global_settings* internal_config;
static rtems_irq_connect_data* rtems_hdl_tbl;
-static unsigned int irqCAUSE[20], irqLOW[20], irqHIGH[20];
-static int irqIndex=0;
+static volatile unsigned *BSP_irqMask_reg[3];
+static volatile unsigned *BSP_irqCause_reg[3];
+static volatile unsigned BSP_irqMask_cache[3]={0,0,0};
-/*
- * Check if IRQ is a MAIN CPU internal IRQ
+
+static int picIsrTblPtr=0;
+static unsigned int GPPIrqInTbl=0;
+static unsigned long long MainIrqInTbl=0;
+
+/*
+ * The software developers are forbidden to setup picIsrTable[],
+ * as it is a powerful engine for the BSP to find the pending
+ * highest priority IRQ at run time. It ensures the fastest/faster
+ * interrupt service to the highest/higher priority IRQ, if pendig.
+ *
+ * The picIsrTable[96] is updated dynamically at run time
+ * based on the priority levels set at BSPirqPrioTable[96],
+ * while the BSP_enable_pic_irq(), and BSP_disable_pic_irq()
+ * commands are invoked.
+ *
+ * The picIsrTable[96] lists the enabled CPU main and GPP external interrupt
+ * numbers [0 (lowest)- 95 (highest)] starting from the highest priority
+ * one to the lowest priority one. The highest priority interrupt is
+ * located at picIsrTable[0], and the lowest priority interrupt is located
+ * at picIsrTable[picIsrTblPtr-1].
+ *
+ *
*/
-static inline int is_main_irq(const rtems_irq_number irqLine)
-{
- return (((int) irqLine <= BSP_MICH_IRQ_MAX_OFFSET) &
- ((int) irqLine >= BSP_MICL_IRQ_LOWEST_OFFSET)
- );
-}
+/* BitNums for Main Interrupt Lo/High Cause and GPP, -1 means invalid bit */
+static unsigned int picIsrTable[BSP_PIC_IRQ_NUMBER]={
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1 };
+
/*
- * Check if IRQ is a GPP IRQ
+ * Check if IRQ is a MAIN CPU internal IRQ or GPP external IRQ
*/
-static inline int is_gpp_irq(const rtems_irq_number irqLine)
+static inline int is_pic_irq(const rtems_irq_number irqLine)
{
return (((int) irqLine <= BSP_GPP_IRQ_MAX_OFFSET) &
- ((int) irqLine >= BSP_GPP_IRQ_LOWEST_OFFSET)
+ ((int) irqLine >= BSP_MICL_IRQ_LOWEST_OFFSET)
);
}
@@ -91,104 +143,14 @@ static inline int is_processor_irq(const rtems_irq_number irqLine)
);
}
-#define GT_GPP_Int1_Cause GT_GPP_Interrupt_Cause+1
-#define GT_GPP_Int2_Cause GT_GPP_Interrupt_Cause+2
-#define GT_GPP_Int3_Cause GT_GPP_Interrupt_Cause+3
-
-void GT_GPP_IntHandler0()
-{
-
- unsigned gppCause, irqNum, bitNum;
- int i, found=0;
-
- gppCause = inb(GT_GPP_Interrupt_Cause) & GT_GPPirq_cache;
-
- for (i=0; GPP7_0IrqTbl[i]!=-1;i++){
- bitNum =GPP7_0IrqTbl[i];
- if (gppCause & (1<<bitNum)) {
- /* Clear the GPP interrupt cause bit */
- outb( ~(1<<bitNum), GT_GPP_Interrupt_Cause);/* Till Straumann */
- found = 1;
- irqNum = bitNum+BSP_GPP_IRQ_LOWEST_OFFSET;
- /* call the necessary interrupt handlers */
- if (rtems_hdl_tbl[irqNum].hdl != default_rtems_entry.hdl)
- rtems_hdl_tbl[irqNum].hdl(rtems_hdl_tbl[irqNum].handle);
- else
- gpp_int_error= bitNum; /*GPP interrupt bitNum not connected */
- }
- }
- if ( !found) gpp_int_error = 33; /* spurious GPP interrupt */
-}
-
-void GT_GPP_IntHandler1()
+static inline unsigned int divIrq32(unsigned irq)
{
- unsigned gppCause, irqNum, bitNum;
- int i, found=0;
-
- gppCause = inb(GT_GPP_Int1_Cause) & (GT_GPPirq_cache>>8);
-
- for (i=0; GPP15_8IrqTbl[i]!=-1;i++){
- bitNum =GPP15_8IrqTbl[i];
- if (gppCause & (1<<bitNum)) {
- /* Clear the GPP interrupt cause bit */
- outb( ~(1<<bitNum), GT_GPP_Int1_Cause); /* Till Straumann */
- found = 1;
- irqNum = bitNum+BSP_GPP8_IRQ_OFFSET;
- /* call the necessary interrupt handlers */
- if (rtems_hdl_tbl[irqNum].hdl != default_rtems_entry.hdl)
- rtems_hdl_tbl[irqNum].hdl(rtems_hdl_tbl[irqNum].handle);
- else
- gpp_int_error= bitNum+8; /*GPP interrupt bitNum not connected */
- }
- }
- if ( !found) gpp_int_error = 33; /* spurious GPP interrupt */
-}
-void GT_GPP_IntHandler2()
-{
- unsigned gppCause, irqNum, bitNum;
- int i, found=0;
-
- gppCause = inb(GT_GPP_Int2_Cause) & (GT_GPPirq_cache>>16);
-
- for (i=0; GPP23_16IrqTbl[i]!=-1;i++){
- bitNum =GPP23_16IrqTbl[i];
- if (gppCause & (1<<bitNum)) {
- /* Clear the GPP interrupt cause bit */
- outb( ~(1<<bitNum), GT_GPP_Int2_Cause);
- found = 1;
- irqNum = bitNum+BSP_GPP16_IRQ_OFFSET;
- /* call the necessary interrupt handlers */
- if (rtems_hdl_tbl[irqNum].hdl != default_rtems_entry.hdl)
- rtems_hdl_tbl[irqNum].hdl(rtems_hdl_tbl[irqNum].handle);
- else
- gpp_int_error= bitNum+16; /*GPP interrupt bitNum not connected */
- }
- }
- if ( !found) gpp_int_error = 33; /* spurious GPP interrupt */
+ return(irq/32);
}
-void GT_GPP_IntHandler3()
+static inline unsigned int modIrq32(unsigned irq)
{
- unsigned gppCause, irqNum, bitNum;
- int i, found=0;
-
- gppCause = inb(GT_GPP_Int3_Cause) & (GT_GPPirq_cache>>24);
-
- for (i=0; GPP31_24IrqTbl[i]!=-1;i++){
- bitNum=GPP31_24IrqTbl[i];
- if (gppCause & (1<<bitNum)) {
- /* Clear the GPP interrupt cause bit */
- outb(~(1<<bitNum), GT_GPP_Int3_Cause);
- found = 1;
- irqNum = bitNum+BSP_GPP24_IRQ_OFFSET;
- /* call the necessary interrupt handlers */
- if (rtems_hdl_tbl[irqNum].hdl != default_rtems_entry.hdl)
- rtems_hdl_tbl[irqNum].hdl(rtems_hdl_tbl[irqNum].handle);
- else
- gpp_int_error= bitNum+24; /*GPP interrupt bitNum not connected */
- }
- }
- if ( !found) gpp_int_error = 33; /* spurious GPP interrupt */
+ return(irq%32);
}
/*
@@ -200,35 +162,255 @@ void GT_GPP_IntHandler3()
* is already set and that the tables it contains are still valid
* and accessible.
*/
-static void compute_GT64260int_masks_from_prio ()
+static void compute_pic_masks_from_prio()
{
- int i,j;
+ int i,j, k;
unsigned long long irq_prio_mask=0;
/*
* Always mask at least current interrupt to prevent re-entrance
*/
- for (i=0; i <BSP_MAIN_IRQ_NUMBER; i++) {
- irq_prio_mask = (unsigned long long) (1LLU << i);
+ for (i=0; i <BSP_PIC_IRQ_NUMBER; i++) {
+ switch(i) {
+ case BSP_MAIN_GPP7_0_IRQ:
+ case BSP_MAIN_GPP15_8_IRQ:
+ case BSP_MAIN_GPP23_16_IRQ:
+ case BSP_MAIN_GPP31_24_IRQ:
+ for (k=0; k< 3; k++)
+ BSP_irq_prio_mask_tbl[k][i]=0;
+
+ irq_prio_mask =0;
+ break;
+ default :
+ irq_prio_mask = (unsigned long long) (1LLU << i);
+ break;
+ }
+
+ if (irq_prio_mask) {
for (j = 0; j <BSP_MAIN_IRQ_NUMBER; j++) {
- /*
- * Mask interrupts at GT64260int level that have a lower priority
- * or <Till Straumann> a equal priority.
- */
- if (internal_config->irqPrioTbl [i] >= internal_config->irqPrioTbl [j]) {
- irq_prio_mask |= (unsigned long long)(1LLU << j);
- }
+ /*
+ * Mask interrupts at PIC level that have a lower priority
+ * or <Till Straumann> a equal priority.
+ */
+ if (internal_config->irqPrioTbl [i] >= internal_config->irqPrioTbl [j])
+ irq_prio_mask |= (unsigned long long)(1LLU << j);
}
+
- irq_prio_maskLO_tbl[i] = irq_prio_mask & 0xffffffff;
- irq_prio_maskHI_tbl[i] = (irq_prio_mask>>32) & 0xffffffff;
+ BSP_irq_prio_mask_tbl[0][i] = irq_prio_mask & 0xffffffff;
+ BSP_irq_prio_mask_tbl[1][i] = (irq_prio_mask>>32) & 0xffffffff;
#ifdef DEBUG
- printk("irq_mask_prio_tbl[%d]:0x%8x%8x\n",i,irq_prio_maskHI_tbl[i],
- irq_prio_maskLO_tbl[i]);
-#endif
+ printk("irq_mask_prio_tbl[%d]:0x%8x%8x\n",i,BSP_irq_prio_mask_tbl[1][i],
+ BSP_irq_prio_mask_tbl[0][i]);
+#endif
+
+ BSP_irq_prio_mask_tbl[2][i] = 1<<i;
+ /* Compute for the GPP priority interrupt mask */
+ for (j=BSP_GPP_IRQ_LOWEST_OFFSET; j <BSP_PROCESSOR_IRQ_LOWEST_OFFSET; j++) {
+ if (internal_config->irqPrioTbl [i] >= internal_config->irqPrioTbl [j])
+ BSP_irq_prio_mask_tbl[2][i] |= 1 << (j-BSP_GPP_IRQ_LOWEST_OFFSET);
+ }
+ }
}
}
+
+static void UpdateMainIrqTbl(int irqNum)
+{
+ int i=0, j, shifted=0;
+
+ switch (irqNum) {
+ case BSP_MAIN_GPP7_0_IRQ:
+ case BSP_MAIN_GPP15_8_IRQ:
+ case BSP_MAIN_GPP23_16_IRQ:
+ case BSP_MAIN_GPP31_24_IRQ:
+ return; /* Do nothing, let GPP take care of it */
+ break;
+ }
+#ifdef SHOW_MORE_INIT_SETTINGS
+ unsigned long val2, val1;
+#endif
+
+ /* If entry not in table*/
+ if ( ((irqNum<BSP_GPP_IRQ_LOWEST_OFFSET) &&
+ (!((unsigned long long)(1LLU << irqNum) & MainIrqInTbl))) ||
+ ((irqNum>BSP_MICH_IRQ_MAX_OFFSET) &&
+ (!(( 1 << (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)) & GPPIrqInTbl))))
+ {
+ while ( picIsrTable[i]!=-1) {
+ if (internal_config->irqPrioTbl[irqNum]>internal_config->irqPrioTbl[picIsrTable[i]]) {
+ /* all other lower priority entries shifted right */
+ for (j=picIsrTblPtr;j>i; j--)
+ picIsrTable[j]=picIsrTable[j-1];
+ picIsrTable[i]=irqNum;
+ shifted=1;
+ break;
+ }
+ i++;
+ }
+ if (!shifted) picIsrTable[picIsrTblPtr]=irqNum;
+ if (irqNum >BSP_MICH_IRQ_MAX_OFFSET)
+ GPPIrqInTbl |= (1<< (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET));
+ else
+ MainIrqInTbl |= (unsigned long long)(1LLU << irqNum);
+ picIsrTblPtr++;
+ }
+#ifdef SHOW_MORE_INIT_SETTINGS
+ val2 = (MainIrqInTbl>>32) & 0xffffffff;
+ val1 = MainIrqInTbl&0xffffffff;
+ printk("irqNum %d, MainIrqInTbl 0x%x%x\n", irqNum, val2, val1);
+ BSP_printPicIsrTbl();
+#endif
+
+}
+
+
+static void CleanMainIrqTbl(int irqNum)
+{
+ int i, j;
+
+ switch (irqNum) {
+ case BSP_MAIN_GPP7_0_IRQ:
+ case BSP_MAIN_GPP15_8_IRQ:
+ case BSP_MAIN_GPP23_16_IRQ:
+ case BSP_MAIN_GPP31_24_IRQ:
+ return; /* Do nothing, let GPP take care of it */
+ break;
+ }
+ if ( ((irqNum<BSP_GPP_IRQ_LOWEST_OFFSET) &&
+ ((unsigned long long)(1LLU << irqNum) & MainIrqInTbl)) ||
+ ((irqNum>BSP_MICH_IRQ_MAX_OFFSET) &&
+ (( 1 << (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)) & GPPIrqInTbl)))
+ { /* If entry in table*/
+ for (i=0; i<64; i++) {
+ if (picIsrTable[i]==irqNum) {/*remove it from the entry */
+ /* all other lower priority entries shifted left */
+ for (j=i;j<picIsrTblPtr; j++)
+ picIsrTable[j]=picIsrTable[j+1];
+ if (irqNum >BSP_MICH_IRQ_MAX_OFFSET)
+ GPPIrqInTbl &= ~(1<< (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET));
+ else
+ MainIrqInTbl &= ~(1LLU << irqNum);
+ picIsrTblPtr--;
+ break;
+ }
+ }
+ }
+}
+
+void BSP_enable_pic_irq(const rtems_irq_number irqNum)
+{
+ unsigned bitNum, regNum;
+ unsigned int level;
+
+ bitNum = modIrq32(((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET);
+ regNum = divIrq32(((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET);
+
+ rtems_interrupt_disable(level);
+
+ UpdateMainIrqTbl((int) irqNum);
+ BSP_irqMask_cache[regNum] |= (1 << bitNum);
+
+ out_le32(BSP_irqMask_reg[regNum], BSP_irqMask_cache[regNum]);
+ while (in_le32(BSP_irqMask_reg[regNum]) != BSP_irqMask_cache[regNum]);
+
+ rtems_interrupt_enable(level);
+}
+
+void BSP_disable_pic_irq(const rtems_irq_number irqNum)
+{
+ unsigned bitNum, regNum;
+ unsigned int level;
+
+ bitNum = modIrq32(((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET);
+ regNum = divIrq32(((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET);
+
+ rtems_interrupt_disable(level);
+
+ CleanMainIrqTbl((int) irqNum);
+ BSP_irqMask_cache[regNum] &= ~(1 << bitNum);
+
+ out_le32(BSP_irqMask_reg[regNum], BSP_irqMask_cache[regNum]);
+ while (in_le32(BSP_irqMask_reg[regNum]) != BSP_irqMask_cache[regNum]);
+
+ rtems_interrupt_enable(level);
+}
+
+int BSP_setup_the_pic() /* adapt the same name as shared/irq */
+{
+ int i;
+
+ /* Get ready for discovery BSP */
+ BSP_irqMask_reg[0]= (volatile unsigned int *) (GT64260_REG_BASE + GT_CPU_INT_MASK_LO);
+ BSP_irqMask_reg[1]= (volatile unsigned int *) (GT64260_REG_BASE + GT_CPU_INT_MASK_HI);
+ BSP_irqMask_reg[2]= (volatile unsigned int *) (GT64260_REG_BASE + GT_GPP_Interrupt_Mask);
+
+ BSP_irqCause_reg[0]= (volatile unsigned int *) (GT64260_REG_BASE + GT_MAIN_INT_CAUSE_LO);
+ BSP_irqCause_reg[1]= (volatile unsigned int *) (GT64260_REG_BASE + GT_MAIN_INT_CAUSE_HI);
+ BSP_irqCause_reg[2]= (volatile unsigned int *) (GT64260_REG_BASE + GT_GPP_Interrupt_Cause);
+
+#ifdef EDGE_TRIGGER
+
+ /* Page 401, Table 598:
+ * Comm Unit Arbiter Control register :
+ * bit 10:GPP interrupts as level sensitive(1) or edge sensitive(0).
+ * We set the GPP interrupts to be edge sensitive.
+ * MOTload default is set as level sensitive(1).
+ */
+ outl((inl(GT_CommUnitArb_Ctrl)& (~(1<<10))), GT_CommUnitArb_Ctrl);
+#else
+ outl((inl(GT_CommUnitArb_Ctrl)| (1<<10)), GT_CommUnitArb_Ctrl);
+#endif
+
+#if 0
+ printk("BSP_irqMask_reg[0] = 0x%x, BSP_irqCause_reg[0] 0x%x\n",
+ in_le32(BSP_irqMask_reg[0]),
+ in_le32(BSP_irqCause_reg[0]));
+ printk("BSP_irqMask_reg[1] = 0x%x, BSP_irqCause_reg[1] 0x%x\n",
+ in_le32(BSP_irqMask_reg[1]),
+ in_le32(BSP_irqCause_reg[1]));
+ printk("BSP_irqMask_reg[2] = 0x%x, BSP_irqCause_reg[2] 0x%x\n",
+ in_le32(BSP_irqMask_reg[2]),
+ in_le32(BSP_irqCause_reg[2]));
+#endif
+
+ /* Initialize the interrupt related GT64260 registers */
+ for (i=0; i<3; i++) {
+ out_le32(BSP_irqCause_reg[i], 0);
+ out_le32(BSP_irqMask_reg[i], 0);
+ }
+ in_le32(BSP_irqMask_reg[2]);
+ compute_pic_masks_from_prio();
+
+#if 0
+ printk("BSP_irqMask_reg[0] = 0x%x, BSP_irqCause_reg[0] 0x%x\n",
+ in_le32(BSP_irqMask_reg[0]),
+ in_le32(BSP_irqCause_reg[0]));
+ printk("BSP_irqMask_reg[1] = 0x%x, BSP_irqCause_reg[1] 0x%x\n",
+ in_le32(BSP_irqMask_reg[1]),
+ in_le32(BSP_irqCause_reg[1]));
+ printk("BSP_irqMask_reg[2] = 0x%x, BSP_irqCause_reg[2] 0x%x\n",
+ in_le32(BSP_irqMask_reg[2]),
+ in_le32(BSP_irqCause_reg[2]));
+#endif
+
+ /*
+ *
+ */
+ for (i=BSP_MICL_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET ; i++) {
+ if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
+ BSP_enable_pic_irq(i);
+ rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
+ }
+ else {
+ rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
+ BSP_disable_pic_irq(i);
+ }
+ }
+
+ return(1);
+}
+
/*
* This function check that the value given for the irq line
* is valid.
@@ -260,9 +442,9 @@ int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
* RATIONALE : to always have the same transition by forcing the user
* to get the previous handler before accepting to disconnect.
*/
- _CPU_ISR_Disable(level);
+ rtems_interrupt_disable(level);
if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
- _CPU_ISR_Enable(level);
+ rtems_interrupt_enable(level);
printk("IRQ vector %d already connected\n",irq->name);
return 0;
}
@@ -271,35 +453,33 @@ int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
* store the data provided by user
*/
rtems_hdl_tbl[irq->name] = *irq;
+#ifdef BSP_SHARED_HANDLER_SUPPORT
+ rtems_hdl_tbl[irq->name].next_handler = (void *)-1;
+#endif
- if (is_main_irq(irq->name)) {
+ if (is_pic_irq(irq->name)) {
/*
- * Enable (internal ) Main Interrupt Cause Low and High
+ * Enable PIC irq : Main Interrupt Cause Low and High & GPP external
*/
#ifdef DEBUG_IRQ
- printk("main irq %d\n",irq->name);
+ printk("PIC irq %d\n",irq->name);
#endif
- BSP_enable_main_irq(irq->name);
- }
-
- if (is_gpp_irq(irq->name)) {
- /*
- * Enable (external) GPP[x] interrupt
- */
- BSP_enable_gpp_irq((int) irq->name);
+ BSP_enable_pic_irq(irq->name);
}
+ else {
+ if (is_processor_irq(irq->name)) {
+ /*
+ * Enable exception at processor level
+ */
- if (is_processor_irq(irq->name)) {
- /*
- * Enable exception at processor level
- */
+ }
}
/*
* Enable interrupt on device
-
- irq->on(irq);*/
+ */
+ irq->on(irq);
- _CPU_ISR_Enable(level);
+ rtems_interrupt_enable(level);
return 1;
}
@@ -331,24 +511,19 @@ int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
return 0;
}
- _CPU_ISR_Disable(level);
+ rtems_interrupt_disable(level);
- if (is_main_irq(irq->name)) {
- /*
- * disable CPU main interrupt
- */
- BSP_disable_main_irq(irq->name);
- }
- if (is_gpp_irq(irq->name)) {
- /*
- * disable external interrupt
- */
- BSP_disable_gpp_irq(irq->name);
- }
- if (is_processor_irq(irq->name)) {
- /*
- * disable exception at processor level
- */
+ /*
+ * disable PIC interrupt
+ */
+ if (is_pic_irq(irq->name))
+ BSP_disable_pic_irq(irq->name);
+ else {
+ if (is_processor_irq(irq->name)) {
+ /*
+ * disable exception at processor level
+ */
+ }
}
/*
@@ -361,7 +536,8 @@ int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
*/
rtems_hdl_tbl[irq->name] = default_rtems_entry;
- _CPU_ISR_Enable(level);
+
+ rtems_interrupt_enable(level);
return 1;
}
@@ -372,8 +548,9 @@ int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
{
- int i;
unsigned int level;
+ int i;
+
/*
* Store various code accelerators
*/
@@ -381,51 +558,17 @@ int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
default_rtems_entry = config->defaultEntry;
rtems_hdl_tbl = config->irqHdlTbl;
- _CPU_ISR_Disable(level);
- compute_GT64260int_masks_from_prio();
+ rtems_interrupt_disable(level);
- /*
- * set up internal tables used by rtems interrupt prologue
- */
- /*
- * start with MAIN CPU IRQ
- */
- for (i=BSP_MICL_IRQ_LOWEST_OFFSET; i < BSP_GPP_IRQ_LOWEST_OFFSET ; i++) {
- if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
- BSP_enable_main_irq(i);
- rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
- }
- else {
- rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
- BSP_disable_main_irq(i);
- }
- }
- /*
- * continue with external IRQ
- */
- for (i=BSP_GPP_IRQ_LOWEST_OFFSET; i<BSP_PROCESSOR_IRQ_LOWEST_OFFSET; i++) {
- if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
- BSP_enable_gpp_irq(i);
- rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
- }
- else {
- rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
- BSP_disable_gpp_irq(i);
- }
+ if ( !BSP_setup_the_pic() ) {
+ printk("PIC setup failed; leaving IRQs OFF\n");
+ return 0;
}
- /*
- * finish with Processor exceptions handled like IRQ
- */
- for (i=BSP_PROCESSOR_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_MAX_OFFSET+1; i++) {
- if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
- rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
- }
- else {
- rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
- }
- }
- _CPU_ISR_Enable(level);
+ for (i= BSP_MAIN_GPP7_0_IRQ; i <= BSP_MAIN_GPP31_24_IRQ; i++)
+ BSP_enable_pic_irq(i);
+
+ rtems_interrupt_enable(level);
return 1;
}
@@ -435,85 +578,74 @@ int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config)
return 0;
}
-int _BSP_vme_bridge_irq = -1;
-
/*
* High level IRQ handler called from shared_raw_irq_code_entry
*/
+
void C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum)
{
- register unsigned msr;
- register unsigned new_msr;
- unsigned mainCause[2];
- register unsigned selectCause;
- register unsigned oldMask[2]={0,0};
- unsigned i, regNum, irq, bitNum, startIrqNum=0;
+ register unsigned msr, new_msr;
+ unsigned long irqCause[3]={0, 0,0};
+ register unsigned long selectCause;
+ unsigned oldMask[3]={0,0,0};
+ register unsigned i=0, j, irq=0, bitmask=0, group=0;
if (excNum == ASM_DEC_VECTOR) {
- _CPU_MSR_GET(msr);
+ _MSR_GET(msr);
new_msr = msr | MSR_EE;
- _CPU_MSR_SET(new_msr);
+ _MSR_SET(new_msr);
rtems_hdl_tbl[BSP_DECREMENTER].hdl(rtems_hdl_tbl[BSP_DECREMENTER].handle);
- _CPU_MSR_SET(msr);
+ _MSR_SET(msr);
return;
}
- selectCause = inl( GT_CPU_SEL_CAUSE);
- if (selectCause & HI_INT_CAUSE ) {
- mainCause[1]= selectCause & inl(GT_CPU_INT_MASK_HI);
- startIrqNum=32;
+
+ for (j=0; j<3; j++ ) oldMask[j] = BSP_irqMask_cache[j];
+
+ if ((selectCause= in_le32((volatile unsigned *)0xf1000c70)) & HI_INT_CAUSE ){
+ irqCause[1] = (selectCause & BSP_irqMask_cache[1]);
+ irqCause[2] = in_le32(BSP_irqCause_reg[2]) & BSP_irqMask_cache[2];
}
else {
- mainCause[0] =inl(GT_MAIN_INT_CAUSE_LO)&inl(GT_CPU_INT_MASK_LO);
- mainCause[1] =inl(GT_MAIN_INT_CAUSE_HI)&inl(GT_CPU_INT_MASK_HI);
+ irqCause[0] = (selectCause & BSP_irqMask_cache[0]);
+ if ((irqCause[1] =(in_le32((volatile unsigned *)0xf1000c68)&BSP_irqMask_cache[1])))
+ irqCause[2] = in_le32(BSP_irqCause_reg[2]) & BSP_irqMask_cache[2];
}
-
-#if 0
- /* very bad practice to put printk here, use only if for debug */
- printk("main 0 %x, main 1 %x \n", mainCause[0],mainCause[1]);
+
+ while ((irq = picIsrTable[i++])!=-1)
+ {
+ if (irqCause[group=(irq/32)] && (irqCause[group]&(bitmask=(1<<(irq % 32))))) {
+ for (j=0; j<3; j++)
+ BSP_irqMask_cache[j] &= (~ BSP_irq_prio_mask_tbl[j][irq]);
+
+ RTEMS_COMPILER_MEMORY_BARRIER();
+ out_le32((volatile unsigned *)0xf1000c1c, BSP_irqMask_cache[0]);
+ out_le32((volatile unsigned *)0xf1000c6c, BSP_irqMask_cache[1]);
+ out_le32((volatile unsigned *)0xf100f10c, BSP_irqMask_cache[2]);
+ in_le32((volatile unsigned *)0xf100f10c);
+
+#ifdef EDGE_TRIGGER
+ if (irq > BSP_MICH_IRQ_MAX_OFFSET)
+ out_le32(BSP_irqCause_reg[2], ~bitmask);/* Till Straumann: Ack the edge triggered GPP IRQ */
#endif
- oldMask[0]= GT_MAINirqLO_cache;
- oldMask[1]= GT_MAINirqHI_cache;
-
- for (i=0;mainIrqTbl[i]!=-1;i++) {
- irq=mainIrqTbl[i];
- if ( irq < startIrqNum ) continue;
- regNum = irq/32;
- bitNum = irq % 32;
- if ( mainCause[regNum] & (1<<bitNum)) {
- GT_MAINirqLO_cache=oldMask[0]&(~irq_prio_maskLO_tbl[irq]);
- outl(GT_MAINirqLO_cache, GT_CPU_INT_MASK_LO);
- __asm __volatile("sync");
- GT_MAINirqHI_cache=oldMask[1]&(~irq_prio_maskHI_tbl[irq]);
- outl(GT_MAINirqHI_cache, GT_CPU_INT_MASK_HI);
- __asm __volatile("sync");
-
- /* <skf> It seems that reading back is necessary to ensure the
- * interrupt mask updated. Otherwise, spurious interrupt will
- * happen. However, I do not want to use "while loop" to risk
- * the CPU stuck. I wound rather keep track of the interrupt
- * mask if not updated.
- */
- if (((irqLOW[irqIndex]= inl(GT_CPU_INT_MASK_LO))!=GT_MAINirqLO_cache)||
- ((irqHIGH[irqIndex]= inl(GT_CPU_INT_MASK_HI))!=GT_MAINirqHI_cache)){
- irqIndex++;
- irqIndex %=20;
- irqCAUSE[irqIndex] = irq;
- }
- _CPU_MSR_GET(msr);
+
+ _MSR_GET(msr);
new_msr = msr | MSR_EE;
- _CPU_MSR_SET(new_msr);
+ _MSR_SET(new_msr);
rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle);
- _CPU_MSR_SET(msr);
+ _MSR_SET(msr);
+
+ for (j=0; j<3; j++ ) BSP_irqMask_cache[j] = oldMask[j];
break;
}
}
- GT_MAINirqLO_cache=oldMask[0];
- outl(GT_MAINirqLO_cache, GT_CPU_INT_MASK_LO);
- GT_MAINirqHI_cache=oldMask[1];
- outl(GT_MAINirqHI_cache, GT_CPU_INT_MASK_HI);
+
+ out_le32((volatile unsigned *)0xf1000c1c, oldMask[0]);
+ out_le32((volatile unsigned *)0xf1000c6c, oldMask[1]);
+ out_le32((volatile unsigned *)0xf100f10c, oldMask[2]);
+ in_le32((volatile unsigned *)0xf100f10c);
}
void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx)
@@ -535,10 +667,15 @@ void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx)
*/
}
-void BSP_printIRQMask()
+/* Only print part of the entries for now */
+void BSP_printPicIsrTbl()
{
int i;
- for (i=0; i< 20; i++)
- printk("IRQ%d : 0x%x %x \n", irqCAUSE[i], irqHIGH[i],irqLOW[i]);
+ printk("picIsrTable[12]={");
+ for (i=0; i<12; i++)
+ printk("%d,", picIsrTable[i]);
+ printk("}\n");
+
+ printk("GPPIrqInTbl: 0x%x :\n", GPPIrqInTbl);
}
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/irq/irq.h b/c/src/lib/libbsp/powerpc/mvme5500/irq/irq.h
index e89ddf3220..9b7c21367e 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/irq/irq.h
+++ b/c/src/lib/libbsp/powerpc/mvme5500/irq/irq.h
@@ -15,12 +15,13 @@
* found in found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
- * Copyright 2004, Brookhaven National Laboratory and
+ * Copyright 2004, 2005 Brookhaven National Laboratory and
* Shuchen Kate Feng <feng1@bnl.gov>
*
* - modified shared/irq/irq.h for Mvme5500 (no ISA devices/PIC)
* - Discovery GT64260 interrupt controller instead of 8259.
* - Added support for software IRQ priority levels.
+ * - modified to optimize the IRQ latency and handling
*
* $Id$
*/
@@ -28,13 +29,14 @@
#ifndef LIBBSP_POWERPC_MVME5500_IRQ_IRQ_H
#define LIBBSP_POWERPC_MVME5500_IRQ_IRQ_H
+/*#define BSP_SHARED_HANDLER_SUPPORT 1*/
#include <rtems/irq.h>
#define BSP_ASM_IRQ_VECTOR_BASE 0x0
#ifndef ASM
-#define DynamicIrqTbl 1
+#define OneTierIrqPrioTbl 1
/*
* Symbolic IRQ names and related definitions.
@@ -83,7 +85,8 @@
* Summary
*/
#define BSP_IRQ_NUMBER (BSP_MISC_IRQ_MAX_OFFSET + 1)
-#define BSP_MAIN_IRQ_NUMBER (64)
+#define BSP_MAIN_IRQ_NUMBER (64)
+#define BSP_PIC_IRQ_NUMBER (96)
#define BSP_LOWEST_OFFSET (BSP_MICL_IRQ_LOWEST_OFFSET)
#define BSP_MAX_OFFSET (BSP_MISC_IRQ_MAX_OFFSET)
@@ -109,6 +112,7 @@
#define BSP_MAIN_GPP31_24_IRQ (BSP_MICH_IRQ_LOWEST_OFFSET+27)
/* on the MVME5500, these are the GT64260B external GPP0 interrupt */
+#define BSP_PCI_IRQ_LOWEST_OFFSET (BSP_GPP_IRQ_LOWEST_OFFSET)
#define BSP_UART_COM2_IRQ (BSP_GPP_IRQ_LOWEST_OFFSET)
#define BSP_UART_COM1_IRQ (BSP_GPP_IRQ_LOWEST_OFFSET)
#define BSP_GPP8_IRQ_OFFSET (BSP_GPP_IRQ_LOWEST_OFFSET+8)
@@ -129,29 +133,7 @@
*/
#define BSP_DECREMENTER (BSP_PROCESSOR_IRQ_LOWEST_OFFSET)
-typedef unsigned int rtems_GTirq_masks;
-
-extern rtems_GTirq_masks GT_GPPirq_cache;
-extern rtems_GTirq_masks GT_MAINirqLO_cache, GT_MAINirqHI_cache;
-
-void BSP_enable_main_irq(unsigned irqNum);
-void BSP_disable_main_irq(unsigned irqNum);
-void BSP_enable_gpp_irq(unsigned irqNum);
-void BSP_disable_gpp_irq(unsigned irqNum);
-
extern void BSP_rtems_irq_mng_init(unsigned cpuId);
-extern int gpp_int_error;
-#if DynamicIrqTbl
-extern int MainIrqTblPtr;
-extern unsigned long long MainIrqInTbl;
-extern unsigned char GPPinMainIrqTbl[4];
-#endif
-extern unsigned int mainIrqTbl[64];
-extern unsigned int GPP7_0IrqTbl[8];
-extern unsigned int GPP15_8IrqTbl[8];
-extern unsigned int GPP23_16IrqTbl[8];
-extern unsigned int GPP31_24IrqTbl[8];
#endif
-
#endif
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/irq/irq_init.c b/c/src/lib/libbsp/powerpc/mvme5500/irq/irq_init.c
index 6ebee01fa1..0902383d41 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/irq/irq_init.c
+++ b/c/src/lib/libbsp/powerpc/mvme5500/irq/irq_init.c
@@ -5,16 +5,13 @@
*
* CopyRight (C) 1999 valette@crf.canon.fr
*
- * Special acknowledgement to Till Straumann <strauman@slac.stanford.edu>
- * for providing inputs to the IRQ optimization.
- *
* Modified and added support for the MVME5500.
- * Copyright 2003, 2004, Brookhaven National Laboratory and
+ * Copyright 2003, 2004, 2005, Brookhaven National Laboratory and
* Shuchen Kate Feng <feng1@bnl.gov>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
+ * http://www.rtems.com/license/LICENSE
*
*/
#include <libcpu/io.h>
@@ -22,14 +19,12 @@
#include <bsp/irq.h>
#include <bsp.h>
#include <libcpu/raw_exception.h> /* ASM_EXT_VECTOR, ASM_DEC_VECTOR ... */
+/*#define TRACE_IRQ_INIT*/
extern unsigned int external_exception_vector_prolog_code_size[];
extern void external_exception_vector_prolog_code();
extern unsigned int decrementer_exception_vector_prolog_code_size[];
extern void decrementer_exception_vector_prolog_code();
-extern void GT_GPP_IntHandler0(), GT_GPP_IntHandler1();
-extern void GT_GPP_IntHandler2(), GT_GPP_IntHandler3();
-extern void BSP_GT64260INT_init();
/*
* default on/off function
@@ -47,116 +42,49 @@ static int connected() {return 1;}
static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER];
static rtems_irq_global_settings initial_config;
static rtems_irq_connect_data defaultIrq = {
- /* vectorIdex, hdl , handle , on , off , isOn */
- 0, nop_func , NULL , nop_func , nop_func , not_connected
+ /* vectorIdex, hdl , handle , on , off , isOn */
+ 0, nop_func , NULL , nop_func , nop_func , not_connected
};
-rtems_irq_prio BSPirqPrioTable[BSP_MAIN_IRQ_NUMBER]={
+rtems_irq_prio BSPirqPrioTable[BSP_PIC_IRQ_NUMBER]={
/*
* This table is where the developers can change the levels of priority
* based on the need of their applications.
*
- * actual priorities for CPU MAIN interrupts 0-63:
+ * actual priorities for CPU MAIN and GPP interrupts (0-95)
+ *
* 0 means that only current interrupt is masked (lowest priority)
- * 255 means all other interrupts are masked
+ * 255 is only used by bits 24, 25, 26 and 27 of the CPU high
+ * interrupt Mask: (e.g. GPP7_0, GPP15_8, GPP23_16, GPP31_24).
+ * The IRQs of those four bits are always enabled. When it's used,
+ * the IRQ number is never listed in the dynamic picIsrTable[96].
+ *
+ * The priorities of GPP interrupts were decided by their own
+ * value set at BSPirqPrioTable.
+ *
*/
/* CPU Main cause low interrupt */
/* 0-15 */
- 0, 0, 0, 0, 0, 0, 0, 0, 4/*Timer*/, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 64/*Timer*/, 0, 0, 0, 0, 0, 0, 0,
/* 16-31 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* CPU Main cause high interrupt */
/* 32-47 */
- 1/*10/100MHZ*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2/*10/100MHz*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 48-63 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0/*serial*/, 3/*VME*/, 2/*1GHZ*/, 5/*WD*/, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 255 /*GPP0-7*/, 255/*GPP8-15*/, 255/*GPP16-23*/, 255/*GPP24-31*/, 0, 0, 0, 0,
+ /* GPP interrupts */
+ /* GPP0-7 */
+ 1/*serial*/,0, 0, 0, 0, 0, 0, 0,
+ /* GPP8-15 */
+ 47/*PMC1A*/,46/*PMC1B*/,45/*PMC1C*/,44/*PMC1D*/,30/*VME0*/, 29/*VME1*/,3,1,
+ /* GPP16-23 */
+ 37/*PMC2A*/,36/*PMC2B*/,35/*PMC2C*/,34/*PMC2D*/,23/*1GHz*/, 0,0,0,
+ /* GPP24-31 */
+ 7/*watchdog*/, 0,0,0,0,0,0,0
};
-/* The mainIrqTbl[64] lists the enabled CPU main interrupt
- * numbers [0-63] starting from the highest priority one
- * to the lowest priority one.
- *
- * The highest priority interrupt is located at mainIrqTbl[0], and
- * the lowest priority interrupt is located at
- * mainIrqTbl[MainIrqTblPtr-1].
- */
-
-#if DynamicIrqTbl
-/* The mainIrqTbl[64] is updated dynamically based on the priority
- * levels set at BSPirqPrioTable[64], as the BSP_enable_main_irq() and
- * BSP_disable_main_irq() commands are invoked.
- *
- * Caveat: The eight GPP IRQs for each BSP_MAIN_GPPx_y_IRQ group are set
- * at the same main priority in the BSPirqPrioTable, while the
- * sub-priority levels for the eight GPP in each group are sorted
- * statically by developers in the GPPx_yIrqTbl[8] from the highest
- * priority to the lowest one.
- */
-int MainIrqTblPtr=0;
-unsigned long long MainIrqInTbl=0;
-unsigned char GPPinMainIrqTbl[4]={0,0,0,0};
-/* BitNums for Main Interrupt Lo/High Cause, -1 means invalid bit */
-unsigned int mainIrqTbl[BSP_MAIN_IRQ_NUMBER]={
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1};
-#else
-/* Pre-sorted for IRQ optimization, and prioritization
- * The interrupts sorted are :
-
- 1. Watchdog timer (GPP #25)
- 2. Timers 0-1 (Main interrupt low cause, bit 8)
- 3. VME interrupt (GPP #12)
- 4. 1 GHZ ethernet (GPP #20)
- 5. 10/100 MHZ ethernet (Main interrupt high cause, bit 0)
- 6. COM1/COM2 (GPP #0)
-
-*/
-/* BitNums for Main Interrupt Lo/High Cause, -1 means invalid bit */
-unsigned int mainIrqTbl[64]={ BSP_MAIN_GPP31_24_IRQ, /* 59:watchdog timer */
- BSP_MAIN_TIMER0_1_IRQ, /* 8:Timers 0-1 */
- BSP_MAIN_GPP15_8_IRQ, /* 57:VME interrupt */
- BSP_MAIN_GPP23_16_IRQ, /* 58: 1 GHZ ethernet */
- BSP_MAIN_ETH0_IRQ, /* 32:10/100 MHZ ethernet */
- BSP_MAIN_GPP7_0_IRQ, /* 56:COM1/COM2 */
- -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1};
-#endif
-
-unsigned int GPP7_0IrqTbl[8]={0, /* COM1/COM2 */
- -1, -1, -1, -1, -1, -1, -1};
-unsigned int GPP15_8IrqTbl[8]={ 4, 5, 6, 7, /* VME interrupt 0-3 */
- 0, 1, 2, 3 /* PMC1 INT A, B, C, D */};
-unsigned int GPP23_16IrqTbl[8]={4, /* 82544 1GHZ ethernet (20-16=4)*/
- 0, 1, 2, 3, /* PMC2 INT A, B, C, D */
- -1, -1, -1};
-unsigned int GPP31_24IrqTbl[8]={1, /* watchdog timer (25-24=1) */
- -1, -1, -1, -1, -1, -1, -1};
-
-static int
-doit(unsigned intNum, rtems_irq_hdl handler, int (*p)(const rtems_irq_connect_data*))
-{
- rtems_irq_connect_data d={0};
- d.name = intNum;
- d.isOn = connected;
- d.hdl = handler;
- return p(&d);
-}
-
-int BSP_GT64260_install_isr(unsigned intNum,rtems_irq_hdl handler)
-{
- return doit(intNum, handler, BSP_install_rtems_irq_handler);
-}
-
/*
* This code assumes the exceptions management setup has already
* been done. We just need to replace the exceptions that will
@@ -174,7 +102,6 @@ void BSP_rtems_irq_mng_init(unsigned cpuId)
#ifdef TRACE_IRQ_INIT
printk("Initializing the interrupt controller of the GT64260\n");
#endif
- BSP_GT64260INT_init();
#ifdef TRACE_IRQ_INIT
printk("Going to re-initialize the rtemsIrq table %d\n",BSP_IRQ_NUMBER);
@@ -186,8 +113,8 @@ void BSP_rtems_irq_mng_init(unsigned cpuId)
* re-init the rtemsIrq table
*/
for (i = 0; i < BSP_IRQ_NUMBER; i++) {
- rtemsIrq[i] = defaultIrq;
- rtemsIrq[i].name = i;
+ rtemsIrq[i] = defaultIrq;
+ rtemsIrq[i].name = i;
}
/*
@@ -209,13 +136,10 @@ void BSP_rtems_irq_mng_init(unsigned cpuId)
*/
BSP_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
}
+#ifdef TRACE_IRQ_INIT
+ printk("Done setup irq mngt configuration\n");
+#endif
- /* Connect the GPP int handler to each of the associated main cause bits */
- BSP_GT64260_install_isr(BSP_MAIN_GPP7_0_IRQ, GT_GPP_IntHandler0); /* COM1 & COM2, .... */
- BSP_GT64260_install_isr(BSP_MAIN_GPP15_8_IRQ, GT_GPP_IntHandler1);
- BSP_GT64260_install_isr(BSP_MAIN_GPP23_16_IRQ, GT_GPP_IntHandler2);
- BSP_GT64260_install_isr(BSP_MAIN_GPP31_24_IRQ, GT_GPP_IntHandler3);
-
/*
* We must connect the raw irq handler for the two
* expected interrupt sources : decrementer and external interrupts.
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/GT64260eth.c b/c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/GT64260eth.c
new file mode 100644
index 0000000000..8ef16ce120
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/GT64260eth.c
@@ -0,0 +1,1575 @@
+/* GT64260eth.c : GT64260 10/100 Mb ethernet MAC driver
+ *
+ * Copyright (c) 2003,2004 Brookhaven National Laboratory
+ * S. Kate Feng <feng1@bnl.gov>
+ * All rights reserved
+ *
+ * Acknowledgements:
+ * netBSD : Copyright (c) 2002 Allegro Networks, Inc., Wasabi Systems, Inc.
+ * Marvell : NDA document for the discovery system controller
+ * The author referenced two RTEMS network drivers of other NICs.
+ * rtems : 1) dec21140.c, a network driver for for TULIP based Ethernet Controller
+ * (C) 1999 Emmanuel Raguet. raguet@crf.canon.fr
+ *
+ * 2) yellowfin.c, a network driver for the SVGM5 BSP.
+ * Stanford Linear Accelerator Center, Till Straumann
+ *
+ * Some notes from the author, S. Kate Feng :
+ *
+ * 1) Mvme5500 uses Eth0 (controller 0) of the GT64260 to implement
+ * the 10/100 BaseT Ethernet with PCI Master Data Byte Swap\
+ * control.
+ * 2) Implemented hardware snoop instead of software snoop
+ * to ensure SDRAM cache coherency. (Copyright : NDA item)
+ * 3) Added S/W support for multi mbuf. (TODO : Let the H/W do it)
+ *
+ */
+#define BYTE_ORDER BIG_ENDIAN
+
+#define INET
+
+#include <rtems.h>
+#include <rtems/bspIo.h> /* printk */
+#include <stdio.h> /* printf for statistics */
+#include <string.h>
+
+#include <libcpu/io.h> /* inp & friends */
+#include <libcpu/spr.h> /* registers.h is included here */
+#include <bsp.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#include <rtems/rtems_bsdnet.h>
+#include <rtems/rtems_bsdnet_internal.h>
+#include <rtems/error.h>
+#include <errno.h>
+
+#include <rtems/rtems/types.h>
+
+#include <sys/queue.h>
+
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sockio.h> /* SIOCADDMULTI, SIOC... */
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#ifdef INET
+#include <netinet/in_var.h>
+#endif
+
+#include <bsp/irq.h>
+#include <bsp/GT64260ethreg.h>
+#include <bsp/GT64260eth.h>
+#include <bsp/VPD.h>
+
+#define GT_ETH_TASK_NAME "Geth"
+#define PKT_BUF_SZ 1536
+#define SOFTC_ALIGN 31
+#define HASH_ALIGN 15
+
+#define TXQ_HiLmt_OFF 2
+
+/* <skf>
+ * 1. printk debug is for diagnosis only, which may cause
+ * unexpected result, especially if txq is under heavy load
+ * because CPU is fast with a decent cache.
+ */
+#define GTeth_debug 0
+#define GTeth_rx_debug 0
+
+#if 0
+#define GE_FORGOT
+#define GE_NORX
+#define GT_DEBUG
+#endif
+
+/* RTEMS event to kill the daemon */
+#define KILL_EVENT RTEMS_EVENT_1
+/* RTEMS event to (re)start the transmitter */
+#define START_TRANSMIT_EVENT RTEMS_EVENT_2
+/* RTEMS events used by the ISR */
+#define RX_EVENT RTEMS_EVENT_3
+#define TX_EVENT RTEMS_EVENT_4
+#define ERR_EVENT RTEMS_EVENT_5
+
+#define ALL_EVENTS (KILL_EVENT|START_TRANSMIT_EVENT|RX_EVENT|TX_EVENT|ERR_EVENT)
+
+enum GTeth_whack_op {
+ GE_WHACK_START, GE_WHACK_RESTART,
+ GE_WHACK_CHANGE, GE_WHACK_STOP
+};
+
+enum GTeth_hash_op {
+ GE_HASH_ADD, GE_HASH_REMOVE,
+};
+
+#define ET_MINLEN 64 /* minimum message length */
+
+static int GTeth_ifioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
+static void GTeth_ifstart (struct ifnet *);
+static void GTeth_ifchange(struct GTeth_softc *sc);
+static void GTeth_init_rx_ring(struct GTeth_softc *sc);
+static void GT64260eth_daemon(void *arg);
+static int GT64260eth_sendpacket(struct GTeth_softc *sc,struct mbuf *m);
+static unsigned GTeth_txq_done(struct GTeth_softc *sc);
+static void GTeth_tx_cleanup(struct GTeth_softc *sc);
+static void GTeth_tx_start(struct GTeth_softc *sc);
+static void GTeth_tx_stop(struct GTeth_softc *sc);
+static void GTeth_rx_cleanup(struct GTeth_softc *sc);
+static int GT64260eth_rx(struct GTeth_softc *sc);
+static void GTeth_rx_setup(struct GTeth_softc *sc);
+static void GTeth_rxprio_setup(struct GTeth_softc *sc);
+static void GTeth_rx_stop(struct GTeth_softc *dc);
+static void GT64260eth_isr();
+static int GTeth_hash_compute(struct GTeth_softc *sc,unsigned char eaddr[ETHER_ADDR_LEN]);
+static int GTeth_hash_entry_op(struct GTeth_softc *sc, enum GTeth_hash_op op,
+ enum GTeth_rxprio prio,unsigned char eaddr[ETHER_ADDR_LEN]);
+
+static int GTeth_hash_fill(struct GTeth_softc *sc);
+static void GTeth_hash_init(struct GTeth_softc *sc);
+
+static struct GTeth_softc *root_GT64260eth_dev = NULL;
+
+static void GT64260eth_irq_on(const rtems_irq_connect_data *irq)
+{
+ struct GTeth_softc *sc;
+
+ for (sc= root_GT64260eth_dev; sc; sc= sc-> next_module) {
+ outl(0x30883444,ETH0_EIMR); /* MOTLoad default interrupt mask */
+ return;
+ }
+}
+
+static void GT64260eth_irq_off(const rtems_irq_connect_data *irq)
+{
+ struct GTeth_softc *sc;
+
+ for (sc= root_GT64260eth_dev; sc; sc= sc-> next_module)
+ outl(0, ETH0_EIMR);
+}
+
+static int GT64260eth_irq_is_on(const rtems_irq_connect_data *irq)
+{
+ return(inl(ETH0_EICR) & ETH_IR_EtherIntSum);
+}
+
+static void GT64260eth_isr()
+{
+ struct GTeth_softc *sc = root_GT64260eth_dev;
+ rtems_event_set events=0;
+ uint32_t cause;
+
+
+ cause = inl(ETH0_EICR);
+ outl( ~cause,ETH0_EICR); /* clear the ICR */
+
+ if ( (!cause) || (cause & 0x803d00)) {
+ sc->intr_errsts[sc->intr_err_ptr2++]=cause;
+ sc->intr_err_ptr2 %=INTR_ERR_SIZE; /* Till Straumann */
+ events |= ERR_EVENT;
+ }
+
+ /* ETH_IR_RxBuffer_3|ETH_IR_RxError_3 */
+ if (cause & 0x880000) {
+ sc->stats.rxInterrupts++;
+ events |= RX_EVENT;
+ }
+ /* If there is an error, we want to continue to next descriptor */
+ /* ETH_IR_TxBufferHigh|ETH_IR_TxEndHigh|ETH_IR_TxErrorHigh */
+ if (cause & 0x444) {
+ sc->stats.txInterrupts++;
+ events |= TX_EVENT;
+ /* It seems to be unnecessary. However, it's there
+ * to be on the safe side due to the datasheet.
+ * So far, it does not seem to affect the network performance
+ * based on the EPICS catime.
+ */
+ /* ETH_ESDCMR_TXDH | ETH_ESDCMR_ERD = 0x800080 */
+ if ((sc->txq_nactive > 1)&& ((inl(ETH0_ESDCMR)&ETH_ESDCMR_TXDH)==0))
+ outl(0x800080,ETH0_ESDCMR);
+
+
+ }
+ rtems_event_send(sc->daemonTid, events);
+}
+
+static rtems_irq_connect_data GT64260ethIrqData={
+ BSP_MAIN_ETH0_IRQ,
+ (rtems_irq_hdl) GT64260eth_isr,
+ NULL,
+ (rtems_irq_enable) GT64260eth_irq_on,
+ (rtems_irq_disable) GT64260eth_irq_off,
+ (rtems_irq_is_enabled) GT64260eth_irq_is_on,
+};
+
+static void GT64260eth_init_hw(struct GTeth_softc *sc)
+{
+
+#ifdef GT_DEBUG
+ printk("GT64260eth_init_hw(");
+#endif
+ /* Kate Feng : Turn the hardware snoop on as MOTLoad did not have
+ * it on by default.
+ */
+ outl(RxBSnoopEn|TxBSnoopEn|RxDSnoopEn|TxDSnoopEn, GT_CUU_Eth0_AddrCtrlLow);
+ outl(HashSnoopEn, GT_CUU_Eth0_AddrCtrlHigh);
+
+ sc->rxq_intrbits=0;
+ sc->sc_flags=0;
+
+#ifndef GE_NORX
+ GTeth_rx_setup(sc);
+#endif
+
+#ifndef GE_NOTX
+ GTeth_tx_start(sc);
+#endif
+
+ sc->sc_pcr |= ETH_EPCR_HS_512;
+ outl(sc->sc_pcr, ETH0_EPCR);
+ outl(sc->sc_pcxr, ETH0_EPCXR); /* port config. extended reg. */
+ outl(0, ETH0_EICR); /* interrupt cause register */
+ outl(sc->sc_intrmask, ETH0_EIMR);
+#ifndef GE_NOHASH
+ /* Port Hash Table Pointer Reg*/
+ outl(((unsigned) sc->sc_hashtable),ETH0_EHTPR);
+#endif
+#ifndef GE_NORX
+ outl(ETH_ESDCMR_ERD,ETH0_ESDCMR); /* enable Rx DMA in SDMA Command Register */
+ sc->sc_flags |= GE_RXACTIVE;
+#endif
+#ifdef GT_DEBUG
+ printk("SDCMR 0x%x ", inl(ETH0_ESDCMR));
+#endif
+
+ /* connect the interrupt handler which should
+ * take care of enabling interrupts
+ */
+ if (!BSP_install_rtems_irq_handler(&GT64260ethIrqData))
+ printk("GT64260eth: unable to install ISR");
+
+ /* The ethernet port is ready to transmit/receive */
+ outl(sc->sc_pcr | ETH_EPCR_EN, ETH0_EPCR);
+
+#ifdef GT_DEBUG
+ printk(")\n");
+#endif
+}
+
+static void GT64260eth_stop_hw(struct GTeth_softc *sc)
+{
+
+ printk("GT64260eth_stop_hw(");
+
+ /* remove our interrupt handler which will also
+ * disable interrupts at the MPIC and the device
+ * itself
+ */
+ if (!BSP_remove_rtems_irq_handler(&GT64260ethIrqData))
+ printk("GT64260eth: unable to remove IRQ handler!");
+
+ outl(sc->sc_pcr, ETH0_EPCR);
+ outl(0, ETH0_EIMR);
+
+ sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
+#ifndef GE_NOTX
+ GTeth_tx_stop(sc);
+#endif
+#ifndef GE_NORX
+ GTeth_rx_stop(sc);
+#endif
+ sc->sc_hashtable = NULL;
+ if (GTeth_debug>0) printk(")");
+}
+
+static void GT64260eth_stop(struct GTeth_softc *sc)
+{
+ if (GTeth_debug>0) printk("GT64260eth_stop(");
+
+ /* The hardware is shutdown in the daemon */
+ /* kill the daemon. We also must release the networking
+ * semaphore or there'll be a deadlock...
+ */
+ rtems_event_send(sc->daemonTid, KILL_EVENT);
+ rtems_bsdnet_semaphore_release();
+
+ sc->daemonTid=0;
+ /* now wait for it to die */
+ rtems_semaphore_obtain(sc->daemonSync,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
+
+ /* reacquire the bsdnet semaphore */
+ rtems_bsdnet_semaphore_obtain();
+ if (GTeth_debug>0) printk(")");
+}
+
+static void GT64260eth_ifinit(void *arg)
+{
+ struct GTeth_softc *sc = (struct GTeth_softc*)arg;
+ int i;
+
+#ifdef GT_DEBUG
+ printk("GT64260eth_ifinit(): daemon ID: 0x%08x)\n", sc->daemonTid);
+#endif
+ if (sc->daemonTid) {
+#ifdef GT_DEBUG
+ printk("GT64260eth: daemon already up, doing nothing\n");
+#endif
+ return;
+ }
+
+#ifndef GE_NOHASH
+ /* Mvme5500, the user must initialize the hash table before enabling the
+ * Ethernet controller
+ */
+ GTeth_hash_init(sc);
+ GTeth_hash_fill(sc);
+#endif
+
+ sc->intr_err_ptr1=0;
+ sc->intr_err_ptr2=0;
+ for (i=0; i< INTR_ERR_SIZE; i++) sc->intr_errsts[i]=0;
+
+ /* initialize the hardware (we are holding the network semaphore at this point) */
+ (void)GT64260eth_init_hw(sc);
+
+ /* launch network daemon */
+
+ /* NOTE:
+ * in ss-20011025 (and later) any task created by 'bsdnet_newproc' is
+ * wrapped by code which acquires the network semaphore...
+ */
+ sc->daemonTid = rtems_bsdnet_newproc(GT_ETH_TASK_NAME,4096,GT64260eth_daemon,arg);
+
+ /* Tell the world that we're running */
+ sc->arpcom.ac_if.if_flags |= IFF_RUNNING;
+
+}
+
+/* attach parameter tells us whether to attach or to detach the driver */
+/* Attach this instance, and then all the sub-devices */
+int rtems_GT64260eth_driver_attach(struct rtems_bsdnet_ifconfig *config, int attach)
+{
+ struct GTeth_softc *sc;
+ struct ifnet *ifp;
+ unsigned sdcr, data;
+ unsigned char hwaddr[6];
+ int i, unit, phyaddr;
+ void *softc_mem;
+ char *name;
+
+ unit = rtems_bsdnet_parse_driver_name(config, &name);
+ if (unit < 0) return 0;
+
+ printk("\nEthernet driver name %s unit %d \n",name, unit);
+ printk("(c) 2004, Brookhaven National Lab. <feng1@bnl.gov> (RTEMS/mvme5500 port)\n");
+
+ /* Make certain elements e.g. descriptor lists are aligned. */
+ softc_mem = rtems_bsdnet_malloc(sizeof(*sc) + SOFTC_ALIGN, M_FREE, M_NOWAIT);
+
+ /* Check for the very unlikely case of no memory. */
+ if (softc_mem == NULL)
+ printk("GT64260eth: OUT OF MEMORY");
+
+ sc = (void *)(((long)softc_mem + SOFTC_ALIGN) & ~SOFTC_ALIGN);
+ memset(sc, 0, sizeof(*sc));
+
+ if (GTeth_debug>0) printk("txq_desc[0] addr:%x, rxq_desc[0] addr:%x, sizeof sc %d\n",&sc->txq_desc[0], &sc->rxq_desc[0], sizeof(*sc));
+
+ sc->sc_macno = unit-1;
+
+ data = inl(ETH_EPAR);
+ phyaddr = ETH_EPAR_PhyAD_GET(data, sc->sc_macno);
+
+ /* try to read HW address from the device if not overridden
+ * by config
+ */
+ if (config->hardware_address) {
+ memcpy(hwaddr, config->hardware_address, ETHER_ADDR_LEN);
+ } else {
+ printk("Read EEPROM ");
+ for (i = 0; i < 6; i++)
+ hwaddr[i] = ConfVPD_buff[VPD_ENET0_OFFSET+i];
+ }
+
+#ifdef GT_DEBUG
+ printk("using MAC addr from device:");
+ for (i = 0; i < ETHER_ADDR_LEN; i++) printk("%x:", hwaddr[i]);
+ printk("\n");
+#endif
+
+ memcpy(sc->arpcom.ac_enaddr, hwaddr, ETHER_ADDR_LEN);
+
+ ifp = &sc->arpcom.ac_if;
+
+ sc->sc_pcr = inl(ETH0_EPCR);
+ sc->sc_pcxr = inl(ETH0_EPCXR);
+ sc->sc_intrmask = inl(ETH0_EIMR) | ETH_IR_MIIPhySTC;
+
+ printk("address %s\n", ether_sprintf(hwaddr));
+
+#ifdef GT_DEBUG
+ printk(", pcr %x, pcxr %x ", sc->sc_pcr, sc->sc_pcxr);
+#endif
+
+
+ sc->sc_pcxr |= ETH_EPCXR_PRIOrx_Override;
+ sc->sc_pcxr |= (3<<6); /* highest priority only */
+ sc->sc_pcxr &= ~ETH_EPCXR_RMIIEn; /* MII mode */
+
+ /* Max. Frame Length (packet) allowed for reception is 1536 bytes,
+ * instead of 2048 (MOTLoad default) or 64K.
+ */
+ sc->sc_pcxr &= ~(3 << 14);
+ sc->sc_pcxr |= (ETH_EPCXR_MFL_1536 << 14);
+ sc->sc_max_frame_length = PKT_BUF_SZ;
+
+
+ if (sc->sc_pcr & ETH_EPCR_EN) {
+ int tries = 1000;
+ /* Abort transmitter and receiver and wait for them to quiese*/
+ outl(ETH_ESDCMR_AR|ETH_ESDCMR_AT,ETH0_ESDCMR);
+ do {
+ rtems_bsp_delay(100);
+ } while (tries-- > 0 && (inl(ETH0_ESDCMR) & (ETH_ESDCMR_AR|ETH_ESDCMR_AT)));
+ }
+#ifdef GT_DEBUG
+ printk(", phy %d (mii)\n", phyaddr);
+ printk("ETH0_ESDCMR %x ", inl(ETH0_ESDCMR));
+#endif
+
+ sc->sc_pcr &= ~(ETH_EPCR_EN | ETH_EPCR_RBM | ETH_EPCR_PM | ETH_EPCR_PBF);
+
+#ifdef GT_DEBUG
+ printk("Now sc_pcr %x,sc_pcxr %x", sc->sc_pcr, sc->sc_pcxr);
+#endif
+
+ /*
+ * Now turn off the GT. If it didn't quiese, too ***ing bad.
+ */
+ outl(sc->sc_pcr, ETH0_EPCR);
+ outl(sc->sc_intrmask, ETH0_EIMR);
+ sdcr = inl(ETH0_ESDCR);
+ /* Burst size is limited to 4 64bit words */
+ ETH_ESDCR_BSZ_SET(sdcr, ETH_ESDCR_BSZ_4);
+ sdcr |= ETH_ESDCR_RIFB;/*limit interrupt on frame boundaries, instead of buffer*/
+#if 0
+ sdcr &= ~(ETH_ESDCR_BLMT|ETH_ESDCR_BLMR); /* MOTLoad defualt Big-endian */
+#endif
+ outl(sdcr, ETH0_ESDCR);
+
+#ifdef GT_DEBUG
+ printk("sdcr %x \n", sdcr);
+#endif
+
+ if (phyaddr== -1) printk("MII auto negotiation ?");
+
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+
+ ifp->if_softc = sc;
+
+ /* set this interface's name and unit */
+ ifp->if_unit = unit;
+ ifp->if_name = name;
+
+ ifp->if_mtu = config->mtu ? config->mtu : ETHERMTU;
+
+ ifp->if_init = GT64260eth_ifinit;
+ ifp->if_ioctl = GTeth_ifioctl;
+ ifp->if_start = GTeth_ifstart;
+ ifp->if_output = ether_output;
+
+ /* ifp->if_watchdog = GTeth_ifwatchdog;*/
+
+ if (ifp->if_snd.ifq_maxlen == 0)
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
+
+ /* create the synchronization semaphore */
+ if (RTEMS_SUCCESSFUL != rtems_semaphore_create(
+ rtems_build_name('G','e','t','h'),0,0,0,&sc->daemonSync))
+ printk("GT64260eth: semaphore creation failed");
+
+ sc->next_module = root_GT64260eth_dev;
+ root_GT64260eth_dev = sc;
+
+ /* Actually attach the interface */
+ if_attach(ifp);
+ ether_ifattach(ifp);
+
+#ifdef GT_DEBUG
+ printk("GT64260eth: Ethernet driver has been attached (handle 0x%08x,ifp 0x%08x)\n",sc, ifp);
+#endif
+
+ return(1);
+}
+
+static void GT64260eth_stats(struct GTeth_softc *sc)
+{
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+
+#if 0
+ printf(" Rx Interrupts:%-8lu\n", sc->stats.rxInterrupts);
+ printf(" Receive Packets:%-8lu\n", ifp->if_ipackets);
+ printf(" Receive errors:%-8lu\n", ifp->if_ierrors);
+ printf(" Framing Errors:%-8lu\n", sc->stats.frame_errors);
+ printf(" Crc Errors:%-8lu\n", sc->stats.crc_errors);
+ printf(" Oversized Frames:%-8lu\n", sc->stats.length_errors);
+ printf(" Active Rxqs:%-8u\n", sc->rxq_active);
+ printf(" Tx Interrupts:%-8lu\n", sc->stats.txInterrupts);
+#endif
+ printf("Multi-BuffTx Packets:%-8lu\n", sc->stats.txMultiBuffPacket);
+ printf("Multi-BuffTx max len:%-8lu\n", sc->stats.txMultiMaxLen);
+ printf("SingleBuffTx max len:%-8lu\n", sc->stats.txSinglMaxLen);
+ printf("Multi-BuffTx maxloop:%-8lu\n", sc->stats.txMultiMaxLoop);
+ printf("Tx buffer max len :%-8lu\n", sc->stats.txBuffMaxLen);
+#if 0
+ printf(" Transmitt Packets:%-8lu\n", ifp->if_opackets);
+ printf(" Transmitt errors:%-8lu\n", ifp->if_oerrors);
+ printf(" Tx/Rx collisions:%-8lu\n", ifp->if_collisions);
+ printf(" Active Txqs:%-8u\n", sc->txq_nactive);
+#endif
+}
+
+void GT64260eth_printStats()
+{
+ GT64260eth_stats(root_GT64260eth_dev);
+}
+
+static int GTeth_ifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ struct GTeth_softc *sc = ifp->if_softc;
+ struct ifreq *ifr = (struct ifreq *) data;
+
+ int error = 0;
+
+#ifdef GT_DEBUG
+ printk("GTeth_ifioctl(");
+#endif
+
+ switch (cmd) {
+ default:
+ if (GTeth_debug >0) {
+ printk("etherioctl(");
+ if (cmd== SIOCSIFADDR) printk("SIOCSIFADDR ");
+ }
+ return ether_ioctl(ifp, cmd, data);
+
+ case SIOCSIFFLAGS:
+ switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
+ case IFF_RUNNING: /* not up, so we stop */
+ GT64260eth_stop(sc);
+ break;
+ case IFF_UP: /* not running, so we start */
+ GT64260eth_ifinit(sc);
+ break;
+ case IFF_UP|IFF_RUNNING:/* active->active, update */
+ GT64260eth_stop(sc);
+ GT64260eth_ifinit(sc);
+ break;
+ default: /* idle->idle: do nothing */
+ break;
+ }
+ break;
+ case SIO_RTEMS_SHOW_STATS:
+ GT64260eth_stats (sc);
+ break;
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ error = (cmd == SIOCADDMULTI)
+ ? ether_addmulti(ifr, &sc->arpcom)
+ : ether_delmulti(ifr, &sc->arpcom);
+ if (error == ENETRESET) {
+ if (ifp->if_flags & IFF_RUNNING)
+ GTeth_ifchange(sc);
+ error = 0;
+ }
+ break;
+ case SIOCSIFMTU:
+ if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) {
+ error = EINVAL;
+ break;
+ }
+ ifp->if_mtu = ifr->ifr_mtu;
+ break;
+ }
+
+#ifdef GT_DEBUG
+ printk("exit ioctl\n");
+#endif
+ return error;
+}
+
+static void GTeth_ifstart(struct ifnet *ifp)
+{
+ struct GTeth_softc *sc = ifp->if_softc;
+
+#ifdef GT_DEBUG
+ printk("GTeth_ifstart(");
+#endif
+
+ if ((ifp->if_flags & IFF_RUNNING) == 0) {
+#ifdef GT_DEBUG
+ printk("IFF_RUNNING==0\n");
+#endif
+ return;
+ }
+
+ ifp->if_flags |= IFF_OACTIVE;
+ rtems_event_send (sc->daemonTid, START_TRANSMIT_EVENT);
+#ifdef GT_DEBUG
+ printk(")\n");
+#endif
+}
+
+/* Initialize the Rx rings */
+static void GTeth_init_rx_ring(struct GTeth_softc *sc)
+{
+ int i;
+ volatile struct GTeth_desc *rxd;
+ unsigned nxtaddr;
+
+ sc->rxq_fi=0;
+ sc->rxq_head_desc = &sc->rxq_desc[0];
+ rxd = sc->rxq_head_desc;
+
+ sc->rxq_desc_busaddr = (unsigned long) sc->rxq_head_desc;
+#ifdef GT_DEBUG
+ printk("rxq_desc_busaddr %x ,&sc->rxq_desc[0] %x\n",
+ sc->rxq_desc_busaddr, sc->rxq_head_desc);
+#endif
+
+ nxtaddr = sc->rxq_desc_busaddr + sizeof(*rxd);
+ sc->rx_buf_sz = (sc->arpcom.ac_if.if_mtu <= 1500 ? PKT_BUF_SZ : sc->arpcom.ac_if.if_mtu + 32);
+ sc->rxq_active = RX_RING_SIZE;
+
+ for (i = 0; i < RX_RING_SIZE; i++, rxd++, nxtaddr += sizeof(*rxd)) {
+ struct mbuf *m;
+
+ rxd->ed_lencnt= sc->rx_buf_sz <<16;
+ rxd->ed_cmdsts = RX_CMD_F|RX_CMD_L|RX_CMD_O|RX_CMD_EI;
+
+ MGETHDR(m, M_WAIT, MT_DATA);
+ MCLGET(m, M_WAIT);
+ m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
+ sc->rxq_mbuf[i] = m;
+
+ /* convert mbuf pointer to data pointer of correct type */
+ rxd->ed_bufptr = (unsigned) mtod(m, void *);
+
+ /*
+ * update the nxtptr to point to the next txd.
+ */
+ if (i == RX_RING_SIZE - 1)
+ nxtaddr = sc->rxq_desc_busaddr;
+ rxd->ed_nxtptr = nxtaddr;
+
+#ifdef GT_DEBUG
+ printk("ed_lencnt %x, rx_buf_sz %x ",rxd->ed_lencnt, sc->rx_buf_sz);
+ printk("ed_cmdsts %x \n",rxd->ed_cmdsts);
+ printk("mbuf @ 0x%x, next desc. @ 0x%x\n",rxd->ed_bufptr,rxd->ed_nxtptr);
+#endif
+ }
+}
+
+void GTeth_rxprio_setup(struct GTeth_softc *sc)
+{
+
+ GTeth_init_rx_ring(sc);
+
+ sc->rxq_intrbits = ETH_IR_RxBuffer|ETH_IR_RxError|ETH_IR_RxBuffer_3|ETH_IR_RxError_3;
+}
+
+static int GT64260eth_rx(struct GTeth_softc *sc)
+{
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ struct mbuf *m;
+ int nloops=0;
+
+#ifdef GT_DEBUG
+ if (GTeth_rx_debug>0) printk("GT64260eth_rx(");
+#endif
+
+ while (sc->rxq_active > 0) {
+ volatile struct GTeth_desc *rxd = &sc->rxq_desc[sc->rxq_fi];
+ struct ether_header *eh;
+ unsigned int cmdsts;
+ unsigned int byteCount;
+
+ cmdsts = rxd->ed_cmdsts;
+
+ /*
+ * Sometimes the GE "forgets" to reset the ownership bit.
+ * But if the length has been rewritten, the packet is ours
+ * so pretend the O bit is set.
+ *
+ */
+ byteCount = rxd->ed_lencnt & 0xffff;
+
+ if (cmdsts & RX_CMD_O) {
+ if (byteCount == 0)
+ return(0);
+
+ /* <Kate Feng> Setting command/status to be zero seems to eliminate
+ * the spurious interrupt associated with the GE_FORGOT issue.
+ */
+ rxd->ed_cmdsts=0;
+
+#ifdef GE_FORGOT
+ /*
+ * For dignosis purpose only. Not a good practice to turn it on
+ */
+ printk("Rxq %d %d %d\n", sc->rxq_fi, byteCount,nloops);
+#endif
+ }
+
+ /* GT gave the ownership back to the CPU or the length has
+ * been rewritten , which means there
+ * is new packet in the descriptor/buffer
+ */
+
+ nloops++;
+ /*
+ * If this is not a single buffer packet with no errors
+ * or for some reason it's bigger than our frame size,
+ * ignore it and go to the next packet.
+ */
+ if ((cmdsts & (RX_CMD_F|RX_CMD_L|RX_STS_ES)) !=
+ (RX_CMD_F|RX_CMD_L) ||
+ byteCount > sc->sc_max_frame_length) {
+ --sc->rxq_active;
+ ifp->if_ipackets++;
+ ifp->if_ierrors++;
+ if (cmdsts & RX_STS_OR) sc->stats.or_errors++;
+ if (cmdsts & RX_STS_CE) sc->stats.crc_errors++;
+ if (cmdsts & RX_STS_MFL) sc->stats.length_errors++;
+ if (cmdsts & RX_STS_SF) sc->stats.frame_errors++;
+ if ((cmdsts & RX_STS_LC) || (cmdsts & RX_STS_COL))
+ ifp->if_collisions++;
+ goto give_it_back;
+ }
+ m = sc->rxq_mbuf[sc->rxq_fi];
+ m->m_len = m->m_pkthdr.len = byteCount - sizeof(struct ether_header);
+ eh = mtod (m, struct ether_header *);
+ m->m_data += sizeof(struct ether_header);
+ ether_input (ifp, eh, m);
+
+ ifp->if_ipackets++;
+ ifp->if_ibytes+=byteCount;
+ --sc->rxq_active;
+
+ give_it_back:
+ MGETHDR (m, M_WAIT, MT_DATA);
+ MCLGET (m, M_WAIT);
+ m->m_pkthdr.rcvif = ifp;
+ sc->rxq_mbuf[sc->rxq_fi]= m;
+ /* convert mbuf pointer to data pointer of correct type */
+ rxd->ed_bufptr = (unsigned) mtod(m, void*);
+ rxd->ed_lencnt = (unsigned long) sc->rx_buf_sz <<16;
+ rxd->ed_cmdsts = RX_CMD_F|RX_CMD_L|RX_CMD_O|RX_CMD_EI;
+
+ if (++sc->rxq_fi == RX_RING_SIZE) sc->rxq_fi = 0;
+
+ sc->rxq_active++;
+ } /* while (sc->rxq_active > 0) */
+#ifdef GT_DEBUG
+ if (GTeth_rx_debug>0) printk(")");
+#endif
+ return nloops;
+}
+
+static void GTeth_rx_setup(struct GTeth_softc *sc)
+{
+
+ if (GTeth_rx_debug>0) printk("GTeth_rx_setup(");
+
+ GTeth_rxprio_setup(sc);
+
+ if ((sc->sc_flags & GE_RXACTIVE) == 0) {
+ /* First Rx Descriptor Pointer 3 */
+ outl( sc->rxq_desc_busaddr, ETH0_EFRDP3);
+ /* Current Rx Descriptor Pointer 3 */
+ outl( sc->rxq_desc_busaddr,ETH0_ECRDP3);
+#ifdef GT_DEBUG
+ printk("ETH0_EFRDP3 0x%x, ETH0_ECRDP3 0x%x \n", inl(ETH0_EFRDP3),
+ inl(ETH0_ECRDP3));
+#endif
+ }
+ sc->sc_intrmask |= sc->rxq_intrbits;
+
+ if (GTeth_rx_debug>0) printk(")\n");
+}
+
+static void GTeth_rx_cleanup(struct GTeth_softc *sc)
+{
+ int i;
+
+ if (GTeth_rx_debug>0) printk( "GTeth_rx_cleanup(");
+
+ for (i=0; i< RX_RING_SIZE; i++) {
+ if (sc->rxq_mbuf[i]) {
+ m_freem(sc->rxq_mbuf[i]);
+ sc->rxq_mbuf[i]=0;
+ }
+ }
+ if (GTeth_rx_debug>0) printk(")");
+}
+
+static void GTeth_rx_stop(struct GTeth_softc *sc)
+{
+ if (GTeth_rx_debug>0) printk( "GTeth_rx_stop(");
+ sc->sc_flags &= ~GE_RXACTIVE;
+ sc->sc_idlemask &= ~(ETH_IR_RxBits|ETH_IR_RxBuffer_3|ETH_IR_RxError_3);
+ sc->sc_intrmask &= ~(ETH_IR_RxBits|ETH_IR_RxBuffer_3|ETH_IR_RxError_3);
+ outl(sc->sc_intrmask, ETH0_EIMR);
+ outl(ETH_ESDCMR_AR, ETH0_ESDCMR); /* abort receive */
+ do {
+ rtems_bsp_delay(10);
+ } while (inl(ETH0_ESDCMR) & ETH_ESDCMR_AR);
+ GTeth_rx_cleanup(sc);
+ if (GTeth_rx_debug>0) printk(")");
+}
+
+static void GTeth_txq_free(struct GTeth_softc *sc, unsigned cmdsts)
+{
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ volatile struct GTeth_desc *txd = &sc->txq_desc[sc->txq_fi];
+
+ /* ownership is sent back to CPU */
+ if (GTeth_debug>0) printk("txq%d,active %d\n", sc->txq_fi, sc->txq_nactive);
+
+ txd->ed_cmdsts &= ~TX_CMD_O; /* <skf> in case GT forgot */
+
+ /* statistics */
+ ifp->if_opackets++;
+ ifp->if_obytes += sc->txq_mbuf[sc->txq_fi]->m_len;
+ if (cmdsts & TX_STS_ES) {
+ ifp->if_oerrors++;
+ if ((cmdsts & TX_STS_LC) || (cmdsts & TX_STS_COL))
+ ifp->if_collisions++;
+ }
+ /* Free the original mbuf chain */
+ m_freem(sc->txq_mbuf[sc->txq_fi]);
+ sc->txq_mbuf[sc->txq_fi] = 0;
+ ifp->if_timer = 5;
+
+ sc->txq_free++;
+ if (++sc->txq_fi == TX_RING_SIZE) sc->txq_fi = 0;
+ --sc->txq_nactive;
+}
+
+static int txq_high_limit(struct GTeth_softc *sc)
+{
+ /*
+ * Have we [over]consumed our limit of descriptors?
+ * Do we have enough free descriptors?
+ */
+ if ( TX_RING_SIZE == sc->txq_nactive + TXQ_HiLmt_OFF) {
+ volatile struct GTeth_desc *txd2 = &sc->txq_desc[sc->txq_fi];
+ unsigned cmdsts;
+
+ cmdsts = txd2->ed_cmdsts;
+ if (cmdsts & TX_CMD_O) { /* Ownership (1=GT 0=CPU) */
+ int nextin;
+
+ /*
+ * Sometime the Discovery forgets to update the
+ * last descriptor. See if CPU owned the descriptor
+ * after it (since we know we've turned that to
+ * the discovery and if CPU owned it, the Discovery
+ * gave it back). If CPU does, we know the Discovery
+ * gave back this one but forgot to mark it back to CPU.
+ */
+ nextin = (sc->txq_fi + 1) % TX_RING_SIZE;
+ if (sc->txq_desc[nextin].ed_cmdsts & TX_CMD_O) {
+#if 0
+ printk("Overconsuming Tx descriptors!\n");
+#endif
+ return 1;
+ }
+ printk("Txq %d forgot\n", sc->txq_fi);
+ }
+ /* Txq ring is almost full, let's free the current buffer here */
+#if 0
+ printk("Txq ring near full, free desc%d\n",sc->txq_fi);
+#endif
+ GTeth_txq_free(sc, cmdsts);
+ } /* end if ( TX_RING_SIZE == sc->txq_nactive + TXQ_HiLmt_OFF) */
+ return 0;
+}
+
+static int GT64260eth_sendpacket(struct GTeth_softc *sc,struct mbuf *m)
+{
+ volatile struct GTeth_desc *txd = &sc->txq_desc[sc->txq_lo];
+ unsigned intrmask = sc->sc_intrmask;
+ unsigned loop=0, index= sc->txq_lo;
+
+ /*
+ * The end-of-list descriptor we put on last time is the starting point
+ * for this packet. The GT is supposed to terminate list processing on
+ * a NULL nxtptr but that currently is broken so a CPU-owned descriptor
+ * must terminate the list.
+ */
+ intrmask = sc->sc_intrmask;
+
+ if ( !(m->m_next)) {/* single buffer packet */
+ sc->txq_mbuf[index]= m;
+ sc->stats.txSinglMaxLen= MAX(m->m_len, sc->stats.txSinglMaxLen);
+ }
+ else /* multiple mbufs in this packet */
+ {
+ struct mbuf *mtp, *mdest;
+ volatile unsigned char *pt;
+ int len, y;
+
+#ifdef GT_DEBUG
+ printk("multi mbufs ");
+#endif
+ MGETHDR(mdest, M_WAIT, MT_DATA);
+ MCLGET(mdest, M_WAIT);
+ pt = (volatile unsigned char *)mdest->m_data;
+ for (mtp=m,len=0;mtp;mtp=mtp->m_next) {
+ loop++;
+ if ( (y=(len+mtp->m_len)) > sizeof(union mcluster)) {
+ /* GT64260 allows us to chain the remaining to the next
+ * free descriptors.
+ */
+ printk("packet size %x > mcluster %x\n", y,sizeof(union mcluster));
+ printk("GT64260eth : packet too large ");
+ }
+ memcpy((void *)pt,(char *)mtp->m_data, mtp->m_len);
+ pt += mtp->m_len;
+#if 0
+ printk("%d ",mtp->m_len);
+#endif
+ len += mtp->m_len;
+ sc->stats.txBuffMaxLen=MAX(mtp->m_len,sc->stats.txBuffMaxLen);
+ }
+ sc->stats.txMultiMaxLoop=MAX(loop, sc->stats.txMultiMaxLoop);
+#if 0
+ printk("\n");
+#endif
+ mdest->m_len=len;
+ /* free old mbuf chain */
+ m_freem(m);
+ sc->txq_mbuf[index] = m = mdest;
+ sc->stats.txMultiBuffPacket++;
+ sc->stats.txMultiMaxLen= MAX(m->m_len, sc->stats.txMultiMaxLen);
+ }
+ if (m->m_len < ET_MINLEN) m->m_len = ET_MINLEN;
+
+ txd->ed_bufptr = (unsigned) mtod(m, void*);
+ txd->ed_lencnt = m->m_len << 16;
+ /*txd->ed_cmdsts = TX_CMD_L|TX_CMD_GC|TX_CMD_P|TX_CMD_O|TX_CMD_F|TX_CMD_EI;*/
+ txd->ed_cmdsts = 0x80c70000;
+ while (txd->ed_cmdsts != 0x80c70000);
+ memBar();
+
+#ifdef GT_DEBUG
+ printk("len = %d, cmdsts 0x%x ", m->m_len,txd->ed_cmdsts);
+#endif
+
+ /*
+ * Tell the SDMA engine to "Fetch!"
+ * Start Tx high.
+ */
+ sc->txq_nactive++;
+ outl(0x800080, ETH0_ESDCMR); /* ETH_ESDCMR_TXDH| ETH_ESDCMR_ERD */
+ if ( ++sc->txq_lo == TX_RING_SIZE) sc->txq_lo = 0;
+ sc->txq_free--;
+
+#if 0
+ /*
+ * Since we have put an item into the packet queue, we now want
+ * an interrupt when the transmit queue finishes processing the
+ * list. But only update the mask if needs changing.
+ */
+ intrmask |= sc->txq_intrbits & ( ETH_IR_TxEndHigh|ETH_IR_TxBufferHigh);
+ if (sc->sc_intrmask != intrmask) {
+ sc->sc_intrmask = intrmask;
+ outl(sc->sc_intrmask, ETH0_EIMR);
+ }
+#endif
+
+#if 0
+ printk("EICR= %x, EIMR= %x ", inl(ETH0_EICR), inl(ETH0_EIMR));
+ printk("%s:transmit frame #%d queued in slot %d.\n",
+ sc->arpcom.ac_if.if_name, sc->txq_lo, index);
+ printk("pcr %x, pcxr %x DMA dcr %x cmr %x\n", inl(ETH0_EPCR), inl(ETH0_EPCXR), inl(ETH0_ESDCR), inl(ETH0_ESDCMR));
+#endif
+
+ return 1;
+}
+
+static unsigned GTeth_txq_done(struct GTeth_softc *sc)
+{
+ if (GTeth_debug>0) printk("Txdone(" );
+
+ while (sc->txq_nactive > 0) {
+ /* next to be returned to the CPU */
+ volatile struct GTeth_desc *txd = &sc->txq_desc[sc->txq_fi];
+ unsigned cmdsts;
+
+ /* if GT64260 still owns it ....... */
+ if ((cmdsts = txd->ed_cmdsts) & TX_CMD_O) {
+ int nextin;
+
+ /* Someone quoted :
+ * "Sometimes the Discovery forgets to update the
+ * ownership bit in the descriptor."
+ * <skf> More correctly, the last descriptor of each
+ * transmitted frame is returned to CPU ownership and
+ * status is updated only after the actual transmission
+ * of the packet is completed. Also, if there is an error
+ * during transmission, we want to continue the
+ * transmission of the next descriptor, in additions to
+ * reporting the error.
+ */
+ /* The last descriptor */
+ if (sc->txq_nactive == 1) return(0);
+
+ /*
+ * Sometimes the Discovery forgets to update the
+ * ownership bit in the descriptor. See if CPU owned
+ * the descriptor after it (since we know we've turned
+ * that to the Discovery and if CPU owned it now then the
+ * Discovery gave it back). If we do, we know the
+ * Discovery gave back this one but forgot to mark it
+ * back to CPU.
+ */
+ nextin = (sc->txq_fi + 1) % TX_RING_SIZE;
+
+ if (sc->txq_desc[nextin].ed_cmdsts & TX_CMD_O) return(0);
+ printk("Txq%d forgot\n",sc->txq_fi);
+ } /* end checking GT64260eth owner */
+ GTeth_txq_free(sc, cmdsts);
+ } /* end while */
+ if (GTeth_debug>0) printk(")\n");
+ return(1);
+}
+
+static void GTeth_tx_start(struct GTeth_softc *sc)
+{
+ int i;
+ volatile struct GTeth_desc *txd;
+ unsigned nxtaddr;
+
+#ifdef GT_DEBUG
+ printk("GTeth_tx_start(");
+#endif
+ sc->sc_intrmask &= ~(ETH_IR_TxEndHigh|ETH_IR_TxBufferHigh|
+ ETH_IR_TxEndLow |ETH_IR_TxBufferLow);
+
+ txd = &sc->txq_desc[0];
+ sc->txq_desc_busaddr = (unsigned long) &sc->txq_desc[0];
+#ifdef GT_DEBUG
+ printk("txq_desc_busaddr %x, &sc->txq_desc[0] %x \n",
+ sc->txq_desc_busaddr,&sc->txq_desc[0]);
+#endif
+
+ nxtaddr = sc->txq_desc_busaddr + sizeof(*txd);
+
+ sc->txq_pendq.ifq_maxlen = 10;
+ sc->txq_pendq.ifq_head= NULL;
+ sc->txq_pendq.ifq_tail= NULL;
+ sc->txq_nactive = 0;
+ sc->txq_fi = 0;
+ sc->txq_lo = 0;
+ sc->txq_inptr = PKT_BUF_SZ;
+ sc->txq_outptr = 0;
+ sc->txq_free = TX_RING_SIZE;
+
+ for (i = 0; i < TX_RING_SIZE;
+ i++, txd++, nxtaddr += sizeof(*txd)) {
+ sc->txq_mbuf[i]=0;
+ txd->ed_bufptr = 0;
+
+ /*
+ * update the nxtptr to point to the next txd.
+ */
+ txd->ed_cmdsts = 0;
+ if ( i== TX_RING_SIZE-1) nxtaddr = sc->txq_desc_busaddr;
+ txd->ed_nxtptr = nxtaddr;
+#ifdef GT_DEBUG
+ printk("next desc. @ 0x%x\n",txd->ed_nxtptr);
+#endif
+ }
+
+ sc->txq_intrbits = ETH_IR_TxEndHigh|ETH_IR_TxBufferHigh;
+ sc->txq_esdcmrbits = ETH_ESDCMR_TXDH; /* Start Tx high */
+ sc->txq_epsrbits = ETH_EPSR_TxHigh;
+ /* offset to current tx desc ptr reg */
+ sc->txq_ectdp = (caddr_t)ETH0_ECTDP1;
+ /* Current Tx Desc Pointer 1 */
+ outl(sc->txq_desc_busaddr,ETH0_ECTDP1);
+
+#ifdef GT_DEBUG
+ printk(")\n");
+#endif
+}
+
+static void GTeth_tx_cleanup(struct GTeth_softc *sc)
+{
+ int i;
+
+ for (i=0; i< TX_RING_SIZE; i++) {
+ if (sc->txq_mbuf[i]) {
+ m_freem(sc->txq_mbuf[i]);
+ sc->txq_mbuf[i]=0;
+ }
+ }
+}
+
+static void GTeth_tx_stop(struct GTeth_softc *sc)
+{
+ /* SDMA command register : stop Tx high and low */
+ outl(ETH_ESDCMR_STDH|ETH_ESDCMR_STDL, ETH0_ESDCMR);
+
+ GTeth_txq_done(sc);
+ sc->sc_intrmask &= ~(ETH_IR_TxEndHigh|ETH_IR_TxBufferHigh|
+ ETH_IR_TxEndLow |ETH_IR_TxBufferLow);
+ GTeth_tx_cleanup(sc);
+
+ sc->arpcom.ac_if.if_timer = 0;
+}
+
+/* TOCHECK : Should it be about rx or tx ? */
+static void GTeth_ifchange(struct GTeth_softc *sc)
+{
+ if (GTeth_debug>0) printk("GTeth_ifchange(");
+ if (GTeth_debug>5) printk("(pcr=%#x,imr=%#x)",inl(ETH0_EPCR),inl(ETH0_EIMR));
+ /* printk("SIOCADDMULTI (SIOCDELMULTI): is it about rx or tx ?\n");*/
+ outl(sc->sc_pcr | ETH_EPCR_EN, ETH0_EPCR);
+ outl(sc->sc_intrmask, ETH0_EIMR);
+ GTeth_ifstart(&sc->arpcom.ac_if);
+ /* Current Tx Desc Pointer 0 and 1 */
+ if (GTeth_debug>5) printk("(ectdp0=%#x, ectdp1=%#x)",
+ inl(ETH0_ECTDP0), inl(ETH0_ECTDP1));
+ if (GTeth_debug>0) printk(")");
+}
+
+static int GTeth_hash_compute(struct GTeth_softc *sc,unsigned char eaddr[ETHER_ADDR_LEN])
+{
+ unsigned w0, add0, add1;
+ unsigned result;
+
+ if (GTeth_debug>0) printk("GTeth_hash_compute(");
+ add0 = ((unsigned) eaddr[5] << 0) |
+ ((unsigned) eaddr[4] << 8) |
+ ((unsigned) eaddr[3] << 16);
+
+ add0 = ((add0 & 0x00f0f0f0) >> 4) | ((add0 & 0x000f0f0f) << 4);
+ add0 = ((add0 & 0x00cccccc) >> 2) | ((add0 & 0x00333333) << 2);
+ add0 = ((add0 & 0x00aaaaaa) >> 1) | ((add0 & 0x00555555) << 1);
+
+ add1 = ((unsigned) eaddr[2] << 0) |
+ ((unsigned) eaddr[1] << 8) |
+ ((unsigned) eaddr[0] << 16);
+
+ add1 = ((add1 & 0x00f0f0f0) >> 4) | ((add1 & 0x000f0f0f) << 4);
+ add1 = ((add1 & 0x00cccccc) >> 2) | ((add1 & 0x00333333) << 2);
+ add1 = ((add1 & 0x00aaaaaa) >> 1) | ((add1 & 0x00555555) << 1);
+
+#ifdef GT_DEBUG
+ printk("eaddr= %s add1:%x add0:%x\n", ether_sprintf1(eaddr), add1, add0);
+#endif
+
+ /*
+ * hashResult is the 15 bits Hash entry address.
+ * ethernetADD is a 48 bit number, which is derived from the Ethernet
+ * MAC address, by nibble swapping in every byte (i.e MAC address
+ * of 0x123456789abc translates to ethernetADD of 0x21436587a9cb).
+ */
+ if ((sc->sc_pcr & ETH_EPCR_HM) == 0) {
+ /*
+ * hashResult[14:0] = hashFunc0(ethernetADD[47:0])
+ *
+ * hashFunc0 calculates the hashResult in the following manner:
+ * hashResult[ 8:0] = ethernetADD[14:8,1,0]
+ * XOR ethernetADD[23:15] XOR ethernetADD[32:24]
+ */
+ result = (add0 & 3) | ((add0 >> 6) & ~3);
+ result ^= (add0 >> 15) ^ (add1 >> 0);
+ result &= 0x1ff;
+ /*
+ * hashResult[14:9] = ethernetADD[7:2]
+ */
+ result |= (add0 & ~3) << 7; /* excess bits will be masked */
+#ifdef GT_DEBUG
+ printk("hash result %x ", result & 0x7fff);
+#endif
+ } else {
+#define TRIBITFLIP 073516240 /* yes its in octal */
+ /*
+ * hashResult[14:0] = hashFunc1(ethernetADD[47:0])
+ *
+ * hashFunc1 calculates the hashResult in the following manner:
+ * hashResult[08:00] = ethernetADD[06:14]
+ * XOR ethernetADD[15:23] XOR ethernetADD[24:32]
+ */
+ w0 = ((add0 >> 6) ^ (add0 >> 15) ^ (add1)) & 0x1ff;
+ /*
+ * Now bitswap those 9 bits
+ */
+ result = 0;
+ result |= ((TRIBITFLIP >> (((w0 >> 0) & 7) * 3)) & 7) << 6;
+ result |= ((TRIBITFLIP >> (((w0 >> 3) & 7) * 3)) & 7) << 3;
+ result |= ((TRIBITFLIP >> (((w0 >> 6) & 7) * 3)) & 7) << 0;
+
+ /*
+ * hashResult[14:09] = ethernetADD[00:05]
+ */
+ result |= ((TRIBITFLIP >> (((add0 >> 0) & 7) * 3)) & 7) << 12;
+ result |= ((TRIBITFLIP >> (((add0 >> 3) & 7) * 3)) & 7) << 9;
+#ifdef GT_DEBUG
+ printk("1(%#x)", result);
+#endif
+ }
+#ifdef GT_DEBUG
+ printk(")");
+#endif
+
+ /* 1/2K address filtering (MOTLoad default )? ->16KB memory required
+ * or 8k address filtering ? -> 256KB memory required
+ */
+ return result & ((sc->sc_pcr & ETH_EPCR_HS_512) ? 0x7ff : 0x7fff);
+}
+
+static int GTeth_hash_entry_op(struct GTeth_softc *sc, enum GTeth_hash_op op,
+ enum GTeth_rxprio prio,unsigned char eaddr[ETHER_ADDR_LEN])
+{
+ unsigned long long he;
+ unsigned long long *maybe_he_p = NULL;
+ int limit;
+ int hash;
+ int maybe_hash = 0;
+
+#ifdef GT_DEBUG
+ printk("GTeth_hash_entry_op(prio %d ", prio);
+#endif
+
+ hash = GTeth_hash_compute(sc, eaddr);
+
+ if (sc->sc_hashtable == NULL) {
+ printk("hashtable == NULL!");
+ }
+#ifdef GT_DEBUG
+ printk("Hash computed %x eaddr %s\n", hash,ether_sprintf1(eaddr));
+#endif
+
+ /*
+ * Assume we are going to insert so create the hash entry we
+ * are going to insert. We also use it to match entries we
+ * will be removing. The datasheet is wrong for this.
+ */
+ he = (((unsigned long long) eaddr[5]) << 43) |
+ (((unsigned long long) eaddr[4]) << 35) |
+ (((unsigned long long) eaddr[3]) << 27) |
+ (((unsigned long long) eaddr[2]) << 19) |
+ (((unsigned long long) eaddr[1]) << 11) |
+ (((unsigned long long) eaddr[0]) << 3) |
+ ((unsigned long long) HSH_PRIO_INS(prio) | HSH_V | HSH_R);
+ /* he = 0x1b1acd87d08005;*/
+ /*
+ * The GT will search upto 12 entries for a hit, so we must mimic that.
+ */
+ hash &= (sc->sc_hashmask / sizeof(he));
+
+#ifdef GT_DEBUG
+ if (GTeth_debug>0) {
+ unsigned val1, val2;
+
+ val1= he & 0xffffffff;
+ val2= (he >>32) & 0xffffffff;
+ printk("Hash addr value %x%x, entry %x\n",val2,val1, hash);
+ }
+#endif
+
+ for (limit = HSH_LIMIT; limit > 0 ; --limit) {
+ /*
+ * Does the GT wrap at the end, stop at the, or overrun the
+ * end? Assume it wraps for now. Stash a copy of the
+ * current hash entry.
+ */
+ unsigned long long *he_p = &sc->sc_hashtable[hash];
+ unsigned long long thishe = *he_p;
+
+ /*
+ * If the hash entry isn't valid, that break the chain. And
+ * this entry a good candidate for reuse.
+ */
+ if ((thishe & HSH_V) == 0) {
+ maybe_he_p = he_p;
+ break;
+ }
+
+ /*
+ * If the hash entry has the same address we are looking for
+ * then ... if we are removing and the skip bit is set, its
+ * already been removed. if are adding and the skip bit is
+ * clear, then its already added. In either return EBUSY
+ * indicating the op has already been done. Otherwise flip
+ * the skip bit and return 0.
+ */
+ if (((he ^ thishe) & HSH_ADDR_MASK) == 0) {
+ if (((op == GE_HASH_REMOVE) && (thishe & HSH_S)) ||
+ ((op == GE_HASH_ADD) && (thishe & HSH_S) == 0))
+ return EBUSY;
+ *he_p = thishe ^ HSH_S;
+
+ if (GTeth_debug>0) {
+ unsigned val1, val2;
+
+ val1= *he_p & 0xffffffff;
+ val2= (*he_p >>32) & 0xffffffff;
+ printk("flip skip bit result %x%x entry %x ",val2,val1, hash);
+ }
+ return 0;
+ }
+
+ /*
+ * If we haven't found a slot for the entry and this entry
+ * is currently being skipped, return this entry.
+ */
+ if (maybe_he_p == NULL && (thishe & HSH_S)) {
+ maybe_he_p = he_p;
+ maybe_hash = hash;
+ }
+ hash = (hash + 1) & (sc->sc_hashmask / sizeof(he));
+ }
+
+ /*
+ * If we got here, then there was no entry to remove.
+ */
+ if (op == GE_HASH_REMOVE) {
+ printk("GT64260eth : No entry to remove\n");
+ return ENOENT;
+ }
+
+ /*
+ * If we couldn't find a slot, return an error.
+ */
+ if (maybe_he_p == NULL) {
+ printk("GT64260eth : No slot found");
+ return ENOSPC;
+ }
+
+ /* Update the entry.*/
+ *maybe_he_p = he;
+ if (GTeth_debug>0) {
+ unsigned val1, val2;
+#if 0
+ unsigned long *pt= sc->sc_hashtable;
+ int i, loop;
+
+ for (loop= 0; loop< 256; loop++) {
+ printk("%d)", loop);
+ for (i=0; i< 16; i++, pt++) printk("%x ",*pt);
+ printk("\n");
+ }
+#endif
+ val1= he & 0xffffffff;
+ val2= (he >>32) & 0xffffffff;
+ printk("Update Hash result %x%x, table addr %x entry %x )\n",val2, val1, maybe_he_p, hash);
+ }
+ return 0;
+}
+
+static int GTeth_hash_fill(struct GTeth_softc *sc)
+{
+ struct ether_multistep step;
+ struct ether_multi *enm;
+ int error;
+
+#ifdef GT_DEBUG
+ printk( "GTeth_hash_fill(");
+#endif
+ error = GTeth_hash_entry_op(sc,GE_HASH_ADD,GE_RXPRIO_HI,sc->arpcom.ac_enaddr);
+
+ if (error) {
+ if (GTeth_debug>0) printk("!");
+ return error;
+ }
+
+ sc->sc_flags &= ~GE_ALLMULTI;
+ if ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) == 0)
+ sc->sc_pcr &= ~ETH_EPCR_PM;
+ /* see lib/include/netinet/if_ether.h */
+ ETHER_FIRST_MULTI(step, &sc->arpcom, enm);
+ while (enm != NULL) {
+ if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
+ /* Frames are received regardless of their destinatin address */
+ sc->sc_flags |= GE_ALLMULTI;
+ sc->sc_pcr |= ETH_EPCR_PM;
+ } else {
+ /* Frames are only received if the destinatin address is found
+ * in the hash table
+ */
+ error = GTeth_hash_entry_op(sc, GE_HASH_ADD,
+ GE_RXPRIO_MEDLO, enm->enm_addrlo);
+ if (error == ENOSPC) break;
+ }
+ ETHER_NEXT_MULTI(step, enm);
+ }
+#ifdef GT_DEBUG
+ printk(")\n");
+#endif
+ return error;
+}
+
+static void GTeth_hash_init(struct GTeth_softc *sc)
+{
+ void *hash_mem;
+
+ if (GTeth_debug>0) printk("GTeth_hash_init(");
+ /* MOTLoad defualt : 512 bytes of address filtering, which
+ * requires 16KB of memory
+ */
+#if 1
+ hash_mem = rtems_bsdnet_malloc(HASH_DRAM_SIZE + HASH_ALIGN, M_FREE, M_NOWAIT);
+ sc->sc_hashtable =(void *)(((long)hash_mem+ HASH_ALIGN) & ~HASH_ALIGN);
+#else
+ /* only for test */
+ hash_mem = 0x68F000;
+ sc->sc_hashtable =(unsigned long long *)hash_mem;
+#endif
+ sc->sc_hashmask = HASH_DRAM_SIZE - 1;
+
+ memset((void *)sc->sc_hashtable, 0,HASH_DRAM_SIZE);
+#ifdef GT_DEBUG
+ printk("hashtable addr:%x, mask %x)\n", sc->sc_hashtable,sc->sc_hashmask);
+#endif
+}
+
+static void GT64260eth_error(struct GTeth_softc *sc)
+{
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ unsigned int intr_status= sc->intr_errsts[sc->intr_err_ptr1];
+
+ /* read and reset the status; because this is written
+ * by the ISR, we must disable interrupts here
+ */
+ if (intr_status) {
+ printk("%s%d: ICR = 0x%x ",
+ ifp->if_name, ifp->if_unit, intr_status);
+#if 1
+ if (intr_status & INTR_RX_ERROR) {
+ printk("Rxq error, if_ierrors %d\n",
+ ifp->if_ierrors);
+ }
+#endif
+ /* Rx error is handled in GT64260eth_rx() */
+ if (intr_status & INTR_TX_ERROR) {
+ ifp->if_oerrors++;
+ printk("Txq error, if_oerrors %d\n",ifp->if_oerrors);
+ }
+ }
+ else
+ printk("%s%d: Ghost interrupt ?\n",ifp->if_name,
+ ifp->if_unit);
+ sc->intr_errsts[sc->intr_err_ptr1++]=0;
+ sc->intr_err_ptr1 %= INTR_ERR_SIZE; /* Till Straumann */
+}
+
+
+/* The daemon does all of the work; RX, TX and cleaning up buffers/descriptors */
+static void GT64260eth_daemon(void *arg)
+{
+ struct GTeth_softc *sc = (struct GTeth_softc*)arg;
+ rtems_event_set events;
+ struct mbuf *m=0;
+ struct ifnet *ifp=&sc->arpcom.ac_if;
+
+#if 0
+ /* see comments in GT64260eth_init(); in newer versions of
+ * rtems, we hold the network semaphore at this point
+ */
+ rtems_semaphore_release(sc->daemonSync);
+#endif
+
+ /* NOTE: our creator possibly holds the bsdnet_semaphore.
+ * since that has PRIORITY_INVERSION enabled, our
+ * subsequent call to bsdnet_event_receive() will
+ * _not_ release it. It's still in posession of our
+ * owner.
+ * This is different from how killing this task
+ * is handled.
+ */
+
+ for (;;) {
+ /* sleep until there's work to be done */
+ /* Note: bsdnet_event_receive() acquires
+ * the global bsdnet semaphore for
+ * mutual exclusion.
+ */
+ rtems_bsdnet_event_receive(ALL_EVENTS,
+ RTEMS_WAIT | RTEMS_EVENT_ANY,
+ RTEMS_NO_TIMEOUT,
+ &events);
+
+ if (KILL_EVENT & events) break;
+
+#ifndef GE_NORX
+ if (events & RX_EVENT) GT64260eth_rx(sc);
+#endif
+#if 0
+ printk("%x ", inb(ETH0_EPSR));
+ if ( ((i++) % 15)==0) printk("\n");
+#endif
+
+ /* clean up and try sending packets */
+ do {
+ if (sc->txq_nactive) GTeth_txq_done(sc);
+
+ while (sc->txq_free>0) {
+ if (sc->txq_free>TXQ_HiLmt_OFF) {
+ m=0;
+ IF_DEQUEUE(&ifp->if_snd,m);
+ if (m==0) break;
+ GT64260eth_sendpacket(sc, m);
+ }
+ else {
+ GTeth_txq_done(sc);
+ break;
+ }
+ }
+ /* we leave this loop
+ * - either because there's no free buffer
+ * (m=0 initializer && !sc->txq_free)
+ * - or there's nothing to send (IF_DEQUEUE
+ * returned 0
+ */
+ } while (m);
+
+ ifp->if_flags &= ~IFF_OACTIVE;
+
+ /* Log errors and other uncommon events. */
+ if (events & ERR_EVENT) GT64260eth_error(sc);
+ } /* end for(;;) { rtems_bsdnet_event_receive() .....*/
+
+ ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
+
+ /* shut down the hardware */
+ GT64260eth_stop_hw(sc);
+ /* flush the output queue */
+ for (;;) {
+ IF_DEQUEUE(&ifp->if_snd,m);
+ if (!m) break;
+ m_freem(m);
+ }
+ /* as of 'rtems_bsdnet_event_receive()' we own the
+ * networking semaphore
+ */
+ rtems_bsdnet_semaphore_release();
+ rtems_semaphore_release(sc->daemonSync);
+
+ /* Note that I dont use sc->daemonTid here -
+ * theoretically, that variable could already
+ * hold a newly created TID
+ */
+ rtems_task_delete(RTEMS_SELF);
+}
+
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/GT64260eth.h b/c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/GT64260eth.h
new file mode 100644
index 0000000000..52ea42c39e
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/GT64260eth.h
@@ -0,0 +1,140 @@
+/* GT64260eth.h
+ *
+ * Copyright (c) 2002 Allegro Networks, Inc., Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * RTEMS/Mvme5500 port 2004 by S. Kate Feng, <feng1@bnl.gov>,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Allegro Networks, Inc., and Wasabi Systems, Inc.
+ * 4. The name of Allegro Networks, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * 5. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ALLEGRO NETWORKS, INC. AND
+ * WASABI SYSTEMS, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL EITHER ALLEGRO NETWORKS, INC. OR WASABI SYSTEMS, INC.
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Keep the ring sizes a power of two for efficiency.
+ Making the Tx ring too long decreases the effectiveness of channel
+ bonding and packet priority.
+ There are no ill effects from too-large receive rings. */
+#define TX_RING_SIZE 32
+#define GT_NEXTTX(x) ((x + 1) % TX_RING_SIZE )
+#define TX_QUARTER_FULL TX_RING_SIZE/2
+#define TX_HALF_FULL TX_RING_SIZE/2
+#define RX_RING_SIZE 16
+#define HASH_TABLE_SIZE 16
+#define HASH_DRAM_SIZE HASH_TABLE_SIZE*1024 /* size of DRAM for hash table */
+#define INTR_ERR_SIZE 16
+
+enum GTeth_txprio {
+ GE_TXPRIO_HI=1,
+ GE_TXPRIO_LO=0,
+ GE_TXPRIO_NONE=2
+};
+enum GTeth_rxprio {
+ GE_RXPRIO_HI=3,
+ GE_RXPRIO_MEDHI=2,
+ GE_RXPRIO_MEDLO=1,
+ GE_RXPRIO_LO=0
+};
+
+struct GTeth_softc {
+ struct GTeth_desc txq_desc[TX_RING_SIZE]; /* transmit descriptor memory */
+ struct GTeth_desc rxq_desc[RX_RING_SIZE]; /* receive descriptor memory */
+ struct mbuf* txq_mbuf[TX_RING_SIZE]; /* transmit buffer memory */
+ struct mbuf* rxq_mbuf[RX_RING_SIZE]; /* receive buffer memory */
+ struct GTeth_softc *next_module;
+ volatile unsigned int intr_errsts[INTR_ERR_SIZE]; /* capture the right intr_status */
+ unsigned int intr_err_ptr1; /* ptr used in GTeth_error() */
+ unsigned int intr_err_ptr2; /* ptr used in ISR */
+ struct ifqueue txq_pendq; /* these are ready to go to the GT */
+ unsigned int txq_pending;
+ unsigned int txq_lo; /* next to be given to GT DMA */
+ unsigned int txq_fi; /* next to be free */
+ unsigned int txq_to_cpu; /* next to be returned to CPU */
+ unsigned int txq_ei_gapcount; /* counter until next EI */
+ unsigned int txq_nactive; /* number of active descriptors */
+ unsigned int txq_nintr; /* number of txq desc. send TX_EVENT */
+ unsigned int txq_outptr; /* where to put next transmit packet */
+ unsigned int txq_inptr; /* start of 1st queued tx packet */
+ unsigned int txq_free; /* free Tx queue slots. */
+ unsigned txq_intrbits; /* bits to write to EIMR */
+ unsigned txq_esdcmrbits; /* bits to write to ESDCMR */
+ unsigned txq_epsrbits; /* bits to test with EPSR */
+
+ caddr_t txq_ectdp; /* offset to cur. tx desc ptr reg */
+ unsigned long txq_desc_busaddr; /* bus addr of tx descriptors */
+ caddr_t txq_buf_busaddr; /* bus addr of tx buffers */
+
+ struct mbuf *rxq_curpkt; /* mbuf for current packet */
+ struct GTeth_desc *rxq_head_desc; /* rxq head descriptor */
+ unsigned int rxq_fi; /* next to be returned to CPU */
+ unsigned int rxq_active; /* # of descriptors given to GT */
+ unsigned rxq_intrbits; /* bits to write to EIMR */
+ unsigned long rxq_desc_busaddr; /* bus addr of rx descriptors */
+
+ struct arpcom arpcom; /* rtems if structure, contains ifnet */
+ int sc_macno; /* which mac? 0, 1, or 2 */
+
+ unsigned int sc_tickflags;
+ #define GE_TICK_TX_IFSTART 0x0001
+ #define GE_TICK_RX_RESTART 0x0002
+ unsigned int sc_flags;
+ #define GE_ALLMULTI 0x0001
+ #define GE_PHYSTSCHG 0x0002
+ #define GE_RXACTIVE 0x0004
+ unsigned sc_pcr; /* current EPCR value */
+ unsigned sc_pcxr; /* current EPCXR value */
+ unsigned sc_intrmask; /* current EIMR value */
+ unsigned sc_idlemask; /* suspended EIMR bits */
+ unsigned sc_max_frame_length; /* maximum frame length */
+ unsigned rx_buf_sz;
+
+ /* Hash table related members */
+ unsigned long long *sc_hashtable;
+ unsigned int sc_hashmask; /* 0x1ff or 0x1fff */
+
+ rtems_id daemonTid;
+ rtems_id daemonSync; /* synchronization with the daemon */
+ /* statistics */
+ struct {
+ volatile unsigned long rxInterrupts;
+
+ volatile unsigned long txInterrupts;
+ unsigned long txMultiBuffPacket;
+ unsigned long txMultiMaxLen;
+ unsigned long txSinglMaxLen;
+ unsigned long txMultiMaxLoop;
+ unsigned long txBuffMaxLen;
+ unsigned long length_errors;
+ unsigned long frame_errors;
+ unsigned long crc_errors;
+ unsigned long or_errors; /* overrun error */
+ } stats;
+};
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/GT64260ethreg.h b/c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/GT64260ethreg.h
new file mode 100644
index 0000000000..efa9ebf0e0
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/GT64260ethreg.h
@@ -0,0 +1,880 @@
+/* $NetBSD: GT64260ethreg.h,v 1.2 2003/03/17 16:41:16 matt Exp $ */
+/* $Id$ */
+
+/*
+ * Copyright (c) 2002 Allegro Networks, Inc., Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Allegro Networks, Inc., and Wasabi Systems, Inc.
+ * 4. The name of Allegro Networks, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * 5. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ALLEGRO NETWORKS, INC. AND
+ * WASABI SYSTEMS, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL EITHER ALLEGRO NETWORKS, INC. OR WASABI SYSTEMS, INC.
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _DEV_GTETHREG_H_
+#define _DEV_GTETHREG_H_
+
+#define ETH__BIT(bit) (1U << (bit))
+#define ETH__LLBIT(bit) (1ULL << (bit))
+#define ETH__MASK(bit) (ETH__BIT(bit) - 1)
+#define ETH__LLMASK(bit) (ETH__LLBIT(bit) - 1)
+#define ETH__GEN(n, off) (0x2400+((n) << 10)+(ETH__ ## off))
+#define ETH__EXT(data, bit, len) (((data) >> (bit)) & ETH__MASK(len))
+#define ETH__LLEXT(data, bit, len) (((data) >> (bit)) & ETH__LLMASK(len))
+#define ETH__CLR(data, bit, len) ((data) &= ~(ETH__MASK(len) << (bit)))
+#define ETH__INS(new, bit) ((new) << (bit))
+#define ETH__LLINS(new, bit) ((unsigned long long)(new) << (bit))
+
+/*
+ * Descriptors used for both receive & transmit data. Note that the descriptor
+ * must start on a 4LW boundary. Since the GT accesses the descriptor as
+ * two 64-bit quantities, we must present them 32bit quantities in the right
+ * order based on endianess.
+ */
+
+struct GTeth_desc {
+#if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN /* for mvme5500 */
+ unsigned ed_lencnt; /* Buffer size is hi 16 bits; Byte count (rx) is lo 16 */
+ unsigned ed_cmdsts; /* command (hi16)/status (lo16) bits */
+ unsigned ed_nxtptr; /* next descriptor (must be 4LW aligned) */
+ unsigned ed_bufptr; /* pointer to packet buffer */
+#endif
+#if defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN
+ unsigned ed_cmdsts; /* command (hi16)/status (lo16) bits */
+ unsigned ed_lencnt; /* length is hi 16 bits; count (rx) is lo 16 */
+ unsigned ed_bufptr; /* pointer to packet buffer */
+ unsigned ed_nxtptr; /* next descriptor (must be 4LW aligned) */
+#endif
+};
+
+/* Ethernet 0 address control (Low), Offset: 0xf200 */
+#define RxBSnoopEn ETH__BIT(6) /* Rx buffer snoop enable,1=enable*/
+#define TxBSnoopEn ETH__BIT(14) /* Tx buffer snoop enable */
+#define RxDSnoopEn ETH__BIT(22) /* Rx descriptor snoop enable */
+#define TxDSnoopEn ETH__BIT(30) /* Tx descriptor snoop enable */
+
+/* Ethernet 0 address control (High), Offset: 0xf204 */
+#define HashSnoopEn ETH__BIT(6) /* Hash Table snoop enable */
+
+/* <skf> */
+#define GT_CUU_Eth0_AddrCtrlLow 0xf200
+#define GT_CUU_Eth0_AddrCtrlHigh 0xf204
+
+/* Table 578: Ethernet TX Descriptor - Command/Status word
+ * All bits except F, EI, AM, O are only valid if TX_CMD_L is also set,
+ * otherwise should be 0 (tx).
+ */
+
+#define TX_STS_LC ETH__BIT(5) /* Late Collision */
+#define TX_STS_UR ETH__BIT(6) /* Underrun error */
+#define TX_STS_RL ETH__BIT(8) /* Retransmit Limit (excession coll) */
+#define TX_STS_COL ETH__BIT(9) /* Collision Occurred */
+#define TX_STS_RC(v) ETH__GETBITS(v, 10, 4) /* Retransmit Count */
+#define TX_STS_ES ETH__BIT(15) /* Error Summary (LC|UR|RL) */
+#define TX_CMD_L ETH__BIT(16) /* Last - End Of Packet */
+#define TX_CMD_F ETH__BIT(17) /* First - Start Of Packet */
+#define TX_CMD_P ETH__BIT(18) /* Pad Packet */
+#define TX_CMD_GC ETH__BIT(22) /* Generate CRC */
+#define TX_CMD_EI ETH__BIT(23) /* Enable Interrupt */
+#define TX_CMD_AM ETH__BIT(30) /* Auto Mode */
+#define TX_CMD_O ETH__BIT(31) /* Ownership (1=GT 0=CPU) */
+
+#define TX_CMD_FIRST (TX_CMD_F|TX_CMD_O)
+#define TX_CMD_LAST (TX_CMD_L|TX_CMD_GC|TX_CMD_P|TX_CMD_O)
+
+/* Table 608: Ethernet RX Descriptor - Command/Status Word
+ * All bits except F, EI, AM, O are only valid if RX_CMD_L is also set,
+ * otherwise should be ignored (rx).
+ */
+#define RX_STS_CE ETH__BIT(0) /* CRC Error */
+#define RX_STS_COL ETH__BIT(1) /* Collision sensed during reception */
+#define RX_STS_LC ETH__BIT(5) /* Late Collision (Reserved) */
+#define RX_STS_OR ETH__BIT(6) /* Overrun Error */
+#define RX_STS_MFL ETH__BIT(7) /* Max Frame Len Error */
+#define RX_STS_SF ETH__BIT(8) /* Short Frame Error (< 64 bytes) */
+#define RX_STS_FT ETH__BIT(11) /* Frame Type (1 = 802.3) */
+#define RX_STS_M ETH__BIT(12) /* Missed Frame */
+#define RX_STS_HE ETH__BIT(13) /* Hash Expired (manual match) */
+#define RX_STS_IGMP ETH__BIT(14) /* IGMP Packet */
+#define RX_STS_ES ETH__BIT(15) /* Error Summary (CE|COL|LC|OR|MFL|SF) */
+#define RX_CMD_L ETH__BIT(16) /* Last - End Of Packet */
+#define RX_CMD_F ETH__BIT(17) /* First - Start Of Packet */
+#define RX_CMD_EI ETH__BIT(23) /* Enable Interrupt */
+#define RX_CMD_AM ETH__BIT(30) /* Auto Mode */
+#define RX_CMD_O ETH__BIT(31) /* Ownership (1=GT 0=CPU) */
+
+/* Table 586: Hash Table Entry Fields
+ */
+#define HSH_V ETH__LLBIT(0) /* Entry is valid */
+#define HSH_S ETH__LLBIT(1) /* Skip this entry */
+#define HSH_RD ETH__LLBIT(2) /* Receive(1) / Discard (0) */
+#define HSH_R ETH__LLBIT(2) /* Receive(1) */
+#define HSH_PRIO_GET(v) ETH__LLEXT(v, 51, 2)
+#define HSH_PRIO_INS(v) ETH__LLINS(v, 51)
+#define HSH_ADDR_MASK 0x7fffff8LLU
+#define HSH_LIMIT 12
+
+
+#define ETH_EPAR 0x2000 /* PHY Address Register */
+#define ETH_ESMIR 0x2010 /* SMI Register */
+
+#define ETH_BASE_ETH0 0x2400 /* Ethernet0 Register Base */
+#define ETH_BASE_ETH1 0x2800 /* Ethernet1 Register Base */
+#define ETH_BASE_ETH2 0x2c00 /* Ethernet2 Register Base */
+#define ETH_SIZE 0x0400 /* Register Space */
+
+#define ETH__EBASE 0x0000 /* Base of Registers */
+#define ETH__EPCR 0x0000 /* Port Config. Register */
+#define ETH__EPCXR 0x0008 /* Port Config. Extend Reg */
+#define ETH__EPCMR 0x0010 /* Port Command Register */
+#define ETH__EPSR 0x0018 /* Port Status Register */
+#define ETH__ESPR 0x0020 /* Port Serial Parameters Reg */
+#define ETH__EHTPR 0x0028 /* Port Hash Table Pointer Reg*/
+#define ETH__EFCSAL 0x0030 /* Flow Control Src Addr Low */
+#define ETH__EFCSAH 0x0038 /* Flow Control Src Addr High */
+#define ETH__ESDCR 0x0040 /* SDMA Configuration Reg */
+#define ETH__ESDCMR 0x0048 /* SDMA Command Register */
+#define ETH__EICR 0x0050 /* Interrupt Cause Register */
+#define ETH__EIMR 0x0058 /* Interrupt Mask Register */
+#define ETH__EFRDP0 0x0080 /* First Rx Desc Pointer 0 */
+#define ETH__EFRDP1 0x0084 /* First Rx Desc Pointer 1 */
+#define ETH__EFRDP2 0x0088 /* First Rx Desc Pointer 2 */
+#define ETH__EFRDP3 0x008c /* First Rx Desc Pointer 3 */
+#define ETH__ECRDP0 0x00a0 /* Current Rx Desc Pointer 0 */
+#define ETH__ECRDP1 0x00a4 /* Current Rx Desc Pointer 1 */
+#define ETH__ECRDP2 0x00a8 /* Current Rx Desc Pointer 2 */
+#define ETH__ECRDP3 0x00ac /* Current Rx Desc Pointer 3 */
+#define ETH__ECTDP0 0x00e0 /* Current Tx Desc Pointer 0 */
+#define ETH__ECTDP1 0x00e4 /* Current Tx Desc Pointer 1 */
+#define ETH__EDSCP2P0L 0x0060 /* IP Differentiated Services
+ CodePoint to Priority0 low */
+#define ETH__EDSCP2P0H 0x0064 /* IP Differentiated Services
+ CodePoint to Priority0 high*/
+#define ETH__EDSCP2P1L 0x0068 /* IP Differentiated Services
+ CodePoint to Priority1 low */
+#define ETH__EDSCP2P1H 0x006c /* IP Differentiated Services
+ CodePoint to Priority1 high*/
+#define ETH__EVPT2P 0x0068 /* VLAN Prio. Tag to Priority */
+#define ETH__EMIBCTRS 0x0100 /* MIB Counters */
+
+/* SKF : we are only concerned with the Ethernet0 for the mvme5500 board */
+#define ETH0_EBASE 0x2400 /* Base of Registers */
+#define ETH0_EPCR 0x2400 /* Port Config. Register */
+#define ETH0_EPCXR 0x2408 /* Port Config. Extend Reg */
+#define ETH0_EPCMR 0x2410 /* Port Command Register */
+#define ETH0_EPSR 0x2418 /* Port Status Register */
+#define ETH0_ESPR 0x2420 /* Port Serial Parameters Reg */
+#define ETH0_EHTPR 0x2428 /* Port Hash Table Pointer Reg*/
+#define ETH0_EFCSAL 0x2430 /* Flow Control Src Addr Low */
+#define ETH0_EFCSAH 0x2438 /* Flow Control Src Addr High */
+#define ETH0_ESDCR 0x2440 /* SDMA Configuration Reg */
+#define ETH0_ESDCMR 0x2448 /* SDMA Command Register */
+#define ETH0_EICR 0x2450 /* Interrupt Cause Register */
+#define ETH0_EIMR 0x2458 /* Interrupt Mask Register */
+#define ETH0_EFRDP0 0x2480 /* First Rx Desc Pointer 0 */
+#define ETH0_EFRDP1 0x2484 /* First Rx Desc Pointer 1 */
+#define ETH0_EFRDP2 0x2488 /* First Rx Desc Pointer 2 */
+#define ETH0_EFRDP3 0x248c /* First Rx Desc Pointer 3 */
+#define ETH0_ECRDP0 0x24a0 /* Current Rx Desc Pointer 0 */
+#define ETH0_ECRDP1 0x24a4 /* Current Rx Desc Pointer 1 */
+#define ETH0_ECRDP2 0x24a8 /* Current Rx Desc Pointer 2 */
+#define ETH0_ECRDP3 0x24ac /* Current Rx Desc Pointer 3 */
+#define ETH0_ECTDP0 0x24e0 /* Current Tx Desc Pointer 0 */
+#define ETH0_ECTDP1 0x24e4 /* Current Tx Desc Pointer 1 */
+#define ETH0_EDSCP2P0L 0x2460 /* IP Differentiated Services
+ CodePoint to Priority0 low */
+#define ETH0_EDSCP2P0H 0x2464 /* IP Differentiated Services
+ CodePoint to Priority0 high*/
+#define ETH0_EDSCP2P1L 0x2468 /* IP Differentiated Services
+ CodePoint to Priority1 low */
+#define ETH0_EDSCP2P1H 0x246c /* IP Differentiated Services
+ CodePoint to Priority1 high*/
+#define ETH0_EVPT2P 0x2468 /* VLAN Prio. Tag to Priority */
+#define ETH0_EMIBCTRS 0x2500 /* MIB Counters */
+
+#define ETH_BASE(n) ETH__GEN(n, EBASE)
+#define ETH_EPCR(n) ETH__GEN(n, EPCR) /* Port Config. Register */
+#define ETH_EPCXR(n) ETH__GEN(n, EPCXR) /* Port Config. Extend Reg */
+#define ETH_EPCMR(n) ETH__GEN(n, EPCMR) /* Port Command Register */
+#define ETH_EPSR(n) ETH__GEN(n, EPSR) /* Port Status Register */
+#define ETH_ESPR(n) ETH__GEN(n, ESPR) /* Port Serial Parameters Reg */
+#define ETH_EHTPR(n) ETH__GEN(n, EHPTR) /* Port Hash Table Pointer Reg*/
+#define ETH_EFCSAL(n) ETH__GEN(n, EFCSAL) /* Flow Control Src Addr Low */
+#define ETH_EFCSAH(n) ETH__GEN(n, EFCSAH) /* Flow Control Src Addr High */
+#define ETH_ESDCR(n) ETH__GEN(n, ESDCR) /* SDMA Configuration Reg */
+#define ETH_ESDCMR(n) ETH__GEN(n, ESDCMR) /* SDMA Command Register */
+#define ETH_EICR(n) ETH__GEN(n, EICR) /* Interrupt Cause Register */
+#define ETH_EIMR(n) ETH__GEN(n, EIMR) /* Interrupt Mask Register */
+#define ETH_EFRDP0(n) ETH__GEN(n, EFRDP0) /* First Rx Desc Pointer 0 */
+#define ETH_EFRDP1(n) ETH__GEN(n, EFRDP1) /* First Rx Desc Pointer 1 */
+#define ETH_EFRDP2(n) ETH__GEN(n, EFRDP2) /* First Rx Desc Pointer 2 */
+#define ETH_EFRDP3(n) ETH__GEN(n, EFRDP3) /* First Rx Desc Pointer 3 */
+#define ETH_ECRDP0(n) ETH__GEN(n, ECRDP0) /* Current Rx Desc Pointer 0 */
+#define ETH_ECRDP1(n) ETH__GEN(n, ECRDP1) /* Current Rx Desc Pointer 1 */
+#define ETH_ECRDP2(n) ETH__GEN(n, ECRDP2) /* Current Rx Desc Pointer 2 */
+#define ETH_ECRDP3(n) ETH__GEN(n, ECRDP3) /* Current Rx Desc Pointer 3 */
+#define ETH_ECTDP0(n) ETH__GEN(n, ECTDP0) /* Current Tx Desc Pointer 0 */
+#define ETH_ECTDP1(n) ETH__GEN(n, ECTDP1) /* Current Tx Desc Pointer 1 */
+#define ETH_EDSCP2P0L(n) ETH__GEN(n, EDSCP2P0L) /* IP Differentiated Services
+ CodePoint to Priority0 low */
+#define ETH_EDSCP2P0H(n) ETH__GEN(n, EDSCP2P0H) /* IP Differentiated Services
+ CodePoint to Priority0 high*/
+#define ETH_EDSCP2P1L(n) ETH__GEN(n, EDSCP2P1L) /* IP Differentiated Services
+ CodePoint to Priority1 low */
+#define ETH_EDSCP2P1H(n) ETH__GEN(n, EDSCP1P1H) /* IP Differentiated Services
+ CodePoint to Priority1 high*/
+#define ETH_EVPT2P(n) ETH__GEN(n, EVPT2P) /* VLAN Prio. Tag to Priority */
+#define ETH_EMIBCTRS(n) ETH__GEN(n, EMIBCTRS) /* MIB Counters */
+
+#define ETH_EPAR_PhyAD_GET(v, n) (((v) >> ((n) * 5)) & 0x1f)
+
+#define ETH_ESMIR_READ(phy, reg) (ETH__INS(phy, 16)|\
+ ETH__INS(reg, 21)|\
+ ETH_ESMIR_ReadOpcode)
+#define ETH_ESMIR_WRITE(phy, reg, val) (ETH__INS(phy, 16)|\
+ ETH__INS(reg, 21)|\
+ ETH__INS(val, 0)|\
+ ETH_ESMIR_WriteOpcode)
+#define ETH_ESMIR_Value_GET(v) ETH__EXT(v, 0, 16)
+#define ETH_ESMIR_WriteOpcode 0
+#define ETH_ESMIR_ReadOpcode ETH__BIT(26)
+#define ETH_ESMIR_ReadValid ETH__BIT(27)
+#define ETH_ESMIR_Busy ETH__BIT(28)
+
+/*
+ * Table 597: Port Configuration Register (PCR)
+ * 00:00 PM Promiscuous mode
+ * 0: Normal mode (Frames are only received if the
+ * destination address is found in the hash
+ * table)
+ * 1: Promiscuous mode (Frames are received
+ * regardless of their destination address.
+ * Errored frames are discarded unless the Port
+ * Configuration register's PBF bit is set)
+ * 01:01 RBM Reject Broadcast Mode
+ * 0: Receive broadcast address
+ * 1: Reject frames with broadcast address
+ * Overridden by the promiscuous mode.
+ * 02:02 PBF Pass Bad Frames
+ * (0: Normal mode, 1: Pass bad Frames)
+ * The Ethernet receiver passes to the CPU errored
+ * frames (like fragments and collided packets)
+ * that are normally rejected.
+ * NOTE: Frames are only passed if they
+ * successfully pass address filtering.
+ * 06:03 Reserved
+ * 07:07 EN Enable (0: Disabled, 1: Enable)
+ * When enabled, the ethernet port is ready to
+ * transmit/receive.
+ * 09:08 LPBK Loop Back Mode
+ * 00: Normal mode
+ * 01: Internal loop back mode (TX data is looped
+ * back to the RX lines. No transition is seen
+ * on the interface pins)
+ * 10: External loop back mode (TX data is looped
+ * back to the RX lines and also transmitted
+ * out to the MII interface pins)
+ * 11: Reserved
+ * 10:10 FC Force Collision
+ * 0: Normal mode.
+ * 1: Force Collision on any TX frame.
+ * For RXM test (in Loopback mode).
+ * 11:11 Reserved.
+ * 12:12 HS Hash Size
+ * 0: 8K address filtering
+ * (256KB of memory space required).
+ * 1: 512 address filtering
+ * ( 16KB of memory space required).
+ * 13:13 HM Hash Mode (0: Hash Func. 0; 1: Hash Func. 1)
+ * 14:14 HDM Hash Default Mode
+ * 0: Discard addresses not found in address table
+ * 1: Pass addresses not found in address table
+ * 15:15 HD Duplex Mode (0: Half Duplex, 1: Full Duplex)
+ * NOTE: Valid only when auto-negotiation for
+ * duplex mode is disabled.
+ * 30:16 Reserved
+ * 31:31 ACCS Accelerate Slot Time
+ * (0: Normal mode, 1: Reserved)
+ */
+#define ETH_EPCR_PM ETH__BIT(0)
+#define ETH_EPCR_RBM ETH__BIT(1)
+#define ETH_EPCR_PBF ETH__BIT(2)
+#define ETH_EPCR_EN ETH__BIT(7)
+#define ETH_EPCR_LPBK_GET(v) ETH__BIT(v, 8, 2)
+#define ETH_EPCR_LPBK_Normal 0
+#define ETH_EPCR_LPBK_Internal 1
+#define ETH_EPCR_LPBK_External 2
+#define ETH_EPCR_FC ETH__BIT(10)
+
+#define ETH_EPCR_HS ETH__BIT(12)
+#define ETH_EPCR_HS_8K 0
+#define ETH_EPCR_HS_512 ETH_EPCR_HS
+
+#define ETH_EPCR_HM ETH__BIT(13)
+#define ETH_EPCR_HM_0 0
+#define ETH_EPCR_HM_1 ETH_EPCR_HM
+
+#define ETH_EPCR_HDM ETH__BIT(14)
+#define ETH_EPCR_HDM_Discard 0
+#define ETH_EPCR_HDM_Pass ETH_EPCR_HDM
+
+#define ETH_EPCR_HD_Half 0
+#define ETH_EPCR_HD_Full ETH_EPCR_HD_Full
+
+#define ETH_EPCR_ACCS ETH__BIT(31)
+
+
+
+/*
+ * Table 598: Port Configuration Extend Register (PCXR)
+ * 00:00 IGMP IGMP Packets Capture Enable
+ * 0: IGMP packets are treated as normal Multicast
+ * packets.
+ * 1: IGMP packets on IPv4/Ipv6 over Ethernet/802.3
+ * are trapped and sent to high priority RX
+ * queue.
+ * 01:01 SPAN Spanning Tree Packets Capture Enable
+ * 0: BPDU (Bridge Protocol Data Unit) packets are
+ * treated as normal Multicast packets.
+ * 1: BPDU packets are trapped and sent to high
+ * priority RX queue.
+ * 02:02 PAR Partition Enable (0: Normal, 1: Partition)
+ * When more than 61 collisions occur while
+ * transmitting, the port enters Partition mode.
+ * It waits for the first good packet from the
+ * wire and then goes back to Normal mode. Under
+ * Partition mode it continues transmitting, but
+ * it does not receive.
+ * 05:03 PRIOtx Priority weight in the round-robin between high
+ * and low priority TX queues.
+ * 000: 1 pkt from HIGH, 1 pkt from LOW.
+ * 001: 2 pkt from HIGH, 1 pkt from LOW.
+ * 010: 4 pkt from HIGH, 1 pkt from LOW.
+ * 011: 6 pkt from HIGH, 1 pkt from LOW.
+ * 100: 8 pkt from HIGH, 1 pkt from LOW.
+ * 101: 10 pkt from HIGH, 1 pkt from LOW.
+ * 110: 12 pkt from HIGH, 1 pkt from LOW.
+ * 111: All pkt from HIGH, 0 pkt from LOW. LOW is
+ * served only if HIGH is empty.
+ * NOTE: If the HIGH queue is emptied before
+ * finishing the count, the count is reset
+ * until the next first HIGH comes in.
+ * 07:06 PRIOrx Default Priority for Packets Received on this
+ * Port (00: Lowest priority, 11: Highest priority)
+ * 08:08 PRIOrx_Override Override Priority for Packets Received on this
+ * Port (0: Do not override, 1: Override with
+ * <PRIOrx> field)
+ * 09:09 DPLXen Enable Auto-negotiation for Duplex Mode
+ * (0: Enable, 1: Disable)
+ * 11:10 FCTLen Enable Auto-negotiation for 802.3x Flow-control
+ * 0: Enable; When enabled, 1 is written (through
+ * SMI access) to the PHY's register 4 bit 10
+ * to advertise flow-control capability.
+ * 1: Disable; Only enables flow control after the
+ * PHY address is set by the CPU. When changing
+ * the PHY address the flow control
+ * auto-negotiation must be disabled.
+ * 11:11 FLP Force Link Pass
+ * (0: Force Link Pass, 1: Do NOT Force Link pass)
+ * 12:12 FCTL 802.3x Flow-Control Mode (0: Enable, 1: Disable)
+ * NOTE: Only valid when auto negotiation for flow
+ * control is disabled.
+ * 13:13 Reserved
+ * 15:14 MFL Max Frame Length
+ * Maximum packet allowed for reception (including
+ * CRC): 00: 1518 bytes, 01: 1536 bytes,
+ * 10: 2048 bytes, 11: 64K bytes
+ * 16:16 MIBclrMode MIB Counters Clear Mode (0: Clear, 1: No effect)
+ * 17:17 MIBctrMode Reserved. (MBZ)
+ * 18:18 Speed Port Speed (0: 10Mbit/Sec, 1: 100Mbit/Sec)
+ * NOTE: Only valid if SpeedEn bit is set.
+ * 19:19 SpeedEn Enable Auto-negotiation for Speed
+ * (0: Enable, 1: Disable)
+ * 20:20 RMIIen RMII enable
+ * 0: Port functions as MII port
+ * 1: Port functions as RMII port
+ * 21:21 DSCPen DSCP enable
+ * 0: IP DSCP field decoding is disabled.
+ * 1: IP DSCP field decoding is enabled.
+ * 31:22 Reserved
+ */
+#define ETH_EPCXR_IGMP ETH__BIT(0)
+#define ETH_EPCXR_SPAN ETH__BIT(1)
+#define ETH_EPCXR_PAR ETH__BIT(2)
+#define ETH_EPCXR_PRIOtx_GET(v) ETH__EXT(v, 3, 3)
+#define ETH_EPCXR_PRIOrx_GET(v) ETH__EXT(v, 3, 3)
+#define ETH_EPCXR_PRIOrx_Override ETH__BIT(8)
+#define ETH_EPCXR_DLPXen ETH__BIT(9)
+#define ETH_EPCXR_FCTLen ETH__BIT(10)
+#define ETH_EPCXR_FLP ETH__BIT(11)
+#define ETH_EPCXR_FCTL ETH__BIT(12)
+#define ETH_EPCXR_MFL_GET(v) ETH__EXT(v, 14, 2)
+#define ETH_EPCXR_MFL_1518 0
+#define ETH_EPCXR_MFL_1536 1
+#define ETH_EPCXR_MFL_2048 2
+#define ETH_EPCXR_MFL_64K 3
+#define ETH_EPCXR_MIBclrMode ETH__BIT(16)
+#define ETH_EPCXR_MIBctrMode ETH__BIT(17)
+#define ETH_EPCXR_Speed ETH__BIT(18)
+#define ETH_EPCXR_SpeedEn ETH__BIT(19)
+#define ETH_EPCXR_RMIIEn ETH__BIT(20)
+#define ETH_EPCXR_DSCPEn ETH__BIT(21)
+
+
+
+/*
+ * Table 599: Port Command Register (PCMR)
+ * 14:00 Reserved
+ * 15:15 FJ Force Jam / Flow Control
+ * When in half-duplex mode, the CPU uses this bit
+ * to force collisions on the Ethernet segment.
+ * When the CPU recognizes that it is going to run
+ * out of receive buffers, it can force the
+ * transmitter to send jam frames, forcing
+ * collisions on the wire. To allow transmission
+ * on the Ethernet segment, the CPU must clear the
+ * FJ bit when more resources are available. When
+ * in full-duplex and flow-control is enabled, this
+ * bit causes the port's transmitter to send
+ * flow-control PAUSE packets. The CPU must reset
+ * this bit when more resources are available.
+ * 31:16 Reserved
+ */
+
+#define ETH_EPCMR_FJ ETH__BIT(15)
+
+
+/*
+ * Table 600: Port Status Register (PSR) -- Read Only
+ * 00:00 Speed Indicates Port Speed (0: 10Mbs, 1: 100Mbs)
+ * 01:01 Duplex Indicates Port Duplex Mode (0: Half, 1: Full)
+ * 02:02 Fctl Indicates Flow-control Mode
+ * (0: enabled, 1: disabled)
+ * 03:03 Link Indicates Link Status (0: down, 1: up)
+ * 04:04 Pause Indicates that the port is in flow-control
+ * disabled state. This bit is set when an IEEE
+ * 802.3x flow-control PAUSE (XOFF) packet is
+ * received (assuming that flow-control is
+ * enabled and the port is in full-duplex mode).
+ * Reset when XON is received, or when the XOFF
+ * timer has expired.
+ * 05:05 TxLow Tx Low Priority Status
+ * Indicates the status of the low priority
+ * transmit queue: (0: Stopped, 1: Running)
+ * 06:06 TxHigh Tx High Priority Status
+ * Indicates the status of the high priority
+ * transmit queue: (0: Stopped, 1: Running)
+ * 07:07 TXinProg TX in Progress
+ * Indicates that the port's transmitter is in an
+ * active transmission state.
+ * 31:08 Reserved
+ */
+#define ETH_EPSR_Speed ETH__BIT(0)
+#define ETH_EPSR_Duplex ETH__BIT(1)
+#define ETH_EPSR_Fctl ETH__BIT(2)
+#define ETH_EPSR_Link ETH__BIT(3)
+#define ETH_EPSR_Pause ETH__BIT(4)
+#define ETH_EPSR_TxLow ETH__BIT(5)
+#define ETH_EPSR_TxHigh ETH__BIT(6)
+#define ETH_EPSR_TXinProg ETH__BIT(7)
+
+
+/*
+ * Table 601: Serial Parameters Register (SPR)
+ * 01:00 JAM_LENGTH Two bits to determine the JAM Length
+ * (in Backpressure) as follows:
+ * 00 = 12K bit-times
+ * 01 = 24K bit-times
+ * 10 = 32K bit-times
+ * 11 = 48K bit-times
+ * 06:02 JAM_IPG Five bits to determine the JAM IPG.
+ * The step is four bit-times. The value may vary
+ * between 4 bit time to 124.
+ * 11:07 IPG_JAM_TO_DATA Five bits to determine the IPG JAM to DATA.
+ * The step is four bit-times. The value may vary
+ * between 4 bit time to 124.
+ * 16:12 IPG_DATA Inter-Packet Gap (IPG)
+ * The step is four bit-times. The value may vary
+ * between 12 bit time to 124.
+ * NOTE: These bits may be changed only when the
+ * Ethernet ports is disabled.
+ * 21:17 Data_Blind Data Blinder
+ * The number of nibbles from the beginning of the
+ * IPG, in which the IPG counter is restarted when
+ * detecting a carrier activity. Following this
+ * value, the port enters the Data Blinder zone and
+ * does not reset the IPG counter. This ensures
+ * fair access to the medium.
+ * The default is 10 hex (64 bit times - 2/3 of the
+ * default IPG). The step is 4 bit-times. Valid
+ * range is 3 to 1F hex nibbles.
+ * NOTE: These bits may be only changed when the
+ * Ethernet port is disabled.
+ * 22:22 Limit4 The number of consecutive packet collisions that
+ * occur before the collision counter is reset.
+ * 0: The port resets its collision counter after
+ * 16 consecutive retransmit trials and
+ * restarts the Backoff algorithm.
+ * 1: The port resets its collision counter and
+ * restarts the Backoff algorithm after 4
+ * consecutive transmit trials.
+ * 31:23 Reserved
+ */
+#define ETH_ESPR_JAM_LENGTH_GET(v) ETH__EXT(v, 0, 2)
+#define ETH_ESPR_JAM_IPG_GET(v) ETH__EXT(v, 2, 5)
+#define ETH_ESPR_IPG_JAM_TO_DATA_GET(v) ETH__EXT(v, 7, 5)
+#define ETH_ESPR_IPG_DATA_GET(v) ETH__EXT(v, 12, 5)
+#define ETH_ESPR_Data_Bilnd_GET(v) ETH__EXT(v, 17, 5)
+#define ETH_ESPR_Limit4(v) ETH__BIT(22)
+
+/*
+ * Table 602: Hash Table Pointer Register (HTPR)
+ * 31:00 HTP 32-bit pointer to the address table.
+ * Bits [2:0] must be set to zero.
+ */
+
+/*
+ * Table 603: Flow Control Source Address Low (FCSAL)
+ * 15:0 SA[15:0] Source Address
+ * The least significant bits of the source
+ * address for the port. This address is used for
+ * Flow Control.
+ * 31:16 Reserved
+ */
+
+/*
+ * Table 604: Flow Control Source Address High (FCSAH)
+ * 31:0 SA[47:16] Source Address
+ * The most significant bits of the source address
+ * for the port. This address is used for Flow
+ * Control.
+ */
+
+
+/*
+ * Table 605: SDMA Configuration Register (SDCR)
+ * 01:00 Reserved
+ * 05:02 RC Retransmit Count
+ * Sets the maximum number of retransmits per
+ * packet. After executing retransmit for RC
+ * times, the TX SDMA closes the descriptor with a
+ * Retransmit Limit error indication and processes
+ * the next packet. When RC is set to 0, the
+ * number of retransmits is unlimited. In this
+ * case, the retransmit process is only terminated
+ * if CPU issues an Abort command.
+ * 06:06 BLMR Big/Little Endian Receive Mode
+ * The DMA supports Big or Little Endian
+ * configurations on a per channel basis. The BLMR
+ * bit only affects data transfer to memory.
+ * 0: Big Endian
+ * 1: Little Endian
+ * 07:07 BLMT Big/Little Endian Transmit Mode
+ * The DMA supports Big or Little Endian
+ * configurations on a per channel basis. The BLMT
+ * bit only affects data transfer from memory.
+ * 0: Big Endian
+ * 1: Little Endian
+ * 08:08 POVR PCI Override
+ * When set, causes the SDMA to direct all its
+ * accesses in PCI_0 direction and overrides
+ * normal address decoding process.
+ * 09:09 RIFB Receive Interrupt on Frame Boundaries
+ * When set, the SDMA Rx generates interrupts only
+ * on frame boundaries (i.e. after writing the
+ * frame status to the descriptor).
+ * 11:10 Reserved
+ * 13:12 BSZ Burst Size
+ * Sets the maximum burst size for SDMA
+ * transactions:
+ * 00: Burst is limited to 1 64bit words.
+ * 01: Burst is limited to 2 64bit words.
+ * 10: Burst is limited to 4 64bit words.
+ * 11: Burst is limited to 8 64bit words.
+ * 31:14 Reserved
+ */
+#define ETH_ESDCR_RC_GET(v) ETH__EXT(v, 2, 4)
+#define ETH_ESDCR_BLMR ETH__BIT(6)
+#define ETH_ESDCR_BLMT ETH__BIT(7)
+#define ETH_ESDCR_POVR ETH__BIT(8)
+#define ETH_ESDCR_RIFB ETH__BIT(9)
+#define ETH_ESDCR_BSZ_GET(v) ETH__EXT(v, 12, 2)
+#define ETH_ESDCR_BSZ_SET(v, n) (ETH__CLR(v, 12, 2),\
+ (v) |= ETH__INS(n, 12))
+#define ETH_ESDCR_BSZ_1 0
+#define ETH_ESDCR_BSZ_2 1
+#define ETH_ESDCR_BSZ_4 2
+#define ETH_ESDCR_BSZ_8 3
+
+#define ETH_ESDCR_BSZ_Strings { "1 64-bit word", "2 64-bit words", \
+ "4 64-bit words", "8 64-bit words" }
+
+/*
+ * Table 606: SDMA Command Register (SDCMR)
+ * 06:00 Reserved
+ * 07:07 ERD Enable RX DMA.
+ * Set to 1 by the CPU to cause the SDMA to start
+ * a receive process. Cleared when the CPU issues
+ * an Abort Receive command.
+ * 14:08 Reserved
+ * 15:15 AR Abort Receive
+ * Set to 1 by the CPU to abort a receive SDMA
+ * operation. When the AR bit is set, the SDMA
+ * aborts its current operation and moves to IDLE.
+ * No descriptor is closed. The AR bit is cleared
+ * upon entering IDLE. After setting the AR bit,
+ * the CPU must poll the bit to verify that the
+ * abort sequence is completed.
+ * 16:16 STDH Stop TX High
+ * Set to 1 by the CPU to stop the transmission
+ * process from the high priority queue at the end
+ * of the current frame. An interrupt is generated
+ * when the stop command has been executed.
+ * Writing 1 to STDH resets TXDH bit.
+ * Writing 0 to this bit has no effect.
+ * 17:17 STDL Stop TX Low
+ * Set to 1 by the CPU to stop the transmission
+ * process from the low priority queue at the end
+ * of the current frame. An interrupt is generated
+ * when the stop command has been executed.
+ * Writing 1 to STDL resets TXDL bit.
+ * Writing 0 to this bit has no effect.
+ * 22:18 Reserved
+ * 23:23 TXDH Start Tx High
+ * Set to 1 by the CPU to cause the SDMA to fetch
+ * the first descriptor and start a transmit
+ * process from the high priority Tx queue.
+ * Writing 1 to TXDH resets STDH bit.
+ * Writing 0 to this bit has no effect.
+ * 24:24 TXDL Start Tx Low
+ * Set to 1 by the CPU to cause the SDMA to fetch
+ * the first descriptor and start a transmit
+ * process from the low priority Tx queue.
+ * Writing 1 to TXDL resets STDL bit.
+ * Writing 0 to this bit has no effect.
+ * 30:25 Reserved
+ * 31:31 AT Abort Transmit
+ * Set to 1 by the CPU to abort a transmit DMA
+ * operation. When the AT bit is set, the SDMA
+ * aborts its current operation and moves to IDLE.
+ * No descriptor is closed. Cleared upon entering
+ * IDLE. After setting AT bit, the CPU must poll
+ * it in order to verify that the abort sequence
+ * is completed.
+ */
+#define ETH_ESDCMR_ERD ETH__BIT(7)
+#define ETH_ESDCMR_AR ETH__BIT(15)
+#define ETH_ESDCMR_STDH ETH__BIT(16)
+#define ETH_ESDCMR_STDL ETH__BIT(17)
+#define ETH_ESDCMR_TXDH ETH__BIT(23)
+#define ETH_ESDCMR_TXDL ETH__BIT(24)
+#define ETH_ESDCMR_AT ETH__BIT(31)
+
+/*
+ * Table 607: Interrupt Cause Register (ICR)
+ * 00:00 RxBuffer Rx Buffer Return
+ * Indicates an Rx buffer returned to CPU ownership
+ * or that the port finished reception of a Rx
+ * frame in either priority queues.
+ * NOTE: In order to get a Rx Buffer return per
+ * priority queue, use bit 19:16. This bit is
+ * set upon closing any Rx descriptor which
+ * has its EI bit set. To limit the
+ * interrupts to frame (rather than buffer)
+ * boundaries, the user must set SDMA
+ * Configuration register's RIFB bit. When
+ * the RIFB bit is set, an interrupt
+ * generates only upon closing the first
+ * descriptor of a received packet, if this
+ * descriptor has it EI bit set.
+ * 01:01 Reserved
+ * 02:02 TxBufferHigh Tx Buffer for High priority Queue
+ * Indicates a Tx buffer returned to CPU ownership
+ * or that the port finished transmission of a Tx
+ * frame.
+ * NOTE: This bit is set upon closing any Tx
+ * descriptor which has its EI bit set. To
+ * limit the interrupts to frame (rather than
+ * buffer) boundaries, the user must set EI
+ * only in the last descriptor.
+ * 03:03 TxBufferLow Tx Buffer for Low Priority Queue
+ * Indicates a Tx buffer returned to CPU ownership
+ * or that the port finished transmission of a Tx
+ * frame.
+ * NOTE: This bit is set upon closing any Tx
+ * descriptor which has its EI bit set. To
+ * limit the interrupts to frame (rather than
+ * buffer) boundaries, the user must set EI
+ * only in the last descriptor.
+ * 05:04 Reserved
+ * 06:06 TxEndHigh Tx End for High Priority Queue
+ * Indicates that the Tx DMA stopped processing the
+ * high priority queue after stop command, or that
+ * it reached the end of the high priority
+ * descriptor chain.
+ * 07:07 TxEndLow Tx End for Low Priority Queue
+ * Indicates that the Tx DMA stopped processing the
+ * low priority queue after stop command, or that
+ * it reached the end of the low priority
+ * descriptor chain.
+ * 08:08 RxError Rx Resource Error
+ * Indicates a Rx resource error event in one of
+ * the priority queues.
+ * NOTE: To get a Rx Resource Error Indication per
+ * priority queue, use bit 23:20.
+ * 09:09 Reserved
+ * 10:10 TxErrorHigh Tx Resource Error for High Priority Queue
+ * Indicates a Tx resource error event during
+ * packet transmission from the high priority queue
+ * 11:11 TxErrorLow Tx Resource Error for Low Priority Queue
+ * Indicates a Tx resource error event during
+ * packet transmission from the low priority queue
+ * 12:12 RxOVR Rx Overrun
+ * Indicates an overrun event that occurred during
+ * reception of a packet.
+ * 13:13 TxUdr Tx Underrun
+ * Indicates an underrun event that occurred during
+ * transmission of packet from either queue.
+ * 15:14 Reserved
+ * 16:16 RxBuffer-Queue[0] Rx Buffer Return in Priority Queue[0]
+ * Indicates a Rx buffer returned to CPU ownership
+ * or that the port completed reception of a Rx
+ * frame in a receive priority queue[0]
+ * 17:17 RxBuffer-Queue[1] Rx Buffer Return in Priority Queue[1]
+ * Indicates a Rx buffer returned to CPU ownership
+ * or that the port completed reception of a Rx
+ * frame in a receive priority queue[1].
+ * 18:18 RxBuffer-Queue[2] Rx Buffer Return in Priority Queue[2]
+ * Indicates a Rx buffer returned to CPU ownership
+ * or that the port completed reception of a Rx
+ * frame in a receive priority queue[2].
+ * 19:19 RxBuffer-Queue[3] Rx Buffer Return in Priority Queue[3]
+ * Indicates a Rx buffer returned to CPU ownership
+ * or that the port completed reception of a Rx
+ * frame in a receive priority queue[3].
+ * 20:20 RxError-Queue[0] Rx Resource Error in Priority Queue[0]
+ * Indicates a Rx resource error event in receive
+ * priority queue[0].
+ * 21:21 RxError-Queue[1] Rx Resource Error in Priority Queue[1]
+ * Indicates a Rx resource error event in receive
+ * priority queue[1].
+ * 22:22 RxError-Queue[2] Rx Resource Error in Priority Queue[2]
+ * Indicates a Rx resource error event in receive
+ * priority queue[2].
+ * 23:23 RxError-Queue[3] Rx Resource Error in Priority Queue[3]
+ * Indicates a Rx resource error event in receive
+ * priority queue[3].
+ * 27:24 Reserved
+ * 28:29 MIIPhySTC MII PHY Status Change
+ * Indicates a status change reported by the PHY
+ * connected to this port. Set when the MII
+ * management interface block identifies a change
+ * in PHY's register 1.
+ * 29:29 SMIdone SMI Command Done
+ * Indicates that the SMI completed a MII
+ * management command (either read or write) that
+ * was initiated by the CPU writing to the SMI
+ * register.
+ * 30:30 Reserved
+ * 31:31 EtherIntSum Ethernet Interrupt Summary
+ * This bit is a logical OR of the (unmasked) bits
+ * [30:04] in the Interrupt Cause register.
+ */
+
+#define ETH_IR_RxBuffer ETH__BIT(0)
+#define ETH_IR_TxBufferHigh ETH__BIT(2)
+#define ETH_IR_TxBufferLow ETH__BIT(3)
+#define ETH_IR_TxEndHigh ETH__BIT(6)
+#define ETH_IR_TxEndLow ETH__BIT(7)
+#define ETH_IR_RxError ETH__BIT(8)
+#define ETH_IR_TxErrorHigh ETH__BIT(10)
+#define ETH_IR_TxErrorLow ETH__BIT(11)
+#define ETH_IR_RxOVR ETH__BIT(12)
+#define ETH_IR_TxUdr ETH__BIT(13)
+#define ETH_IR_RxBuffer_0 ETH__BIT(16)
+#define ETH_IR_RxBuffer_1 ETH__BIT(17)
+#define ETH_IR_RxBuffer_2 ETH__BIT(18)
+#define ETH_IR_RxBuffer_3 ETH__BIT(19)
+#define ETH_IR_RxBuffer_GET(v) ETH__EXT(v, 16, 4)
+#define ETH_IR_RxError_0 ETH__BIT(20)
+#define ETH_IR_RxError_1 ETH__BIT(21)
+#define ETH_IR_RxError_2 ETH__BIT(22)
+#define ETH_IR_RxError_3 ETH__BIT(23)
+#define ETH_IR_RxError_GET(v) ETH__EXT(v, 20, 4)
+#define ETH_IR_RxBits (ETH_IR_RxBuffer_0|\
+ ETH_IR_RxBuffer_1|\
+ ETH_IR_RxBuffer_2|\
+ ETH_IR_RxBuffer_3|\
+ ETH_IR_RxError_0|\
+ ETH_IR_RxError_1|\
+ ETH_IR_RxError_2|\
+ ETH_IR_RxError_3)
+#define ETH_IR_MIIPhySTC ETH__BIT(28)
+#define ETH_IR_SMIdone ETH__BIT(29)
+#define ETH_IR_EtherIntSum (1<<31)
+#define ETH_IR_Summary (1<<31)
+#define ETH_IR_ErrorSum 0x803d00
+#define INTR_RX_ERROR 0x801100
+#define INTR_TX_ERROR 0x002c00
+
+/*
+ * Table 608: Interrupt Mask Register (IMR)
+ * 31:00 Various Mask bits for the Interrupt Cause register.
+ */
+
+/*
+ * Table 609: IP Differentiated Services CodePoint to Priority0 low (DSCP2P0L),
+ * 31:00 Priority0_low The LSB priority bits for DSCP[31:0] entries.
+ */
+
+/*
+ * Table 610: IP Differentiated Services CodePoint to Priority0 high (DSCP2P0H)
+ * 31:00 Priority0_high The LSB priority bits for DSCP[63:32] entries.
+ */
+
+/*
+ * Table 611: IP Differentiated Services CodePoint to Priority1 low (DSCP2P1L)
+ * 31:00 Priority1_low The MSB priority bits for DSCP[31:0] entries.
+ */
+
+/*
+ * Table 612: IP Differentiated Services CodePoint to Priority1 high (DSCP2P1H)
+ * 31:00 Priority1_high The MSB priority bit for DSCP[63:32] entries.
+ */
+
+/*
+ * Table 613: VLAN Priority Tag to Priority (VPT2P)
+ * 07:00 Priority0 The LSB priority bits for VLAN Priority[7:0]
+ * entries.
+ * 15:08 Priority1 The MSB priority bits for VLAN Priority[7:0]
+ * entries.
+ * 31:16 Reserved
+ */
+#endif /* _DEV_GTETHREG_H_ */
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/Makefile.am b/c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/Makefile.am
new file mode 100644
index 0000000000..1e00aaad5b
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/Makefile.am
@@ -0,0 +1,46 @@
+##
+## $Id$
+##
+
+VPATH = @srcdir@:
+
+INCLUDES = -I @srcdir@/../GT64260
+
+C_FILES = GT64260eth.c
+include_bspdir = $(includedir)/bsp
+include_bsp_HEADERS = GT64260eth.h GT64260ethreg.h
+
+H_FILES = GT64260eth.h GT64260ethreg.h
+
+C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.$(OBJEXT))
+
+EXTRA_DIST = GT64260eth.c
+
+OBJS = $(C_O_FILES)
+
+include $(top_srcdir)/../../../../../../automake/compile.am
+include $(top_srcdir)/../../../../../../automake/lib.am
+
+CFLAGS += -msoft-float
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+$(PROJECT_INCLUDE)/bsp:
+ $(mkinstalldirs) $<
+
+$(PROJECT_INCLUDE)/bsp/GT64260eth.h: GT64260eth.h
+ $(INSTALL_DATA) $< $@
+
+$(PROJECT_INCLUDE)/bsp/GT64260ethreg.h: GT64260ethreg.h
+ $(INSTALL_DATA) $< $@
+
+
+# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
+PREINSTALL_FILES = $(PROJECT_INCLUDE)/bsp $(PROJECT_INCLUDE)/bsp/GT64260eth.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/GT64260ethreg.h
+
+all-local: $(ARCH) $(PREINSTALL_FILES) $(OBJS)
+
+include $(top_srcdir)/../../../../../../automake/local.am
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/Makefile.am b/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/Makefile.am
new file mode 100644
index 0000000000..9511e4822e
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/Makefile.am
@@ -0,0 +1,45 @@
+##
+## $Id$
+##
+
+VPATH = @srcdir@:
+
+INCLUDES = -I @srcdir@/../GT64260
+
+C_FILES = if_wm.c pci_map.c
+include_bspdir = $(includedir)/bsp
+include_bsp_HEADERS = if_wmreg.h pcireg.h
+
+H_FILES = if_wmreg.h pcireg.h
+
+C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.$(OBJEXT))
+
+EXTRA_DIST = if_wm.c pci_map.c
+
+OBJS = $(C_O_FILES)
+
+include $(top_srcdir)/../../../../../../automake/compile.am
+include $(top_srcdir)/../../../../../../automake/lib.am
+
+CFLAGS += -msoft-float
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+$(PROJECT_INCLUDE)/bsp:
+ $(mkinstalldirs) $<
+
+$(PROJECT_INCLUDE)/bsp/if_wmreg.h: if_wmreg.h
+ $(INSTALL_DATA) $< $@
+
+$(PROJECT_INCLUDE)/bsp/pcireg.h: pcireg.h
+ $(INSTALL_DATA) $< $@
+
+# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/if_wmreg.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/pcireg.h
+
+all-local: $(ARCH) $(PREINSTALL_FILES) $(OBJS)
+
+include $(top_srcdir)/../../../../../../automake/local.am
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/POSSIBLEBUG b/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/POSSIBLEBUG
new file mode 100644
index 0000000000..b3a139a4ec
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/POSSIBLEBUG
@@ -0,0 +1,4 @@
+S. Kate Feng <feng1@bnl.gov>, Sept. 06, 2007
+
+This driver boots smoothly with the 1GHZ media.
+It might not boot with the 10/100MHZ media.
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/if_wm.c b/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/if_wm.c
new file mode 100644
index 0000000000..453da7d9b1
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/if_wm.c
@@ -0,0 +1,1556 @@
+/*
+ * Copyright (c) 2004,2005 RTEMS/Mvme5500 port by S. Kate Feng <feng1@bnl.gov>
+ * Brookhaven National Laboratory, All rights reserved
+ *
+ * Acknowledgements:
+ * netBSD : Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
+ * Jason R. Thorpe for Wasabi Systems, Inc.
+ * Intel : NDA document
+ *
+ * Some notes from the author, S. Kate Feng :
+ *
+ * 1) The error reporting routine i82544EI_error() employs two pointers
+ * for the error report buffer. One for the ISR and another one for
+ * the error report.
+ * 2) Enable the hardware Auto-Negotiation state machine.
+ * 3) Set Big Endian mode in the WMREG_CTRL so that we do not need htole32
+ * because PPC is big endian mode.
+ * However, the data packet structure defined in if_wmreg.h
+ * should be redefined for the big endian mode.
+ * 4) To ensure the cache coherence, the MOTLoad had the PCI
+ * snoop control registers (0x1f00) set to "snoop to WB region" for
+ * the entire 512MB of memory.
+ * 5) MOTLoad default :
+ * little endian mode, cache line size is 32 bytes, no checksum control,
+ * hardware auto-neg. state machine disabled. PCI control "snoop
+ * to WB region", MII mode (PHY) instead of TBI mode.
+ * 6) We currently only use 32-bit (instead of 64-bit) DMA addressing.
+ * 7) Support for checksum offloading and TCP segmentation offload will
+ * be available for releasing in 2008, upon request, if I still believe.
+ *
+ */
+
+#define BYTE_ORDER BIG_ENDIAN
+
+#define INET
+
+#include <rtems.h>
+#include <rtems/bspIo.h> /* printk */
+#include <stdio.h> /* printf for statistics */
+#include <string.h>
+
+#include <libcpu/io.h> /* inp & friends */
+#include <libcpu/spr.h> /* registers.h is included here */
+#include <bsp.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#include <rtems/rtems_bsdnet.h>
+#include <rtems/rtems_bsdnet_internal.h>
+#include <rtems/error.h>
+#include <errno.h>
+
+#include <rtems/rtems/types.h>
+#include <rtems/score/cpu.h>
+
+#include <sys/queue.h>
+
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sockio.h> /* SIOCADDMULTI, SIOC... */
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#ifdef INET
+#include <netinet/in_var.h>
+#endif
+
+#include <bsp/irq.h>
+#include <bsp/pci.h>
+#include <bsp/pcireg.h>
+#include <bsp/if_wmreg.h>
+#define WMREG_RADV 0x282c /* Receive Interrupt Absolute Delay Timer */
+
+/*#define CKSUM_OFFLOAD*/
+
+#define ETHERTYPE_FLOWCONTROL 0x8808 /* 802.3x flow control packet */
+
+#define i82544EI_TASK_NAME "IGHZ"
+#define SOFTC_ALIGN 4095
+
+#define INTR_ERR_SIZE 16
+
+/*#define WM_DEBUG*/
+#ifdef WM_DEBUG
+#define WM_DEBUG_LINK 0x01
+#define WM_DEBUG_TX 0x02
+#define WM_DEBUG_RX 0x04
+#define WM_DEBUG_GMII 0x08
+int wm_debug = WM_DEBUG_TX|WM_DEBUG_RX|WM_DEBUG_LINK;
+
+#define DPRINTF(x, y) if (wm_debug & (x)) printk y
+#else
+#define DPRINTF(x, y) /* nothing */
+#endif /* WM_DEBUG */
+
+/* RTEMS event to kill the daemon */
+#define KILL_EVENT RTEMS_EVENT_1
+/* RTEMS event to (re)start the transmitter */
+#define START_TRANSMIT_EVENT RTEMS_EVENT_2
+/* RTEMS events used by the ISR */
+#define RX_EVENT RTEMS_EVENT_3
+#define TX_EVENT RTEMS_EVENT_4
+#define ERR_EVENT RTEMS_EVENT_5
+#define INIT_EVENT RTEMS_EVENT_6
+
+#define ALL_EVENTS (KILL_EVENT|START_TRANSMIT_EVENT|RX_EVENT|TX_EVENT|ERR_EVENT|INIT_EVENT)
+
+
+#define NTXDESC 128
+#define NTXDESC_MASK (NTXDESC - 1)
+#define WM_NEXTTX(x) (((x) + 1) & NTXDESC_MASK)
+
+#define NRXDESC 64
+#define NRXDESC_MASK (NRXDESC - 1)
+#define WM_NEXTRX(x) (((x) + 1) & NRXDESC_MASK)
+#define WM_PREVRX(x) (((x) - 1) & NRXDESC_MASK)
+
+#define WM_CDOFF(x) offsetof(struct wm_control_data, x)
+#define WM_CDTXOFF(x) WM_CDOFF(sc_txdescs[(x)])
+#define WM_CDRXOFF(x) WM_CDOFF(sc_rxdescs[(x)])
+
+#define TXQ_HiLmt_OFF 64
+
+static uint32_t TxDescCmd;
+
+/*
+ * Software state per device.
+ */
+struct wm_softc {
+ wiseman_txdesc_t sc_txdescs[NTXDESC]; /* transmit descriptor memory */
+ wiseman_rxdesc_t sc_rxdescs[NRXDESC]; /* receive descriptor memory */
+ struct mbuf *txs_mbuf[NTXDESC]; /* transmit buffer memory */
+ struct mbuf *rxs_mbuf[NRXDESC]; /* receive buffer memory */
+ struct wm_softc *next_module;
+ volatile unsigned int intr_errsts[INTR_ERR_SIZE]; /* intr_status */
+ unsigned int intr_err_ptr1; /* ptr used in i82544EI_error() */
+ unsigned int intr_err_ptr2; /* ptr used in ISR */
+ int txs_firstdesc; /* first descriptor in packet */
+ int txs_lastdesc; /* last descriptor in packet */
+ int txs_ndesc; /* # of descriptors used */
+ unsigned sc_membase; /* Memory space base address */
+ unsigned sc_memsize; /* Memory space size */
+
+ char dv_xname[16]; /* external name (name + unit) */
+ void *sc_sdhook; /* shutdown hook */
+ struct arpcom arpcom; /* rtems if structure, contains ifnet */
+ int sc_flags; /* flags; see below */
+ int sc_bus_speed; /* PCI/PCIX bus speed */
+ int sc_flowflags; /* 802.3x flow control flags */
+
+ void *sc_ih; /* interrupt cookie */
+
+ int sc_ee_addrbits; /* EEPROM address bits */
+ rtems_id daemonTid;
+ rtems_id daemonSync; /* synchronization with the daemon */
+
+ int txq_next; /* next Tx descriptor ready for transmitting */
+ uint32_t txq_nactive; /* number of active TX descriptors */
+ uint32_t txq_fi; /* next free Tx descriptor */
+ uint32_t txq_free; /* number of free Tx jobs */
+ uint32_t sc_txctx_ipcs; /* cached Tx IP cksum ctx */
+ uint32_t sc_txctx_tucs; /* cached Tx TCP/UDP cksum ctx */
+
+ int sc_rxptr; /* next ready Rx descriptor/queue ent */
+ int sc_rxdiscard;
+ int sc_rxlen;
+ uint32_t sc_ctrl; /* prototype CTRL register */
+#if 0
+ uint32_t sc_ctrl_ext; /* prototype CTRL_EXT register */
+#endif
+ uint32_t sc_icr; /* prototype interrupt bits */
+ uint32_t sc_tctl; /* prototype TCTL register */
+ uint32_t sc_rctl; /* prototype RCTL register */
+ uint32_t sc_tipg; /* prototype TIPG register */
+ uint32_t sc_fcrtl; /* prototype FCRTL register */
+
+ int sc_mchash_type; /* multicast filter offset */
+
+ /* statistics */
+ struct {
+ volatile unsigned long rxInterrupts;
+ volatile unsigned long txInterrupts;
+ unsigned long txMultiBuffPacket;
+ unsigned long txMultiMaxLen;
+ unsigned long txSinglMaxLen;
+ unsigned long txMultiMaxLoop;
+ unsigned long txBuffMaxLen;
+ unsigned long linkInterrupts;
+ unsigned long length_errors;
+ unsigned long frame_errors;
+ unsigned long crc_errors;
+ unsigned long rxOvrRunInterrupts; /* Rx overrun interrupt */
+ unsigned long rxSeqErr;
+ unsigned long rxC_ordered;
+ unsigned long ghostInterrupts;
+ unsigned long linkStatusChng;
+ } stats;
+};
+
+/* <skf> our memory address seen from the PCI bus should be 1:1 */
+#define htole32(x) le32toh(x)
+#define le32toh(x) CPU_swap_u32((unsigned int) x)
+#define le16toh(x) CPU_swap_u16(x)
+
+/* sc_flags */
+#define WM_F_HAS_MII 0x01 /* has MII */
+/* 82544 EI does not perform EEPROM handshake, EEPROM interface is not SPI */
+#define WM_F_EEPROM_HANDSHAKE 0x02 /* requires EEPROM handshake */
+#define WM_F_EEPROM_SPI 0x04 /* EEPROM is SPI */
+#define WM_F_IOH_VALID 0x10 /* I/O handle is valid */
+#define WM_F_BUS64 0x20 /* bus is 64-bit */
+#define WM_F_PCIX 0x40 /* bus is PCI-X */
+
+#define CSR_READ(sc,reg) in_le32((volatile unsigned *)(sc->sc_membase+reg))
+#define CSR_WRITE(sc,reg,val) out_le32((volatile unsigned *)(sc->sc_membase+reg), val)
+
+#define WM_CDTXADDR(sc) ( (uint32_t) &sc->sc_txdescs[0] )
+#define WM_CDRXADDR(sc) ( (uint32_t) &sc->sc_rxdescs[0] )
+
+static struct wm_softc *root_i82544EI_dev = NULL;
+
+static void i82544EI_ifstart(struct ifnet *ifp);
+static int wm_ioctl(struct ifnet *ifp, u_long cmd,uint32_t data);
+static void i82544EI_ifinit(void *arg);
+static void wm_stop(struct ifnet *ifp, int disable);
+
+static void wm_rxdrain(struct wm_softc *sc);
+static int wm_add_rxbuf(struct wm_softc *sc, int idx);
+static int wm_read_eeprom(struct wm_softc *sc,int word,int wordcnt, uint16_t *data);
+static void i82544EI_daemon(void *arg);
+static void wm_set_filter(struct wm_softc *sc);
+
+static void i82544EI_isr();
+static void i82544EI_sendpacket(struct wm_softc *sc, struct mbuf *m);
+extern int pci_mem_find(), pci_io_find(), pci_get_capability();
+extern char * ether_sprintf1();
+
+static void i82544EI_irq_on(const rtems_irq_connect_data *irq)
+{
+ struct wm_softc *sc;
+ unsigned int irqMask= ICR_TXDW | ICR_LSC | ICR_RXSEQ | ICR_RXDMT0 | ICR_RXO | ICR_RXT0 | ICR_RXCFG;
+
+ for (sc= root_i82544EI_dev; sc; sc= sc-> next_module) {
+ CSR_WRITE(sc,WMREG_IMS,(CSR_READ(sc,WMREG_IMS)| irqMask) );
+ return;
+ }
+}
+
+static void i82544EI_irq_off(const rtems_irq_connect_data *irq)
+{
+ struct wm_softc *sc;
+ unsigned int irqMask= ICR_TXDW | ICR_LSC | ICR_RXSEQ | ICR_RXDMT0 | ICR_RXO | ICR_RXT0 |ICR_RXCFG ;
+
+ for (sc= root_i82544EI_dev; sc; sc= sc-> next_module) {
+ CSR_WRITE(sc,WMREG_IMS, (CSR_READ(sc,WMREG_IMS) & ~irqMask) );
+ return;
+ }
+}
+
+static int i82544EI_irq_is_on(const rtems_irq_connect_data *irq)
+{
+ return(CSR_READ(root_i82544EI_dev,WMREG_ICR) & root_i82544EI_dev->sc_icr);
+}
+
+static rtems_irq_connect_data i82544IrqData={
+ BSP_GPP_82544_IRQ,
+ (rtems_irq_hdl) i82544EI_isr,
+ (rtems_irq_enable) i82544EI_irq_on,
+ (rtems_irq_disable) i82544EI_irq_off,
+ (rtems_irq_is_enabled) i82544EI_irq_is_on,
+};
+
+int rtems_i82544EI_driver_attach(struct rtems_bsdnet_ifconfig *config, int attach)
+{
+ struct wm_softc *sc;
+ struct ifnet *ifp;
+ uint8_t enaddr[ETHER_ADDR_LEN];
+ uint16_t myea[ETHER_ADDR_LEN / 2], cfg1, cfg2, swdpin;
+ unsigned reg;
+ int b,d,f; /* PCI bus/device/function */
+ int unit;
+ void *softc_mem;
+ char *name;
+
+ unit = rtems_bsdnet_parse_driver_name(config, &name);
+ if (unit < 0) return 0;
+
+ printk("\nEthernet driver name %s unit %d \n",name, unit);
+ printk("Copyright (c) 2004,2005 S. Kate Feng <feng1@bnl.gov> (RTEMS/mvme5500 port)\n");
+
+ /* Make sure certain elements e.g. descriptor lists are aligned.*/
+ softc_mem = rtems_bsdnet_malloc(sizeof(*sc) + SOFTC_ALIGN, M_FREE, M_NOWAIT);
+
+ /* Check for the very unlikely case of no memory. */
+ if (softc_mem == NULL)
+ rtems_panic("i82544EI: OUT OF MEMORY");
+
+ sc = (void *)(((long)softc_mem + SOFTC_ALIGN) & ~SOFTC_ALIGN);
+ memset(sc, 0, sizeof(*sc));
+
+ sprintf(sc->dv_xname, "%s%d", name, unit);
+
+ if (pci_find_device(PCI_VENDOR_ID_INTEL,PCI_DEVICE_INTEL_82544EI_COPPER,
+ unit-1,&b, &d, &f))
+ rtems_panic("i82544EI device ID not found\n");
+
+#if WM_DEBUG
+ printk("82544EI:b%d, d%d, f%d\n", b, d,f);
+#endif
+
+ /* Memory-mapped acccess is required for normal operation.*/
+ if ( pci_mem_find(b,d,f,PCI_MAPREG_START, &sc->sc_membase, &sc->sc_memsize))
+ rtems_panic("i82544EI: unable to map memory space\n");
+
+#ifdef WM_DEBUG
+ printk("Memory base addr 0x%x\n", sc->sc_membase);
+ printk("txdesc[0] addr:0x%x, rxdesc[0] addr:0x%x, sizeof sc %d\n",&sc->sc_txdescs[0], &sc->sc_rxdescs[0], sizeof(*sc));
+#endif
+
+
+ sc->sc_ctrl |=CSR_READ(sc,WMREG_CTRL);
+ /*
+ * Determine a few things about the bus we're connected to.
+ */
+ reg = CSR_READ(sc,WMREG_STATUS);
+ if (reg & STATUS_BUS64) sc->sc_flags |= WM_F_BUS64;
+ sc->sc_bus_speed = (reg & STATUS_PCI66) ? 66 : 33;
+#ifdef WM_DEBUG
+ printk("%s%d: %d-bit %dMHz PCI bus\n",name, unit,
+ (sc->sc_flags & WM_F_BUS64) ? 64 : 32, sc->sc_bus_speed);
+#endif
+
+ /*
+ * Setup some information about the EEPROM.
+ */
+
+ sc->sc_ee_addrbits = 6;
+
+#ifdef WM_DEBUG
+ printk("%s%d: %u word (%d address bits) MicroWire EEPROM\n",
+ name, unit, 1U << sc->sc_ee_addrbits,
+ sc->sc_ee_addrbits);
+#endif
+
+ /*
+ * Read the Ethernet address from the EEPROM.
+ */
+ if (wm_read_eeprom(sc, EEPROM_OFF_MACADDR,
+ sizeof(myea) / sizeof(myea[0]), myea))
+ rtems_panic("i82544ei 1GHZ ethernet: unable to read Ethernet address");
+
+ enaddr[0] = myea[0] & 0xff;
+ enaddr[1] = myea[0] >> 8;
+ enaddr[2] = myea[1] & 0xff;
+ enaddr[3] = myea[1] >> 8;
+ enaddr[4] = myea[2] & 0xff;
+ enaddr[5] = myea[2] >> 8;
+
+
+ memcpy(sc->arpcom.ac_enaddr, enaddr, ETHER_ADDR_LEN);
+#ifdef WM_DEBUG
+ printk("%s: Ethernet address %s\n", sc->dv_xname,
+ ether_sprintf1(enaddr));
+#endif
+
+ /*
+ * Read the config info from the EEPROM, and set up various
+ * bits in the control registers based on their contents.
+ */
+ if (wm_read_eeprom(sc, EEPROM_OFF_CFG1, 1, &cfg1)) {
+ printk("%s: unable to read CFG1 from EEPROM\n",sc->dv_xname);
+ return(0);
+ }
+ if (wm_read_eeprom(sc, EEPROM_OFF_CFG2, 1, &cfg2)) {
+ printk("%s: unable to read CFG2 from EEPROM\n",sc->dv_xname);
+ return(0);
+ }
+ if (wm_read_eeprom(sc, EEPROM_OFF_SWDPIN, 1, &swdpin)) {
+ printk("%s: unable to read SWDPIN from EEPROM\n",sc->dv_xname);
+ return(0);
+ }
+
+ if (cfg1 & EEPROM_CFG1_ILOS) sc->sc_ctrl |= CTRL_ILOS;
+ sc->sc_ctrl|=((swdpin >> EEPROM_SWDPIN_SWDPIO_SHIFT) & 0xf) <<
+ CTRL_SWDPIO_SHIFT;
+ sc->sc_ctrl |= ((swdpin >> EEPROM_SWDPIN_SWDPIN_SHIFT) & 0xf) <<
+ CTRL_SWDPINS_SHIFT;
+
+ CSR_WRITE(sc,WMREG_CTRL, sc->sc_ctrl);
+#if 0
+ CSR_WRITE(sc,WMREG_CTRL_EXT, sc->sc_ctrl_ext);
+#endif
+
+ ifp = &sc->arpcom.ac_if;
+ /* set this interface's name and unit */
+ ifp->if_unit = unit;
+ ifp->if_name = name;
+ ifp->if_softc = sc;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_mtu = config->mtu ? config->mtu : ETHERMTU;
+ ifp->if_ioctl = wm_ioctl;
+ ifp->if_start = i82544EI_ifstart;
+ /* ifp->if_watchdog = wm_watchdog;*/
+ ifp->if_init = i82544EI_ifinit;
+ if (ifp->if_snd.ifq_maxlen == 0)
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
+
+ ifp->if_output = ether_output;
+
+ /* create the synchronization semaphore */
+ if (RTEMS_SUCCESSFUL != rtems_semaphore_create(
+ rtems_build_name('I','G','H','Z'),0,0,0,&sc->daemonSync))
+ rtems_panic("i82544EI: semaphore creation failed");
+
+ sc->next_module = root_i82544EI_dev;
+ root_i82544EI_dev = sc;
+
+ /* Attach the interface. */
+ if_attach(ifp);
+ ether_ifattach(ifp);
+#ifdef WM_DEBUG
+ printk("82544EI: Ethernet driver has been attached (handle 0x%08x,ifp 0x%08x)\n",sc, ifp);
+#endif
+
+ return(1);
+}
+
+/*
+ * i82544EI_ifstart: [ifnet interface function]
+ *
+ * Start packet transmission on the interface.
+ */
+static void
+i82544EI_ifstart(struct ifnet *ifp)
+{
+ struct wm_softc *sc = ifp->if_softc;
+
+#ifdef WM_DEBUG
+ printk("i82544EI_ifstart(");
+#endif
+
+ if ((ifp->if_flags & IFF_RUNNING) == 0) {
+#ifdef WM_DEBUG
+ printk("IFF_RUNNING==0\n");
+#endif
+ return;
+ }
+
+ ifp->if_flags |= IFF_OACTIVE;
+ rtems_event_send (sc->daemonTid, START_TRANSMIT_EVENT);
+#ifdef WM_DEBUG
+ printk(")\n");
+#endif
+}
+
+static void i82544EI_stats(struct wm_softc *sc)
+{
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+
+ printf(" Rx Interrupts:%-8u\n", sc->stats.rxInterrupts);
+ printf(" Receive Packets:%-8u\n", CSR_READ(sc,WMREG_GPRC));
+ printf(" Receive Overrun:%-8u\n", sc->stats.rxOvrRunInterrupts);
+ printf(" Receive errors:%-8u\n", CSR_READ(sc,WMREG_RXERRC));
+ printf(" Rx sequence error:%-8u\n", sc->stats.rxSeqErr);
+ printf(" Rx /C/ ordered:%-8u\n", sc->stats.rxC_ordered);
+ printf(" Rx Length Errors:%-8u\n", CSR_READ(sc,WMREG_RLEC));
+ printf(" Tx Interrupts:%-8u\n", sc->stats.txInterrupts);
+#if 0
+ printf("Multi-BuffTx Packets:%-8u\n", sc->stats.txMultiBuffPacket);
+ printf("Multi-BuffTx max len:%-8u\n", sc->stats.txMultiMaxLen);
+ printf("SingleBuffTx max len:%-8u\n", sc->stats.txSinglMaxLen);
+ printf("Multi-BuffTx maxloop:%-8u\n", sc->stats.txMultiMaxLoop);
+ printf("Tx buffer max len :%-8u\n", sc->stats.txBuffMaxLen);
+#endif
+ printf(" Transmitt Packets:%-8u\n", CSR_READ(sc,WMREG_GPTC));
+ printf(" Transmitt errors:%-8u\n", ifp->if_oerrors);
+ printf(" Active Txqs:%-8u\n", sc->txq_nactive);
+ printf(" collisions:%-8u\n", CSR_READ(sc,WMREG_COLC));
+ printf(" Crc Errors:%-8u\n", CSR_READ(sc,WMREG_CRCERRS));
+ printf(" Link Status Change:%-8u\n", sc->stats.linkStatusChng);
+}
+
+/*
+ * wm_ioctl: [ifnet interface function]
+ *
+ * Handle control requests from the operator.
+ */
+static int wm_ioctl(struct ifnet *ifp, u_long cmd,uint32_t data)
+{
+ struct wm_softc *sc = ifp->if_softc;
+ int error=0;
+
+ switch (cmd) {
+ default:
+ error = ether_ioctl(ifp, cmd, data);
+ if (error == ENETRESET) {
+ /*
+ * Multicast list has changed; set the hardware filter
+ * accordingly.
+ */
+ wm_set_filter(sc);
+ error = 0;
+ }
+ break;
+ case SIO_RTEMS_SHOW_STATS:
+ i82544EI_stats(sc);
+ break;
+ }
+
+ /* Try to get more packets going.*/
+ i82544EI_ifstart(ifp);
+ return (error);
+}
+
+/*
+ * wm_isr:
+ *
+ * Interrupt service routine.
+ */
+static void i82544EI_isr()
+{
+ volatile struct wm_softc *sc = root_i82544EI_dev;
+ uint32_t icr;
+ rtems_event_set events=0;
+
+ /* Reading the WMREG_ICR clears the interrupt bits */
+ icr = CSR_READ(sc,WMREG_ICR);
+
+ if ( icr & (ICR_RXDMT0|ICR_RXT0)) {
+ sc->stats.rxInterrupts++;
+ events |= RX_EVENT;
+ }
+
+ if (icr & ICR_TXDW) {
+ sc->stats.txInterrupts++;
+ events |= TX_EVENT;
+ }
+ /* <SKF> Rx overrun : no available receive buffer
+ * or PCI receive bandwidth inadequate.
+ */
+ if (icr & ICR_RXO) {
+ sc->stats.rxOvrRunInterrupts++;
+ events |= INIT_EVENT;
+ }
+ if (icr & ICR_RXSEQ) /* framing error */ {
+ sc->intr_errsts[sc->intr_err_ptr2++]=icr;
+ sc->intr_err_ptr2 %=INTR_ERR_SIZE; /* Till Straumann */
+ events |= ERR_EVENT;
+ sc->stats.rxSeqErr++;
+ }
+ if ( !icr) sc->stats.ghostInterrupts++;
+
+ if (icr & ICR_LSC) sc->stats.linkStatusChng++;
+ if (icr & ICR_RXCFG) sc->stats.rxC_ordered++;
+
+ rtems_event_send(sc->daemonTid, events);
+}
+
+/*
+ * i82544EI_sendpacket:
+ *
+ * Helper; handle transmit interrupts.
+ */
+static void i82544EI_sendpacket(struct wm_softc *sc, struct mbuf *m)
+{
+
+#ifdef WM_DEBUG_TX
+ printk("sendpacket(");
+#endif
+
+ if ( !(m->m_next)) { /* single buffer packet */
+ sc->txs_mbuf[sc->txq_next]= m;
+ /* Note: we currently only use 32-bit DMA addresses. */
+ sc->sc_txdescs[sc->txq_next].wtx_addr.wa_low = htole32(mtod(m, void*));
+ sc->sc_txdescs[sc->txq_next].wtx_cmdlen =htole32(TxDescCmd | m->m_len);
+ sc->txs_lastdesc= sc->txq_next;
+ sc->txq_next = WM_NEXTTX(sc->txq_next);
+ sc->txq_nactive++;
+ sc->txq_free--;
+ }
+ else /* multiple mbufs in this packet */
+ {
+ struct mbuf *mtp, *mdest;
+ volatile unsigned char *pt;
+ int len, y, loop=0;
+
+#ifdef WM_DEBUG_TX
+ printk("multi mbufs ");
+#endif
+ mtp = m;
+ while ( mtp) {
+ MGETHDR(mdest, M_WAIT, MT_DATA);
+ MCLGET(mdest, M_WAIT);
+ pt = (volatile unsigned char *)mdest->m_data;
+ for ( len=0;mtp;mtp=mtp->m_next) {
+ loop++;
+ /* Each descriptor gets a 2k (MCLBYTES) buffer, although
+ * the length of each descriptor can be up to 16288 bytes.
+ * For packets which fill more than one buffer ( >2k), we
+ * chain them together.
+ * <Kate Feng> : This effective for packets > 2K
+ * The other way is effective for packets < 2K
+ */
+ if ( ((y=(len+mtp->m_len)) > sizeof(union mcluster))) {
+ printk(">2048, use next descriptor\n");
+ break;
+ }
+ memcpy((void *)pt,(char *)mtp->m_data, mtp->m_len);
+ pt += mtp->m_len;
+ len += mtp->m_len;
+#if 0
+ sc->stats.txSinglMaxLen= MAX(mtp->m_len, sc->stats.txSinglMaxLen);
+#endif
+ } /* end for loop */
+ mdest->m_len=len;
+ sc->txs_mbuf[sc->txq_next] = mdest;
+ /* Note: we currently only use 32-bit DMA addresses. */
+ sc->sc_txdescs[sc->txq_next].wtx_addr.wa_low = htole32(mtod(mdest, void*));
+ sc->sc_txdescs[sc->txq_next].wtx_cmdlen = htole32(TxDescCmd|mdest->m_len);
+ sc->txs_lastdesc = sc->txq_next;
+ sc->txq_next = WM_NEXTTX(sc->txq_next);
+ sc->txq_nactive ++;
+ if (sc->txq_free)
+ sc->txq_free--;
+ else
+ rtems_panic("i8254EI : no more free descriptors");
+#if 0
+ sc->stats.txMultiMaxLen= MAX(mdest->m_len, sc->stats.txMultiMaxLen);
+ sc->stats.txMultiBuffPacket++;
+#endif
+ } /* end for while */
+ /* free old mbuf chain */
+#if 0
+ sc->stats.txMultiMaxLoop=MAX(loop, sc->stats.txMultiMaxLoop);
+#endif
+ m_freem(m);
+ m=0;
+ } /* end multiple mbufs */
+
+ DPRINTF(WM_DEBUG_TX,("%s: TX: desc %d: cmdlen 0x%08x\n", sc->dv_xname,
+ sc->txs_lastdesc, le32toh(sc->sc_txdescs[sc->txs_lastdesc].wtx_cmdlen)));
+ DPRINTF(WM_DEBUG_TX,("status 0x%08x\n",sc->sc_txdescs[sc->txq_fi].wtx_fields.wtxu_status));
+
+ memBar();
+
+ /* This is the location where software writes the first NEW descriptor */
+ CSR_WRITE(sc,WMREG_TDT, sc->txq_next);
+
+ DPRINTF(WM_DEBUG_TX,("%s: addr 0x%08x, TX: TDH %d, TDT %d\n",sc->dv_xname,
+ le32toh(sc->sc_txdescs[sc->txs_lastdesc].wtx_addr.wa_low), CSR_READ(sc,WMREG_TDH),
+ CSR_READ(sc,WMREG_TDT)));
+
+ DPRINTF(WM_DEBUG_TX,("%s: TX: finished transmitting packet, job %d\n",
+ sc->dv_xname, sc->txq_next));
+
+}
+
+static void i82544EI_txq_free(struct wm_softc *sc, uint8_t status)
+{
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+
+ /* We might use the statistics registers instead of variables
+ * to keep tack of the network statistics
+ */
+
+ /* statistics */
+ ifp->if_opackets++;
+
+ if (status & (WTX_ST_EC|WTX_ST_LC)) {
+ ifp->if_oerrors++;
+
+ if (status & WTX_ST_LC)
+ printf("%s: late collision\n", sc->dv_xname);
+ else if (status & WTX_ST_EC) {
+ ifp->if_collisions += 16;
+ printf("%s: excessive collisions\n", sc->dv_xname);
+ }
+ }
+ /* Free the original mbuf chain */
+ m_freem(sc->txs_mbuf[sc->txq_fi]);
+ sc->txs_mbuf[sc->txq_fi] = 0;
+ sc->sc_txdescs[sc->txq_fi].wtx_fields.wtxu_status=0;
+
+ sc->txq_free ++;
+ sc->txq_fi = WM_NEXTTX(sc->txq_fi);
+ --sc->txq_nactive;
+}
+
+static void i82544EI_txq_done(struct wm_softc *sc)
+{
+ uint8_t status;
+
+ /*
+ * Go through the Tx list and free mbufs for those
+ * frames which have been transmitted.
+ */
+ while ( sc->txq_nactive > 0) {
+ status = sc->sc_txdescs[sc->txq_fi].wtx_fields.wtxu_status;
+ if ((status & WTX_ST_DD) == 0) break;
+ i82544EI_txq_free(sc, status);
+ DPRINTF(WM_DEBUG_TX,("%s: TX: job %d done\n",
+ sc->dv_xname, sc->txq_fi));
+ }
+}
+
+static void wm_init_rxdesc(struct wm_softc *sc, int x)
+{
+ wiseman_rxdesc_t *__rxd = &(sc)->sc_rxdescs[(x)];
+ struct mbuf *m;
+
+ m = sc->rxs_mbuf[x];
+
+ __rxd->wrx_addr.wa_low=htole32(mtod(m, void*));
+ __rxd->wrx_addr.wa_high = 0;
+ __rxd->wrx_len = 0;
+ __rxd->wrx_cksum = 0;
+ __rxd->wrx_status = 0;
+ __rxd->wrx_errors = 0;
+ __rxd->wrx_special = 0;
+ /* Receive Descriptor Tail: add Rx desc. to H/W free list */
+ CSR_WRITE(sc,WMREG_RDT, (x));
+}
+
+static void i82544EI_rx(struct wm_softc *sc)
+{
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ struct mbuf *m;
+ int i, len;
+ uint8_t status, errors;
+ struct ether_header *eh;
+
+#ifdef WM_DEBUG
+ printk("i82544EI_rx()\n");
+#endif
+
+ for (i = sc->sc_rxptr;; i = WM_NEXTRX(i)) {
+ DPRINTF(WM_DEBUG_RX, ("%s: RX: checking descriptor %d\n",
+ sc->dv_xname, i));
+
+ status = sc->sc_rxdescs[i].wrx_status;
+ errors = sc->sc_rxdescs[i].wrx_errors;
+ len = le16toh(sc->sc_rxdescs[i].wrx_len);
+ m = sc->rxs_mbuf[i];
+
+ if ((status & WRX_ST_DD) == 0) break; /* descriptor not done */
+
+ if (sc->sc_rxdiscard) {
+ printk("RX: discarding contents of descriptor %d\n", i);
+ wm_init_rxdesc(sc, i);
+ if (status & WRX_ST_EOP) {
+ /* Reset our state. */
+ printk("RX: resetting rxdiscard -> 0\n");
+ sc->sc_rxdiscard = 0;
+ }
+ continue;
+ }
+
+ /*
+ * If an error occurred, update stats and drop the packet.
+ */
+ if (errors &(WRX_ER_CE|WRX_ER_SE|WRX_ER_SEQ|WRX_ER_CXE|WRX_ER_RXE)) {
+ ifp->if_ierrors++;
+ if (errors & WRX_ER_SE)
+ printk("%s: symbol error\n",sc->dv_xname);
+ else if (errors & WRX_ER_SEQ)
+ printk("%s: receive sequence error\n",sc->dv_xname);
+ else if (errors & WRX_ER_CE)
+ printk("%s: CRC error\n",sc->dv_xname);
+ m_freem(m);
+ goto give_it_back;
+ }
+
+ /*
+ * No errors. Receive the packet.
+ *
+ * Note, we have configured the chip to include the
+ * CRC with every packet.
+ */
+ m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header);
+
+ DPRINTF(WM_DEBUG_RX,("%s: RX: buffer at %p len %d\n",
+ sc->dv_xname, m->m_data, len));
+
+
+ eh = mtod (m, struct ether_header *);
+ m->m_data += sizeof(struct ether_header);
+ ether_input (ifp, eh, m);
+ /* Pass it on. */
+ ifp->if_ipackets++;
+
+ give_it_back:
+ /* Add a new receive buffer to the ring.*/
+ if (wm_add_rxbuf(sc, i) != 0) {
+ /*
+ * Failed, throw away what we've done so
+ * far, and discard the rest of the packet.
+ */
+ printk("Failed in wm_add_rxbuf(), drop packet\n");
+ ifp->if_ierrors++;
+ wm_init_rxdesc(sc, i);
+ if ((status & WRX_ST_EOP) == 0)
+ sc->sc_rxdiscard = 1;
+ m_freem(m);
+ }
+ } /* end for */
+
+ /* Update the receive pointer. */
+ sc->sc_rxptr = i;
+ DPRINTF(WM_DEBUG_RX, ("%s: RX: rxptr -> %d\n", sc->dv_xname, i));
+}
+
+static int i82544EI_init_hw(struct wm_softc *sc)
+{
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ int i,error;
+ uint8_t cksumfields;
+
+ /* Cancel any pending I/O. */
+ wm_stop(ifp, 0);
+
+ /* Initialize the error buffer ring */
+ sc->intr_err_ptr1=0;
+ sc->intr_err_ptr2=0;
+ for (i=0; i< INTR_ERR_SIZE; i++) sc->intr_errsts[i]=0;
+
+ /* Initialize the transmit descriptor ring. */
+ memset(sc->sc_txdescs, 0, sizeof(sc->sc_txdescs));
+ sc->txq_free = NTXDESC;
+ sc->txq_next = 0;
+ sc->txs_lastdesc = 0;
+ sc->txq_next = 0;
+ sc->txq_free = NTXDESC;
+ sc->txq_nactive = 0;
+
+ sc->sc_txctx_ipcs = 0xffffffff;
+ sc->sc_txctx_tucs = 0xffffffff;
+
+ CSR_WRITE(sc,WMREG_TBDAH, 0);
+ CSR_WRITE(sc,WMREG_TBDAL, WM_CDTXADDR(sc));
+#ifdef WM_DEBUG
+ printk("TBDAL 0x%x, TDLEN %d\n", WM_CDTXADDR(sc), sizeof(sc->sc_txdescs));
+#endif
+ CSR_WRITE(sc,WMREG_TDLEN, sizeof(sc->sc_txdescs));
+ CSR_WRITE(sc,WMREG_TDH, 0);
+ CSR_WRITE(sc,WMREG_TDT, 0);
+ CSR_WRITE(sc,WMREG_TIDV, 64 );
+ CSR_WRITE(sc,WMREG_TADV, 128);
+
+ CSR_WRITE(sc,WMREG_TXDCTL, TXDCTL_PTHRESH(0) |
+ TXDCTL_HTHRESH(0) | TXDCTL_WTHRESH(0));
+ CSR_WRITE(sc,WMREG_RXDCTL, RXDCTL_PTHRESH(0) |
+ RXDCTL_HTHRESH(0) | RXDCTL_WTHRESH(1) | RXDCTL_GRAN );
+
+ CSR_WRITE(sc,WMREG_TQSA_LO, 0);
+ CSR_WRITE(sc,WMREG_TQSA_HI, 0);
+
+ /*
+ * Set up checksum offload parameters for
+ * this packet.
+ */
+#ifdef CKSUM_OFFLOAD
+ if (m0->m_pkthdr.csum_flags &
+ (M_CSUM_IPv4|M_CSUM_TCPv4|M_CSUM_UDPv4)) {
+ if (wm_tx_cksum(sc, txs, &TxDescCmd,&cksumfields) != 0) {
+ /* Error message already displayed. */
+ continue;
+ }
+ } else {
+#endif
+ TxDescCmd = 0;
+ cksumfields = 0;
+#ifdef CKSUM_OFFLOAD
+ }
+#endif
+
+ TxDescCmd |= WTX_CMD_EOP|WTX_CMD_IFCS|WTX_CMD_RS;
+
+ /* Initialize the transmit job descriptors. */
+ for (i = 0; i < NTXDESC; i++) {
+ sc->txs_mbuf[i] = 0;
+ sc->sc_txdescs[i].wtx_fields.wtxu_options=cksumfields;
+ sc->sc_txdescs[i].wtx_addr.wa_high = 0;
+ sc->sc_txdescs[i].wtx_addr.wa_low = 0;
+ sc->sc_txdescs[i].wtx_cmdlen = htole32(TxDescCmd);
+ }
+
+ /*
+ * Initialize the receive descriptor and receive job
+ * descriptor rings.
+ */
+ memset(sc->sc_rxdescs, 0, sizeof(sc->sc_rxdescs));
+ CSR_WRITE(sc,WMREG_RDBAH, 0);
+ CSR_WRITE(sc,WMREG_RDBAL, WM_CDRXADDR(sc));
+ CSR_WRITE(sc,WMREG_RDLEN, sizeof(sc->sc_rxdescs));
+ CSR_WRITE(sc,WMREG_RDH, 0);
+ CSR_WRITE(sc,WMREG_RDT, 0);
+ CSR_WRITE(sc,WMREG_RDTR, 0 |RDTR_FPD);
+ CSR_WRITE(sc, WMREG_RADV, 256);
+
+ for (i = 0; i < NRXDESC; i++) {
+ if (sc->rxs_mbuf[i] == NULL) {
+ if ((error = wm_add_rxbuf(sc, i)) != 0) {
+ printk("%s%d: unable to allocate or map rx buffer"
+ "%d, error = %d\n",ifp->if_name,ifp->if_unit, i, error);
+ /*
+ * XXX Should attempt to run with fewer receive
+ * XXX buffers instead of just failing.
+ */
+ wm_rxdrain(sc);
+ return(error);
+ }
+ } else {
+ printk("sc->rxs_mbuf[%d] not NULL.\n", i);
+ wm_init_rxdesc(sc, i);
+ }
+ }
+ sc->sc_rxptr = 0;
+ sc->sc_rxdiscard = 0;
+
+ /*
+ * Clear out the VLAN table -- we don't use it (yet).
+ */
+ CSR_WRITE(sc,WMREG_VET, 0);
+ for (i = 0; i < WM_VLAN_TABSIZE; i++)
+ CSR_WRITE(sc,WMREG_VFTA + (i << 2), 0);
+
+ /*
+ * Set up flow-control parameters.
+ *
+ * XXX Values could probably stand some tuning.
+ */
+ CSR_WRITE(sc,WMREG_FCAL, FCAL_CONST);/*safe,even though MOTLOAD 0x00c28001 */
+ CSR_WRITE(sc,WMREG_FCAH, FCAH_CONST);/*safe,even though MOTLOAD 0x00000100 */
+ CSR_WRITE(sc,WMREG_FCT, ETHERTYPE_FLOWCONTROL);/*safe,even though MOTLoad 0x8808 */
+
+
+ /* safe,even though MOTLoad default all 0 */
+ sc->sc_fcrtl = FCRTL_DFLT;
+
+ CSR_WRITE(sc,WMREG_FCRTH, FCRTH_DFLT);
+ CSR_WRITE(sc,WMREG_FCRTL, sc->sc_fcrtl);
+ CSR_WRITE(sc,WMREG_FCTTV, FCTTV_DFLT);
+
+ sc->sc_ctrl &= ~CTRL_VME;
+ /*sc->sc_ctrl |= CTRL_TFCE | CTRL_RFCE;*/
+ /* enable Big Endian Mode for the powerPC
+ sc->sc_ctrl |= CTRL_BEM;*/
+
+ /* Write the control registers. */
+ CSR_WRITE(sc,WMREG_CTRL, sc->sc_ctrl);
+#if 0
+ CSR_WRITE(sc,WMREG_CTRL_EXT, sc->sc_ctrl_ext);
+#endif
+
+ /* MOTLoad : WMREG_RXCSUM (0x5000)= 0, no Rx checksum offloading */
+
+ /*
+ * Set up the interrupt registers.
+ */
+ CSR_WRITE(sc,WMREG_IMC, 0xffffffffU);
+ /* Reading the WMREG_ICR clears the interrupt bits */
+ CSR_READ(sc,WMREG_ICR);
+
+ /* printf("WMREG_IMS 0x%x\n", CSR_READ(sc,WMREG_IMS));*/
+
+ sc->sc_icr = ICR_TXDW | ICR_LSC | ICR_RXSEQ | ICR_RXCFG | ICR_RXDMT0 | ICR_RXO | ICR_RXT0;
+
+ CSR_WRITE(sc,WMREG_IMS, sc->sc_icr);
+
+ /* Set up the inter-packet gap. */
+ CSR_WRITE(sc,WMREG_TIPG, sc->sc_tipg);
+
+#if 0 /* XXXJRT */
+ /* Set the VLAN ethernetype. */
+ CSR_WRITE(sc,WMREG_VET, ETHERTYPE_VLAN);
+#endif
+
+ /*
+ * Set up the transmit control register; we start out with
+ * a collision distance suitable for FDX, but update it when
+ * we resolve the media type.
+ */
+ sc->sc_tctl = TCTL_EN | TCTL_PSP | TCTL_CT(TX_COLLISION_THRESHOLD) |
+ TCTL_COLD(TX_COLLISION_DISTANCE_FDX) | TCTL_RTLC; /*transmitter enable*/
+
+ /*
+ * Set up the receive control register; we actually program
+ * the register when we set the receive filter. Use multicast
+ * address offset type 0.
+ *
+ * Only the i82544 has the ability to strip the incoming
+ * CRC, so we don't enable that feature. (TODO)
+ */
+ sc->sc_mchash_type = 0;
+ sc->sc_rctl = RCTL_EN | RCTL_LBM_NONE | RCTL_RDMTS_1_2 | RCTL_LPE |
+ RCTL_DPF | RCTL_MO(sc->sc_mchash_type);
+
+ /* (MCLBYTES == 2048) */
+ sc->sc_rctl |= RCTL_2k;
+
+#ifdef WM_DEBUG
+ printk("RDBAL 0x%x,RDLEN %d, RDT %d\n",CSR_READ(sc,WMREG_RDBAL),CSR_READ(sc,WMREG_RDLEN), CSR_READ(sc,WMREG_RDT));
+#endif
+
+ /* Set the receive filter. */
+ wm_set_filter(sc);
+
+ CSR_WRITE(sc,WMREG_TCTL, sc->sc_tctl);
+
+ /* Map and establish our interrupt. */
+ if (!BSP_install_rtems_irq_handler(&i82544IrqData))
+ rtems_panic("1GHZ ethernet: unable to install ISR");
+
+ return(0);
+}
+
+/*
+ * i82544EI_ifinit: [ifnet interface function]
+ *
+ * Initialize the interface.
+ */
+static void i82544EI_ifinit(void *arg)
+{
+ struct wm_softc *sc = (struct wm_softc*)arg;
+
+#ifdef WM_DEBUG
+ printk("i82544EI_ifinit(): daemon ID: 0x%08x)\n", sc->daemonTid);
+#endif
+ if (sc->daemonTid) {
+#ifdef WM_DEBUG
+ printk("i82544EI: daemon already up, doing nothing\n");
+#endif
+ return;
+ }
+ i82544EI_init_hw(sc);
+
+ sc->daemonTid = rtems_bsdnet_newproc(i82544EI_TASK_NAME,4096,i82544EI_daemon,arg);
+
+ /* ...all done! */
+ sc->arpcom.ac_if.if_flags |= IFF_RUNNING;
+
+#ifdef WM_DEBUG
+ printk(")");
+#endif
+}
+
+/*
+ * wm_txdrain:
+ *
+ * Drain the transmit queue.
+ */
+static void wm_txdrain(struct wm_softc *sc)
+{
+ int i;
+
+ /* Release any queued transmit buffers. */
+ for (i = 0; i < NTXDESC; i++) {
+ if (sc->txs_mbuf[i] != NULL) {
+ m_freem(sc->txs_mbuf[i]);
+ sc->txs_mbuf[i] = NULL;
+ }
+ }
+}
+
+/*
+ * wm_rxdrain:
+ *
+ * Drain the receive queue.
+ */
+static void wm_rxdrain(struct wm_softc *sc)
+{
+ int i;
+
+ for (i = 0; i < NRXDESC; i++) {
+ if (sc->rxs_mbuf[i] != NULL) {
+ m_freem(sc->rxs_mbuf[i]);
+ sc->rxs_mbuf[i] = NULL;
+ }
+ }
+}
+
+static void i82544EI_tx_stop(struct wm_softc *sc)
+{
+ wm_txdrain(sc);
+}
+
+static void i82544EI_rx_stop(struct wm_softc *sc)
+{
+ wm_rxdrain(sc);
+}
+
+static void i82544EI_stop_hw(struct wm_softc *sc)
+{
+#ifdef WM_DEBUG
+ printk("i82544EI_stop_hw(");
+#endif
+
+ /* remove our interrupt handler which will also
+ * disable interrupts at the MPIC and the device
+ * itself
+ */
+ if (!BSP_remove_rtems_irq_handler(&i82544IrqData))
+ rtems_panic("i82544EI: unable to remove IRQ handler!");
+
+ CSR_WRITE(sc,WMREG_IMS, 0);
+
+ sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
+ i82544EI_tx_stop(sc);
+ i82544EI_rx_stop(sc);
+#ifdef WM_DEBUG
+ printk(")");
+#endif
+}
+
+/*
+ * wm_stop: [ifnet interface function]
+ *
+ * Stop transmission on the interface.
+ */
+static void wm_stop(struct ifnet *ifp, int disable)
+{
+ struct wm_softc *sc = ifp->if_softc;
+
+#ifdef WM_DEBUG
+ printk("wm_stop(");
+#endif
+ /* Stop the transmit and receive processes. */
+ CSR_WRITE(sc,WMREG_TCTL, 0);
+ CSR_WRITE(sc,WMREG_RCTL, 0);
+
+ wm_txdrain(sc);
+ wm_rxdrain(sc);
+
+ /* Mark the interface as down */
+ ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+#ifdef WM_DEBUG
+ printk(")\n");
+#endif
+}
+
+/*
+ * wm_eeprom_sendbits:
+ *
+ * Send a series of bits to the EEPROM.
+ */
+static void wm_eeprom_sendbits(struct wm_softc *sc, uint32_t bits, int nbits)
+{
+ uint32_t reg;
+ int x;
+
+ reg = CSR_READ(sc,WMREG_EECD);
+
+ for (x = nbits; x > 0; x--) {
+ if (bits & (1U << (x - 1)))
+ reg |= EECD_DI;
+ else
+ reg &= ~EECD_DI;
+ CSR_WRITE(sc,WMREG_EECD, reg);
+ rtems_bsp_delay(2);
+ CSR_WRITE(sc,WMREG_EECD, reg | EECD_SK);
+ rtems_bsp_delay(2);
+ CSR_WRITE(sc,WMREG_EECD, reg);
+ rtems_bsp_delay(2);
+ }
+}
+
+/*
+ * wm_eeprom_recvbits:
+ *
+ * Receive a series of bits from the EEPROM.
+ */
+static void wm_eeprom_recvbits(struct wm_softc *sc, uint32_t *valp, int nbits)
+{
+ uint32_t reg, val;
+ int x;
+
+ reg = CSR_READ(sc,WMREG_EECD) & ~EECD_DI;
+
+ val = 0;
+ for (x = nbits; x > 0; x--) {
+ CSR_WRITE(sc,WMREG_EECD, reg | EECD_SK);
+ rtems_bsp_delay(2);
+ if (CSR_READ(sc,WMREG_EECD) & EECD_DO)
+ val |= (1U << (x - 1));
+ CSR_WRITE(sc,WMREG_EECD, reg);
+ rtems_bsp_delay(2);
+ }
+ *valp = val;
+}
+
+/*
+ * wm_read_eeprom_uwire:
+ *
+ * Read a word from the EEPROM using the MicroWire protocol.
+ *
+ * (The 82544EI Gigabit Ethernet Controller is compatible with
+ * most MicroWire interface, serial EEPROM devices.)
+ */
+static int wm_read_eeprom_uwire(struct wm_softc *sc, int word, int wordcnt, uint16_t *data)
+{
+ uint32_t reg, val;
+ int i;
+
+ for (i = 0; i < wordcnt; i++) {
+ /* Clear SK and DI. */
+ reg = CSR_READ(sc,WMREG_EECD) & ~(EECD_SK | EECD_DI);
+ CSR_WRITE(sc,WMREG_EECD, reg);
+
+ /* Set CHIP SELECT. */
+ reg |= EECD_CS;
+ CSR_WRITE(sc,WMREG_EECD, reg);
+ rtems_bsp_delay(2);
+
+ /* Shift in the READ command. */
+ wm_eeprom_sendbits(sc, UWIRE_OPC_READ, 3);
+
+ /* Shift in address. */
+ wm_eeprom_sendbits(sc, word + i, sc->sc_ee_addrbits);
+
+ /* Shift out the data. */
+ wm_eeprom_recvbits(sc, &val, 16);
+ data[i] = val & 0xffff;
+
+ /* Clear CHIP SELECT. */
+ reg = CSR_READ(sc,WMREG_EECD) & ~EECD_CS;
+ CSR_WRITE(sc,WMREG_EECD, reg);
+ rtems_bsp_delay(2);
+ }
+ return (0);
+}
+
+/*
+ * wm_acquire_eeprom:
+ *
+ * Perform the EEPROM handshake required on some chips.
+ */
+static int wm_acquire_eeprom(struct wm_softc *sc)
+{
+ uint32_t reg;
+ int x;
+
+ reg = CSR_READ(sc,WMREG_EECD);
+
+ /* Request EEPROM access. */
+ reg |= EECD_EE_REQ;
+ CSR_WRITE(sc,WMREG_EECD, reg);
+
+ /* ..and wait for it to be granted. */
+ for (x = 0; x < 100; x++) {
+ reg = CSR_READ(sc,WMREG_EECD);
+ if (reg & EECD_EE_GNT) break;
+ rtems_bsp_delay(500);
+ }
+ if ((reg & EECD_EE_GNT) == 0) {
+ printk("Could not acquire EEPROM GNT x= %d\n", x);
+ reg &= ~EECD_EE_REQ;
+ CSR_WRITE(sc,WMREG_EECD, reg);
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * wm_read_eeprom:
+ *
+ * Read data from the serial EEPROM.
+ * 82544EI does not Perform the EEPROM handshake
+ */
+static int wm_read_eeprom(struct wm_softc *sc, int word, int wordcnt, uint16_t *data)
+{
+#if 0
+ /* base on the datasheet, this does not seem to be applicable */
+ if (wm_acquire_eeprom(sc))
+ return(1);
+#endif
+ return(wm_read_eeprom_uwire(sc, word, wordcnt, data));
+}
+
+/*
+ * wm_add_rxbuf:
+ *
+ * Add a receive buffer to the indiciated descriptor.
+ */
+static int wm_add_rxbuf(struct wm_softc *sc, int idx)
+{
+ struct mbuf *m;
+
+ MGETHDR(m, M_WAIT, MT_DATA);
+ if (m == NULL) return (ENOBUFS);
+ MCLGET(m, M_WAIT);
+ if ((m->m_flags & M_EXT) == 0) {
+ m_freem(m);
+ return (ENOBUFS);
+ }
+ m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
+ sc->rxs_mbuf[idx] = m;
+ /* m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;*/
+ wm_init_rxdesc(sc, idx);
+#if 0
+ printk("sc->rxs_mbuf[%d]= 0x%x, mbuf @ 0x%x\n",
+ idx, sc->rxs_mbuf[idx], le32toh(sc->sc_rxdescs[idx].wrx_addr.wa_low));
+#endif
+ return(0);
+}
+
+/*
+ * wm_set_ral:
+ *
+ * Set an entery in the receive address list.
+ */
+static void
+wm_set_ral(struct wm_softc *sc, const uint8_t *enaddr, int idx)
+{
+ uint32_t ral_lo, ral_hi;
+
+ if (enaddr != NULL) {
+ ral_lo = enaddr[0]|(enaddr[1] << 8)|(enaddr[2] << 16)|(enaddr[3] << 24);
+ ral_hi = enaddr[4] | (enaddr[5] << 8);
+ ral_hi |= RAL_AV;
+ } else {
+ ral_lo = 0;
+ ral_hi = 0;
+ }
+
+ CSR_WRITE(sc,WMREG_RAL_LO(WMREG_CORDOVA_RAL_BASE, idx),ral_lo);
+ CSR_WRITE(sc,WMREG_RAL_HI(WMREG_CORDOVA_RAL_BASE, idx),ral_hi);
+}
+
+/*
+ * wm_mchash:
+ *
+ * Compute the hash of the multicast address for the 4096-bit
+ * multicast filter.
+ */
+static uint32_t
+wm_mchash(struct wm_softc *sc, const uint8_t *enaddr)
+{
+ static const int lo_shift[4] = { 4, 3, 2, 0 };
+ static const int hi_shift[4] = { 4, 5, 6, 8 };
+ uint32_t hash;
+
+ hash = (enaddr[4] >> lo_shift[sc->sc_mchash_type]) |
+ (((uint16_t) enaddr[5]) << hi_shift[sc->sc_mchash_type]);
+
+ return (hash & 0xfff);
+}
+
+/*
+ * wm_set_filter: Set up the receive filter.
+ */
+static void wm_set_filter(struct wm_softc *sc)
+{
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ struct ether_multi *enm;
+ struct ether_multistep step;
+ uint32_t mta_reg;
+ uint32_t hash, reg, bit;
+ int i;
+
+#ifdef WM_DEBUG
+ printk("wm_set_filter(");
+#endif
+ mta_reg = WMREG_CORDOVA_MTA;
+ sc->sc_rctl &= ~(RCTL_BAM | RCTL_UPE | RCTL_MPE);
+
+ /* if (ifp->if_flags & IFF_BROADCAST)*/
+ sc->sc_rctl |= RCTL_BAM;
+ if (ifp->if_flags & IFF_PROMISC) {
+ sc->sc_rctl |= RCTL_UPE;
+ goto allmulti;
+ }
+
+ /*
+ * Set the station address in the first RAL slot, and
+ * clear the remaining slots.
+ */
+ wm_set_ral(sc, sc->arpcom.ac_enaddr, 0);
+ for (i = 1; i < WM_RAL_TABSIZE; i++)
+ wm_set_ral(sc, NULL, i);
+
+ /* Clear out the multicast table. */
+ for (i = 0; i < WM_MC_TABSIZE; i++)
+ CSR_WRITE(sc,mta_reg + (i << 2), 0);
+
+ ETHER_FIRST_MULTI(step, &sc->arpcom, enm);
+ while (enm != NULL) {
+ if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
+ /*
+ * We must listen to a range of multicast addresses.
+ * For now, just accept all multicasts, rather than
+ * trying to set only those filter bits needed to match
+ * the range. (At this time, the only use of address
+ * ranges is for IP multicast routing, for which the
+ * range is big enough to require all bits set.)
+ */
+ goto allmulti;
+ }
+
+ hash = wm_mchash(sc, enm->enm_addrlo);
+
+ reg = (hash >> 5) & 0x7f;
+ bit = hash & 0x1f;
+
+ hash = CSR_READ(sc,mta_reg + (reg << 2));
+ hash |= 1U << bit;
+
+ /* XXX Hardware bug?? */
+ if ((reg & 0xe) == 1) {
+ bit = CSR_READ(sc,mta_reg + ((reg - 1) << 2));
+ CSR_WRITE(sc,mta_reg + (reg << 2), hash);
+ CSR_WRITE(sc,mta_reg + ((reg - 1) << 2), bit);
+ } else
+ CSR_WRITE(sc,mta_reg + (reg << 2), hash);
+
+ ETHER_NEXT_MULTI(step, enm);
+ }
+
+ ifp->if_flags &= ~IFF_ALLMULTI;
+ goto setit;
+
+ allmulti:
+ ifp->if_flags |= IFF_ALLMULTI;
+ sc->sc_rctl |= RCTL_MPE;
+
+ setit:
+ CSR_WRITE(sc,WMREG_RCTL, sc->sc_rctl);
+
+#ifdef WM_DEBUG
+ printk("RCTL 0x%x)\n", CSR_READ(sc,WMREG_RCTL));
+#endif
+}
+
+static void i82544EI_error(struct wm_softc *sc)
+{
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ unsigned long intr_status= sc->intr_errsts[sc->intr_err_ptr1++];
+
+ /* read and reset the status; because this is written
+ * by the ISR, we must disable interrupts here
+ */
+ sc->intr_err_ptr1 %=INTR_ERR_SIZE; /* Till Straumann */
+ if (intr_status) {
+ printk("Error %s%d:", ifp->if_name, ifp->if_unit);
+ if (intr_status & ICR_RXSEQ) {
+ printk("Rxq framing error (ICR= %x), if_ierrors %d\n",
+ intr_status, ifp->if_ierrors);
+ }
+ }
+ else
+ printk("%s%d: Ghost interrupt ?\n",ifp->if_name,ifp->if_unit);
+}
+
+void i82544EI_printStats()
+{
+ i82544EI_stats(root_i82544EI_dev);
+}
+
+/* The daemon does all of the work; RX, TX and cleaning up buffers/descriptors */
+static void i82544EI_daemon(void *arg)
+{
+ struct wm_softc *sc = (struct wm_softc*)arg;
+ rtems_event_set events;
+ struct mbuf *m=0;
+ struct ifnet *ifp=&sc->arpcom.ac_if;
+
+#ifdef WM_DEBUG
+ printk("i82544EI_daemon()\n");
+#endif
+
+ /* NOTE: our creator possibly holds the bsdnet_semaphore.
+ * since that has PRIORITY_INVERSION enabled, our
+ * subsequent call to bsdnet_event_receive() will
+ * _not_ release it. It's still in posession of our
+ * owner.
+ * This is different from how killing this task
+ * is handled.
+ */
+
+ for (;;) {
+ /* sleep until there's work to be done */
+ /* Note: bsdnet_event_receive() acquires
+ * the global bsdnet semaphore for
+ * mutual exclusion.
+ */
+ rtems_bsdnet_event_receive(ALL_EVENTS,
+ RTEMS_WAIT | RTEMS_EVENT_ANY,
+ RTEMS_NO_TIMEOUT,
+ &events);
+ if (KILL_EVENT & events) break;
+
+ if (events & RX_EVENT) i82544EI_rx(sc);
+
+ /* clean up and try sending packets */
+ do {
+ i82544EI_txq_done(sc);
+
+ while (sc->txq_free>0) {
+ if (sc->txq_free>TXQ_HiLmt_OFF) {
+ IF_DEQUEUE(&ifp->if_snd,m);
+ if (m==0) break;
+ i82544EI_sendpacket(sc, m);
+ }
+ else {
+ i82544EI_txq_done(sc);
+ break;
+ }
+ if (events & RX_EVENT) i82544EI_rx(sc);
+ }
+ /* we leave this loop
+ * - either because there's no free buffer
+ * (m=0 initializer && !sc->txq_free)
+ * - or there's nothing to send (IF_DEQUEUE
+ * returned 0
+ */
+ } while (m && sc->txq_free);
+
+ ifp->if_flags &= ~IFF_OACTIVE;
+
+ /* Log errors and other uncommon events. */
+ if (events & ERR_EVENT) i82544EI_error(sc);
+ /* Rx overrun */
+ if ( events & INIT_EVENT) {
+ printk("Warnning, Rx overrun. Make sure the old mbuf was free\n");
+ i82544EI_ifinit(arg);
+ }
+
+ } /* end for(;;) { rtems_bsdnet_event_receive() .....*/
+
+ printf("out of daemon\n");
+ ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
+
+ /* shut down the hardware */
+ i82544EI_stop_hw(sc);
+ /* flush the output queue */
+ for (;;) {
+ IF_DEQUEUE(&ifp->if_snd,m);
+ if (!m) break;
+ m_freem(m);
+ }
+ /* as of 'rtems_bsdnet_event_receive()' we own the
+ * networking semaphore
+ */
+ rtems_bsdnet_semaphore_release();
+ rtems_semaphore_release(sc->daemonSync);
+
+ /* Note that I dont use sc->daemonTid here -
+ * theoretically, that variable could already
+ * hold a newly created TID
+ */
+ rtems_task_delete(RTEMS_SELF);
+}
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/if_wmreg.h b/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/if_wmreg.h
new file mode 100644
index 0000000000..d0fd42f1ce
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/if_wmreg.h
@@ -0,0 +1,737 @@
+/* $NetBSD: if_wmreg.h,v 1.22 2007/04/29 20:35:21 bouyer Exp $ */
+
+/*
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Register description for the Intel i82542 (``Wiseman''),
+ * i82543 (``Livengood''), and i82544 (``Cordova'') Gigabit
+ * Ethernet chips.
+ */
+
+/*
+ * The wiseman supports 64-bit PCI addressing. This structure
+ * describes the address in descriptors.
+ */
+typedef struct wiseman_addr {
+ uint32_t wa_low; /* low-order 32 bits */
+ uint32_t wa_high; /* high-order 32 bits */
+} __attribute__((__packed__)) wiseman_addr_t;
+
+/*
+ * The Wiseman receive descriptor.
+ *
+ * The receive descriptor ring must be aligned to a 4K boundary,
+ * and there must be an even multiple of 8 descriptors in the ring.
+ */
+typedef struct wiseman_rxdesc {
+ wiseman_addr_t wrx_addr; /* buffer address */
+
+ uint16_t wrx_len; /* buffer length */
+ uint16_t wrx_cksum; /* checksum (starting at PCSS) */
+
+ uint8_t wrx_status; /* Rx status */
+ uint8_t wrx_errors; /* Rx errors */
+ uint16_t wrx_special; /* special field (VLAN, etc.) */
+} __attribute__((__packed__)) wiseman_rxdesc_t;
+
+/* wrx_status bits */
+#define WRX_ST_DD (1U << 0) /* descriptor done */
+#define WRX_ST_EOP (1U << 1) /* end of packet */
+#define WRX_ST_IXSM (1U << 2) /* ignore checksum indication */
+#define WRX_ST_VP (1U << 3) /* VLAN packet */
+#define WRX_ST_BPDU (1U << 4) /* ??? */
+#define WRX_ST_TCPCS (1U << 5) /* TCP checksum performed */
+#define WRX_ST_IPCS (1U << 6) /* IP checksum performed */
+#define WRX_ST_PIF (1U << 7) /* passed in-exact filter */
+
+/* wrx_error bits */
+#define WRX_ER_CE (1U << 0) /* CRC error */
+#define WRX_ER_SE (1U << 1) /* symbol error */
+#define WRX_ER_SEQ (1U << 2) /* sequence error */
+#define WRX_ER_ICE (1U << 3) /* ??? */
+#define WRX_ER_CXE (1U << 4) /* carrier extension error */
+#define WRX_ER_TCPE (1U << 5) /* TCP checksum error */
+#define WRX_ER_IPE (1U << 6) /* IP checksum error */
+#define WRX_ER_RXE (1U << 7) /* Rx data error */
+
+/* wrx_special field for VLAN packets */
+#define WRX_VLAN_ID(x) ((x) & 0x0fff) /* VLAN identifier */
+#define WRX_VLAN_CFI (1U << 12) /* Canonical Form Indicator */
+#define WRX_VLAN_PRI(x) (((x) >> 13) & 7)/* VLAN priority field */
+
+/*
+ * The Wiseman transmit descriptor.
+ *
+ * The transmit descriptor ring must be aligned to a 4K boundary,
+ * and there must be an even multiple of 8 descriptors in the ring.
+ */
+typedef struct wiseman_tx_fields {
+ uint8_t wtxu_status; /* Tx status */
+ uint8_t wtxu_options; /* options */
+ uint16_t wtxu_vlan; /* VLAN info */
+} __attribute__((__packed__)) wiseman_txfields_t;
+typedef struct wiseman_txdesc {
+ wiseman_addr_t wtx_addr; /* buffer address */
+ uint32_t wtx_cmdlen; /* command and length */
+ wiseman_txfields_t wtx_fields; /* fields; see below */
+} __attribute__((__packed__)) wiseman_txdesc_t;
+
+/* Commands for wtx_cmdlen */
+#define WTX_CMD_EOP (1U << 24) /* end of packet */
+#define WTX_CMD_IFCS (1U << 25) /* insert FCS */
+#define WTX_CMD_RS (1U << 27) /* report status */
+#define WTX_CMD_RPS (1U << 28) /* report packet sent */
+#define WTX_CMD_DEXT (1U << 29) /* descriptor extension */
+#define WTX_CMD_VLE (1U << 30) /* VLAN enable */
+#define WTX_CMD_IDE (1U << 31) /* interrupt delay enable */
+
+/* Descriptor types (if DEXT is set) */
+#define WTX_DTYP_C (0U << 20) /* context */
+#define WTX_DTYP_D (1U << 20) /* data */
+
+/* wtx_fields status bits */
+#define WTX_ST_DD (1U << 0) /* descriptor done */
+#define WTX_ST_EC (1U << 1) /* excessive collisions */
+#define WTX_ST_LC (1U << 2) /* late collision */
+#define WTX_ST_TU (1U << 3) /* transmit underrun */
+
+/* wtx_fields option bits for IP/TCP/UDP checksum offload */
+#define WTX_IXSM (1U << 0) /* IP checksum offload */
+#define WTX_TXSM (1U << 1) /* TCP/UDP checksum offload */
+
+/* Maximum payload per Tx descriptor */
+#define WTX_MAX_LEN 4096
+
+/*
+ * The Livengood TCP/IP context descriptor.
+ */
+struct livengood_tcpip_ctxdesc {
+ uint32_t tcpip_ipcs; /* IP checksum context */
+ uint32_t tcpip_tucs; /* TCP/UDP checksum context */
+ uint32_t tcpip_cmdlen;
+ uint32_t tcpip_seg; /* TCP segmentation context */
+};
+
+/* commands for context descriptors */
+#define WTX_TCPIP_CMD_TCP (1U << 24) /* 1 = TCP, 0 = UDP */
+#define WTX_TCPIP_CMD_IP (1U << 25) /* 1 = IPv4, 0 = IPv6 */
+#define WTX_TCPIP_CMD_TSE (1U << 26) /* segmentation context valid */
+
+#define WTX_TCPIP_IPCSS(x) ((x) << 0) /* checksum start */
+#define WTX_TCPIP_IPCSO(x) ((x) << 8) /* checksum value offset */
+#define WTX_TCPIP_IPCSE(x) ((x) << 16) /* checksum end */
+
+#define WTX_TCPIP_TUCSS(x) ((x) << 0) /* checksum start */
+#define WTX_TCPIP_TUCSO(x) ((x) << 8) /* checksum value offset */
+#define WTX_TCPIP_TUCSE(x) ((x) << 16) /* checksum end */
+
+#define WTX_TCPIP_SEG_STATUS(x) ((x) << 0)
+#define WTX_TCPIP_SEG_HDRLEN(x) ((x) << 8)
+#define WTX_TCPIP_SEG_MSS(x) ((x) << 16)
+
+/*
+ * PCI config registers used by the Wiseman.
+ */
+#define WM_PCI_MMBA PCI_MAPREG_START
+/* registers for FLASH access on ICH8 */
+#define WM_ICH8_FLASH 0x0014
+
+/*
+ * Wiseman Control/Status Registers.
+ */
+#define WMREG_CTRL 0x0000 /* Device Control Register */
+#define CTRL_FD (1U << 0) /* full duplex */
+#define CTRL_BEM (1U << 1) /* big-endian mode */
+#define CTRL_PRIOR (1U << 2) /* 0 = receive, 1 = fair */
+#define CTRL_LRST (1U << 3) /* link reset */
+#define CTRL_ASDE (1U << 5) /* auto speed detect enable */
+#define CTRL_SLU (1U << 6) /* set link up */
+#define CTRL_ILOS (1U << 7) /* invert loss of signal */
+#define CTRL_SPEED(x) ((x) << 8) /* speed (Livengood) */
+#define CTRL_SPEED_10 CTRL_SPEED(0)
+#define CTRL_SPEED_100 CTRL_SPEED(1)
+#define CTRL_SPEED_1000 CTRL_SPEED(2)
+#define CTRL_SPEED_MASK CTRL_SPEED(3)
+#define CTRL_FRCSPD (1U << 11) /* force speed (Livengood) */
+#define CTRL_FRCFDX (1U << 12) /* force full-duplex (Livengood) */
+#define CTRL_D_UD_EN (1U << 13) /* Dock/Undock enable */
+#define CTRL_D_UD_POL (1U << 14) /* Defined polarity of Dock/Undock indication in SDP[0] */
+#define CTRL_F_PHY_R (1U << 15) /* Reset both PHY ports, through PHYRST_N pin */
+#define CTRL_EXT_LINK_EN (1U << 16) /* enable link status from external LINK_0 and LINK_1 pins */
+#define CTRL_SWDPINS_SHIFT 18
+#define CTRL_SWDPINS_MASK 0x0f
+#define CTRL_SWDPIN(x) (1U << (CTRL_SWDPINS_SHIFT + (x)))
+#define CTRL_SWDPIO_SHIFT 22
+#define CTRL_SWDPIO_MASK 0x0f
+#define CTRL_SWDPIO(x) (1U << (CTRL_SWDPIO_SHIFT + (x)))
+#define CTRL_RST (1U << 26) /* device reset */
+#define CTRL_RFCE (1U << 27) /* Rx flow control enable */
+#define CTRL_TFCE (1U << 28) /* Tx flow control enable */
+#define CTRL_VME (1U << 30) /* VLAN Mode Enable */
+#define CTRL_PHY_RESET (1U << 31) /* PHY reset (Cordova) */
+
+#define WMREG_CTRL_SHADOW 0x0004 /* Device Control Register (shadow) */
+
+#define WMREG_STATUS 0x0008 /* Device Status Register */
+#define STATUS_FD (1U << 0) /* full duplex */
+#define STATUS_LU (1U << 1) /* link up */
+#define STATUS_TCKOK (1U << 2) /* Tx clock running */
+#define STATUS_RBCOK (1U << 3) /* Rx clock running */
+#define STATUS_FUNCID_SHIFT 2 /* 82546 function ID */
+#define STATUS_FUNCID_MASK 3 /* ... */
+#define STATUS_TXOFF (1U << 4) /* Tx paused */
+#define STATUS_TBIMODE (1U << 5) /* fiber mode (Livengood) */
+#define STATUS_SPEED(x) ((x) << 6) /* speed indication */
+#define STATUS_SPEED_10 STATUS_SPEED(0)
+#define STATUS_SPEED_100 STATUS_SPEED(1)
+#define STATUS_SPEED_1000 STATUS_SPEED(2)
+#define STATUS_ASDV(x) ((x) << 8) /* auto speed det. val. (Livengood) */
+#define STATUS_MTXCKOK (1U << 10) /* MTXD clock running */
+#define STATUS_PCI66 (1U << 11) /* 66MHz bus (Livengood) */
+#define STATUS_BUS64 (1U << 12) /* 64-bit bus (Livengood) */
+#define STATUS_PCIX_MODE (1U << 13) /* PCIX mode (Cordova) */
+#define STATUS_PCIXSPD(x) ((x) << 14) /* PCIX speed indication (Cordova) */
+#define STATUS_PCIXSPD_50_66 STATUS_PCIXSPD(0)
+#define STATUS_PCIXSPD_66_100 STATUS_PCIXSPD(1)
+#define STATUS_PCIXSPD_100_133 STATUS_PCIXSPD(2)
+#define STATUS_PCIXSPD_MASK STATUS_PCIXSPD(3)
+
+#define WMREG_EECD 0x0010 /* EEPROM Control Register */
+#define EECD_SK (1U << 0) /* clock */
+#define EECD_CS (1U << 1) /* chip select */
+#define EECD_DI (1U << 2) /* data in */
+#define EECD_DO (1U << 3) /* data out */
+#define EECD_FWE(x) ((x) << 4) /* flash write enable control */
+#define EECD_FWE_DISABLED EECD_FWE(1)
+#define EECD_FWE_ENABLED EECD_FWE(2)
+#define EECD_EE_REQ (1U << 6) /* (shared) EEPROM request */
+#define EECD_EE_GNT (1U << 7) /* (shared) EEPROM grant */
+#define EECD_EE_PRES (1U << 8) /* EEPROM present */
+#define EECD_EE_SIZE (1U << 9) /* EEPROM size
+ (0 = 64 word, 1 = 256 word) */
+#define EECD_EE_AUTORD (1U << 9) /* auto read done */
+#define EECD_EE_ABITS (1U << 10) /* EEPROM address bits
+ (based on type) */
+#define EECD_EE_TYPE (1U << 13) /* EEPROM type
+ (0 = Microwire, 1 = SPI) */
+#define EECD_SEC1VAL (1U << 22) /* Sector One Valid */
+
+#define UWIRE_OPC_ERASE 0x04 /* MicroWire "erase" opcode */
+#define UWIRE_OPC_WRITE 0x05 /* MicroWire "write" opcode */
+#define UWIRE_OPC_READ 0x06 /* MicroWire "read" opcode */
+
+#define SPI_OPC_WRITE 0x02 /* SPI "write" opcode */
+#define SPI_OPC_READ 0x03 /* SPI "read" opcode */
+#define SPI_OPC_A8 0x08 /* opcode bit 3 == address bit 8 */
+#define SPI_OPC_WREN 0x06 /* SPI "set write enable" opcode */
+#define SPI_OPC_WRDI 0x04 /* SPI "clear write enable" opcode */
+#define SPI_OPC_RDSR 0x05 /* SPI "read status" opcode */
+#define SPI_OPC_WRSR 0x01 /* SPI "write status" opcode */
+#define SPI_MAX_RETRIES 5000 /* max wait of 5ms for RDY signal */
+
+#define SPI_SR_RDY 0x01
+#define SPI_SR_WEN 0x02
+#define SPI_SR_BP0 0x04
+#define SPI_SR_BP1 0x08
+#define SPI_SR_WPEN 0x80
+
+#define EEPROM_OFF_MACADDR 0x00 /* MAC address offset */
+#define EEPROM_OFF_CFG1 0x0a /* config word 1 */
+#define EEPROM_OFF_CFG2 0x0f /* config word 2 */
+#define EEPROM_OFF_SWDPIN 0x20 /* SWD Pins (Cordova) */
+
+#define EEPROM_CFG1_LVDID (1U << 0)
+#define EEPROM_CFG1_LSSID (1U << 1)
+#define EEPROM_CFG1_PME_CLOCK (1U << 2)
+#define EEPROM_CFG1_PM (1U << 3)
+#define EEPROM_CFG1_ILOS (1U << 4)
+#define EEPROM_CFG1_SWDPIO_SHIFT 5
+#define EEPROM_CFG1_SWDPIO_MASK (0xf << EEPROM_CFG1_SWDPIO_SHIFT)
+#define EEPROM_CFG1_IPS1 (1U << 8)
+#define EEPROM_CFG1_LRST (1U << 9)
+#define EEPROM_CFG1_FD (1U << 10)
+#define EEPROM_CFG1_FRCSPD (1U << 11)
+#define EEPROM_CFG1_IPS0 (1U << 12)
+#define EEPROM_CFG1_64_32_BAR (1U << 13)
+
+#define EEPROM_CFG2_CSR_RD_SPLIT (1U << 1)
+#define EEPROM_CFG2_APM_EN (1U << 2)
+#define EEPROM_CFG2_64_BIT (1U << 3)
+#define EEPROM_CFG2_MAX_READ (1U << 4)
+#define EEPROM_CFG2_DMCR_MAP (1U << 5)
+#define EEPROM_CFG2_133_CAP (1U << 6)
+#define EEPROM_CFG2_MSI_DIS (1U << 7)
+#define EEPROM_CFG2_FLASH_DIS (1U << 8)
+#define EEPROM_CFG2_FLASH_SIZE(x) (((x) & 3) >> 9)
+#define EEPROM_CFG2_ANE (1U << 11)
+#define EEPROM_CFG2_PAUSE(x) (((x) & 3) >> 12)
+#define EEPROM_CFG2_ASDE (1U << 14)
+#define EEPROM_CFG2_APM_PME (1U << 15)
+#define EEPROM_CFG2_SWDPIO_SHIFT 4
+#define EEPROM_CFG2_SWDPIO_MASK (0xf << EEPROM_CFG2_SWDPIO_SHIFT)
+
+#define EEPROM_SWDPIN_MASK 0xdf
+#define EEPROM_SWDPIN_SWDPIN_SHIFT 0
+#define EEPROM_SWDPIN_SWDPIO_SHIFT 8
+
+#define WMREG_EERD 0x0014 /* EEPROM read */
+#define EERD_DONE 0x02 /* done bit */
+#define EERD_START 0x01 /* First bit for telling part to start operation */
+#define EERD_ADDR_SHIFT 2 /* Shift to the address bits */
+#define EERD_DATA_SHIFT 16 /* Offset to data in EEPROM read/write registers */
+
+#define WMREG_CTRL_EXT 0x0018 /* Extended Device Control Register */
+#define CTRL_EXT_GPI_EN(x) (1U << (x)) /* gpin interrupt enable */
+#define CTRL_EXT_SWDPINS_SHIFT 4
+#define CTRL_EXT_SWDPINS_MASK 0x0d
+#define CTRL_EXT_SWDPIN(x) (1U << (CTRL_EXT_SWDPINS_SHIFT + (x) - 4))
+#define CTRL_EXT_SWDPIO_SHIFT 8
+#define CTRL_EXT_SWDPIO_MASK 0x0d
+#define CTRL_EXT_SWDPIO(x) (1U << (CTRL_EXT_SWDPIO_SHIFT + (x) - 4))
+#define CTRL_EXT_ASDCHK (1U << 12) /* ASD check */
+#define CTRL_EXT_EE_RST (1U << 13) /* EEPROM reset */
+#define CTRL_EXT_IPS (1U << 14) /* invert power state bit 0 */
+#define CTRL_EXT_SPD_BYPS (1U << 15) /* speed select bypass */
+#define CTRL_EXT_IPS1 (1U << 16) /* invert power state bit 1 */
+#define CTRL_EXT_RO_DIS (1U << 17) /* relaxed ordering disabled */
+#define CTRL_EXT_LINK_MODE_MASK 0x00C00000
+#define CTRL_EXT_LINK_MODE_GMII 0x00000000
+#define CTRL_EXT_LINK_MODE_TBI 0x00C00000
+#define CTRL_EXT_LINK_MODE_KMRN 0x00000000
+#define CTRL_EXT_LINK_MODE_SERDES 0x00C00000
+
+
+#define WMREG_MDIC 0x0020 /* MDI Control Register */
+#define MDIC_DATA(x) ((x) & 0xffff)
+#define MDIC_REGADD(x) ((x) << 16)
+#define MDIC_PHYADD(x) ((x) << 21)
+#define MDIC_OP_WRITE (1U << 26)
+#define MDIC_OP_READ (2U << 26)
+#define MDIC_READY (1U << 28)
+#define MDIC_I (1U << 29) /* interrupt on MDI complete */
+#define MDIC_E (1U << 30) /* MDI error */
+
+#define WMREG_FCAL 0x0028 /* Flow Control Address Low */
+#define FCAL_CONST 0x00c28001 /* Flow Control MAC addr low */
+
+#define WMREG_FCAH 0x002c /* Flow Control Address High */
+#define FCAH_CONST 0x00000100 /* Flow Control MAC addr high */
+
+#define WMREG_FCT 0x0030 /* Flow Control Type */
+
+#define WMREG_VET 0x0038 /* VLAN Ethertype */
+
+#define WMREG_RAL_BASE 0x0040 /* Receive Address List */
+#define WMREG_CORDOVA_RAL_BASE 0x5400
+#define WMREG_RAL_LO(b, x) ((b) + ((x) << 3))
+#define WMREG_RAL_HI(b, x) (WMREG_RAL_LO(b, x) + 4)
+ /*
+ * Receive Address List: The LO part is the low-order 32-bits
+ * of the MAC address. The HI part is the high-order 16-bits
+ * along with a few control bits.
+ */
+#define RAL_AS(x) ((x) << 16) /* address select */
+#define RAL_AS_DEST RAL_AS(0) /* (cordova?) */
+#define RAL_AS_SOURCE RAL_AS(1) /* (cordova?) */
+#define RAL_RDR1 (1U << 30) /* put packet in alt. rx ring */
+#define RAL_AV (1U << 31) /* entry is valid */
+
+#define WM_RAL_TABSIZE 16
+#define WM_ICH8_RAL_TABSIZE 7
+
+#define WMREG_ICR 0x00c0 /* Interrupt Cause Register */
+#define ICR_TXDW (1U << 0) /* Tx desc written back */
+#define ICR_TXQE (1U << 1) /* Tx queue empty */
+#define ICR_LSC (1U << 2) /* link status change */
+#define ICR_RXSEQ (1U << 3) /* receive sequence error */
+#define ICR_RXDMT0 (1U << 4) /* Rx ring 0 nearly empty */
+#define ICR_RXO (1U << 6) /* Rx overrun */
+#define ICR_RXT0 (1U << 7) /* Rx ring 0 timer */
+#define ICR_MDAC (1U << 9) /* MDIO access complete */
+#define ICR_RXCFG (1U << 10) /* Receiving /C/ */
+#define ICR_GPI(x) (1U << (x)) /* general purpose interrupts */
+#define ICR_INT (1U << 31) /* device generated an interrupt */
+
+#define WMREG_ITR 0x00c4 /* Interrupt Throttling Register */
+#define ITR_IVAL_MASK 0xffff /* Interval mask */
+#define ITR_IVAL_SHIFT 0 /* Interval shift */
+
+#define WMREG_ICS 0x00c8 /* Interrupt Cause Set Register */
+ /* See ICR bits. */
+
+#define WMREG_IMS 0x00d0 /* Interrupt Mask Set Register */
+ /* See ICR bits. */
+
+#define WMREG_IMC 0x00d8 /* Interrupt Mask Clear Register */
+ /* See ICR bits. */
+
+#define WMREG_RCTL 0x0100 /* Receive Control */
+#define RCTL_EN (1U << 1) /* receiver enable */
+#define RCTL_SBP (1U << 2) /* store bad packets */
+#define RCTL_UPE (1U << 3) /* unicast promisc. enable */
+#define RCTL_MPE (1U << 4) /* multicast promisc. enable */
+#define RCTL_LPE (1U << 5) /* large packet enable */
+#define RCTL_LBM(x) ((x) << 6) /* loopback mode */
+#define RCTL_LBM_NONE RCTL_LBM(0)
+#define RCTL_LBM_PHY RCTL_LBM(3)
+#define RCTL_RDMTS(x) ((x) << 8) /* receive desc. min thresh size */
+#define RCTL_RDMTS_1_2 RCTL_RDMTS(0)
+#define RCTL_RDMTS_1_4 RCTL_RDMTS(1)
+#define RCTL_RDMTS_1_8 RCTL_RDMTS(2)
+#define RCTL_RDMTS_MASK RCTL_RDMTS(3)
+#define RCTL_MO(x) ((x) << 12) /* multicast offset */
+#define RCTL_BAM (1U << 15) /* broadcast accept mode */
+#define RCTL_2k (0 << 16) /* 2k Rx buffers */
+#define RCTL_1k (1 << 16) /* 1k Rx buffers */
+#define RCTL_512 (2 << 16) /* 512 byte Rx buffers */
+#define RCTL_256 (3 << 16) /* 256 byte Rx buffers */
+#define RCTL_BSEX_16k (1 << 16) /* 16k Rx buffers (BSEX) */
+#define RCTL_BSEX_8k (2 << 16) /* 8k Rx buffers (BSEX) */
+#define RCTL_BSEX_4k (3 << 16) /* 4k Rx buffers (BSEX) */
+#define RCTL_DPF (1U << 22) /* discard pause frames */
+#define RCTL_PMCF (1U << 23) /* pass MAC control frames */
+#define RCTL_BSEX (1U << 25) /* buffer size extension (Livengood) */
+#define RCTL_SECRC (1U << 26) /* strip Ethernet CRC */
+
+#define WMREG_OLD_RDTR0 0x0108 /* Receive Delay Timer (ring 0) */
+#define WMREG_RDTR 0x2820
+#define RDTR_FPD (1U << 31) /* flush partial descriptor */
+
+#define WMREG_RADV 0x282c /* Receive Interrupt Absolute Delay Timer */
+
+#define WMREG_OLD_RDBAL0 0x0110 /* Receive Descriptor Base Low (ring 0) */
+#define WMREG_RDBAL 0x2800
+
+#define WMREG_OLD_RDBAH0 0x0114 /* Receive Descriptor Base High (ring 0) */
+#define WMREG_RDBAH 0x2804
+
+#define WMREG_OLD_RDLEN0 0x0118 /* Receive Descriptor Length (ring 0) */
+#define WMREG_RDLEN 0x2808
+
+#define WMREG_OLD_RDH0 0x0120 /* Receive Descriptor Head (ring 0) */
+#define WMREG_RDH 0x2810
+
+#define WMREG_OLD_RDT0 0x0128 /* Receive Descriptor Tail (ring 0) */
+#define WMREG_RDT 0x2818
+
+#define WMREG_RXDCTL 0x2828 /* Receive Descriptor Control */
+#define RXDCTL_PTHRESH(x) ((x) << 0) /* prefetch threshold */
+#define RXDCTL_HTHRESH(x) ((x) << 8) /* host threshold */
+#define RXDCTL_WTHRESH(x) ((x) << 16) /* write back threshold */
+#define RXDCTL_GRAN (1U << 24) /* 0 = cacheline, 1 = descriptor */
+
+#define WMREG_OLD_RDTR1 0x0130 /* Receive Delay Timer (ring 1) */
+
+#define WMREG_OLD_RDBA1_LO 0x0138 /* Receive Descriptor Base Low (ring 1) */
+
+#define WMREG_OLD_RDBA1_HI 0x013c /* Receive Descriptor Base High (ring 1) */
+
+#define WMREG_OLD_RDLEN1 0x0140 /* Receive Drscriptor Length (ring 1) */
+
+#define WMREG_OLD_RDH1 0x0148
+
+#define WMREG_OLD_RDT1 0x0150
+
+#define WMREG_OLD_FCRTH 0x0160 /* Flow Control Rx Threshold Hi (OLD) */
+#define WMREG_FCRTL 0x2160 /* Flow Control Rx Threshold Lo */
+#define FCRTH_DFLT 0x00008000
+
+#define WMREG_OLD_FCRTL 0x0168 /* Flow Control Rx Threshold Lo (OLD) */
+#define WMREG_FCRTH 0x2168 /* Flow Control Rx Threhsold Hi */
+#define FCRTL_DFLT 0x00004000
+#define FCRTL_XONE 0x80000000 /* Enable XON frame transmission */
+
+#define WMREG_FCTTV 0x0170 /* Flow Control Transmit Timer Value */
+#define FCTTV_DFLT 0x00000600
+
+#define WMREG_TXCW 0x0178 /* Transmit Configuration Word (TBI mode) */
+ /* See MII ANAR_X bits. */
+#define TXCW_TxConfig (1U << 30) /* Tx Config */
+#define TXCW_ANE (1U << 31) /* Autonegotiate */
+
+#define WMREG_RXCW 0x0180 /* Receive Configuration Word (TBI mode) */
+ /* See MII ANLPAR_X bits. */
+#define RXCW_NC (1U << 26) /* no carrier */
+#define RXCW_IV (1U << 27) /* config invalid */
+#define RXCW_CC (1U << 28) /* config change */
+#define RXCW_C (1U << 29) /* /C/ reception */
+#define RXCW_SYNCH (1U << 30) /* synchronized */
+#define RXCW_ANC (1U << 31) /* autonegotiation complete */
+
+#define WMREG_MTA 0x0200 /* Multicast Table Array */
+#define WMREG_CORDOVA_MTA 0x5200
+
+#define WMREG_TCTL 0x0400 /* Transmit Control Register */
+#define TCTL_EN (1U << 1) /* transmitter enable */
+#define TCTL_PSP (1U << 3) /* pad short packets */
+#define TCTL_CT(x) (((x) & 0xff) << 4) /* 4:11 - collision threshold */
+#define TCTL_COLD(x) (((x) & 0x3ff) << 12) /* 12:21 - collision distance */
+#define TCTL_SWXOFF (1U << 22) /* software XOFF */
+#define TCTL_RTLC (1U << 24) /* retransmit on late collision */
+#define TCTL_NRTU (1U << 25) /* no retransmit on underrun */
+#define TCTL_MULR (1U << 28) /* multiple request */
+
+#define TX_COLLISION_THRESHOLD 15
+#define TX_COLLISION_DISTANCE_HDX 512
+#define TX_COLLISION_DISTANCE_FDX 64
+
+#define WMREG_TCTL_EXT 0x0404 /* Transmit Control Register */
+#define TCTL_EXT_BST_MASK 0x000003FF /* Backoff Slot Time */
+#define TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */
+
+#define DEFAULT_80003ES2LAN_TCTL_EXT_GCEX 0x00010000
+
+#define WMREG_TQSA_LO 0x0408
+
+#define WMREG_TQSA_HI 0x040c
+
+#define WMREG_TIPG 0x0410 /* Transmit IPG Register */
+#define TIPG_IPGT(x) (x) /* IPG transmit time */
+#define TIPG_IPGR1(x) ((x) << 10) /* IPG receive time 1 */
+#define TIPG_IPGR2(x) ((x) << 20) /* IPG receive time 2 */
+
+#define TIPG_WM_DFLT (TIPG_IPGT(0x0a) | TIPG_IPGR1(0x02) | TIPG_IPGR2(0x0a))
+#define TIPG_LG_DFLT (TIPG_IPGT(0x06) | TIPG_IPGR1(0x08) | TIPG_IPGR2(0x06))
+#define TIPG_1000T_DFLT (TIPG_IPGT(0x08) | TIPG_IPGR1(0x08) | TIPG_IPGR2(0x06))
+#define TIPG_1000T_80003_DFLT \
+ (TIPG_IPGT(0x08) | TIPG_IPGR1(0x02) | TIPG_IPGR2(0x07))
+#define TIPG_10_100_80003_DFLT \
+ (TIPG_IPGT(0x09) | TIPG_IPGR1(0x02) | TIPG_IPGR2(0x07))
+
+#define WMREG_TQC 0x0418
+
+#define WMREG_EEWR 0x102c /* EEPROM write */
+
+#define WMREG_RDFH 0x2410 /* Receive Data FIFO Head */
+
+#define WMREG_RDFT 0x2418 /* Receive Data FIFO Tail */
+
+#define WMREG_RDFHS 0x2420 /* Receive Data FIFO Head Saved */
+
+#define WMREG_RDFTS 0x2428 /* Receive Data FIFO Tail Saved */
+
+#define WMREG_TDFH 0x3410 /* Transmit Data FIFO Head */
+
+#define WMREG_TDFT 0x3418 /* Transmit Data FIFO Tail */
+
+#define WMREG_TDFHS 0x3420 /* Transmit Data FIFO Head Saved */
+
+#define WMREG_TDFTS 0x3428 /* Transmit Data FIFO Tail Saved */
+
+#define WMREG_TDFPC 0x3430 /* Transmit Data FIFO Packet Count */
+
+#define WMREG_OLD_TBDAL 0x0420 /* Transmit Descriptor Base Lo */
+#define WMREG_TBDAL 0x3800
+
+#define WMREG_OLD_TBDAH 0x0424 /* Transmit Descriptor Base Hi */
+#define WMREG_TBDAH 0x3804
+
+#define WMREG_OLD_TDLEN 0x0428 /* Transmit Descriptor Length */
+#define WMREG_TDLEN 0x3808
+
+#define WMREG_OLD_TDH 0x0430 /* Transmit Descriptor Head */
+#define WMREG_TDH 0x3810
+
+#define WMREG_OLD_TDT 0x0438 /* Transmit Descriptor Tail */
+#define WMREG_TDT 0x3818
+
+#define WMREG_OLD_TIDV 0x0440 /* Transmit Delay Interrupt Value */
+#define WMREG_TIDV 0x3820
+
+#define WMREG_TXDCTL 0x3828 /* Trandmit Descriptor Control */
+#define TXDCTL_PTHRESH(x) ((x) << 0) /* prefetch threshold */
+#define TXDCTL_HTHRESH(x) ((x) << 8) /* host threshold */
+#define TXDCTL_WTHRESH(x) ((x) << 16) /* write back threshold */
+
+#define WMREG_TADV 0x382c /* Transmit Absolute Interrupt Delay Timer */
+
+#define WMREG_AIT 0x0458 /* Adaptive IFS Throttle */
+
+#define WMREG_VFTA 0x0600
+
+#define WM_MC_TABSIZE 128
+#define WM_ICH8_MC_TABSIZE 32
+#define WM_VLAN_TABSIZE 128
+
+#define WMREG_PBA 0x1000 /* Packet Buffer Allocation */
+#define PBA_BYTE_SHIFT 10 /* KB -> bytes */
+#define PBA_ADDR_SHIFT 7 /* KB -> quadwords */
+#define PBA_8K 0x0008
+#define PBA_12K 0x000c
+#define PBA_16K 0x0010 /* 16K, default Tx allocation */
+#define PBA_22K 0x0016
+#define PBA_24K 0x0018
+#define PBA_30K 0x001e
+#define PBA_32K 0x0020
+#define PBA_40K 0x0028
+#define PBA_48K 0x0030 /* 48K, default Rx allocation */
+
+#define WMREG_PBS 0x1000 /* Packet Buffer Size (ICH8 only ?) */
+
+#define WMREG_TXDMAC 0x3000 /* Transfer DMA Control */
+#define TXDMAC_DPP (1U << 0) /* disable packet prefetch */
+
+#define WMREG_TSPMT 0x3830 /* TCP Segmentation Pad and Minimum
+ Threshold (Cordova) */
+#define TSPMT_TSMT(x) (x) /* TCP seg min transfer */
+#define TSPMT_TSPBP(x) ((x) << 16) /* TCP seg pkt buf padding */
+
+#define WMREG_RXCSUM 0x5000 /* Receive Checksum register */
+#define RXCSUM_PCSS 0x000000ff /* Packet Checksum Start */
+#define RXCSUM_IPOFL (1U << 8) /* IP checksum offload */
+#define RXCSUM_TUOFL (1U << 9) /* TCP/UDP checksum offload */
+#define RXCSUM_IPV6OFL (1U << 10) /* IPv6 checksum offload */
+
+#define WMREG_RXERRC 0x400C /* receive error Count - R/clr */
+#define WMREG_COLC 0x4028 /* collision Count - R/clr */
+#define WMREG_XONRXC 0x4048 /* XON Rx Count - R/clr */
+#define WMREG_XONTXC 0x404c /* XON Tx Count - R/clr */
+#define WMREG_XOFFRXC 0x4050 /* XOFF Rx Count - R/clr */
+#define WMREG_XOFFTXC 0x4054 /* XOFF Tx Count - R/clr */
+#define WMREG_FCRUC 0x4058 /* Flow Control Rx Unsupported Count - R/clr */
+
+#define WMREG_KUMCTRLSTA 0x0034 /* MAC-PHY interface - RW */
+#define KUMCTRLSTA_MASK 0x0000FFFF
+#define KUMCTRLSTA_OFFSET 0x001F0000
+#define KUMCTRLSTA_OFFSET_SHIFT 16
+#define KUMCTRLSTA_REN 0x00200000
+
+#define KUMCTRLSTA_OFFSET_FIFO_CTRL 0x00000000
+#define KUMCTRLSTA_OFFSET_CTRL 0x00000001
+#define KUMCTRLSTA_OFFSET_INB_CTRL 0x00000002
+#define KUMCTRLSTA_OFFSET_DIAG 0x00000003
+#define KUMCTRLSTA_OFFSET_TIMEOUTS 0x00000004
+#define KUMCTRLSTA_OFFSET_INB_PARAM 0x00000009
+#define KUMCTRLSTA_OFFSET_HD_CTRL 0x00000010
+#define KUMCTRLSTA_OFFSET_M2P_SERDES 0x0000001E
+#define KUMCTRLSTA_OFFSET_M2P_MODES 0x0000001F
+
+/* FIFO Control */
+#define KUMCTRLSTA_FIFO_CTRL_RX_BYPASS 0x00000008
+#define KUMCTRLSTA_FIFO_CTRL_TX_BYPASS 0x00000800
+
+/* In-Band Control */
+#define KUMCTRLSTA_INB_CTRL_LINK_TMOUT_DFLT 0x00000500
+#define KUMCTRLSTA_INB_CTRL_DIS_PADDING 0x00000010
+
+/* Half-Duplex Control */
+#define KUMCTRLSTA_HD_CTRL_10_100_DEFAULT 0x00000004
+#define KUMCTRLSTA_HD_CTRL_1000_DEFAULT 0x00000000
+
+#define WMREG_MDPHYA 0x003C /* PHY address - RW */
+
+#define WMREG_MANC2H 0x5860 /* Managment Control To Host - RW */
+
+#define WMREG_SWSM 0x5b50 /* SW Semaphore */
+#define SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
+#define SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
+#define SWSM_WMNG 0x00000004 /* Wake MNG Clock */
+#define SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */
+
+#define WMREG_SW_FW_SYNC 0x5b5c /* software-firmware semaphore */
+#define SWFW_EEP_SM 0x0001 /* eeprom access */
+#define SWFW_PHY0_SM 0x0002 /* first ctrl phy access */
+#define SWFW_PHY1_SM 0x0004 /* second ctrl phy access */
+#define SWFW_MAC_CSR_SM 0x0008
+#define SWFW_SOFT_SHIFT 0 /* software semaphores */
+#define SWFW_FIRM_SHIFT 16 /* firmware semaphores */
+
+#define WMREG_EXTCNFCTR 0x0f00 /* Extended Configuration Control */
+#define EXTCNFCTR_PCIE_WRITE_ENABLE 0x00000001
+#define EXTCNFCTR_PHY_WRITE_ENABLE 0x00000002
+#define EXTCNFCTR_D_UD_ENABLE 0x00000004
+#define EXTCNFCTR_D_UD_LATENCY 0x00000008
+#define EXTCNFCTR_D_UD_OWNER 0x00000010
+#define EXTCNFCTR_MDIO_SW_OWNERSHIP 0x00000020
+#define EXTCNFCTR_MDIO_HW_OWNERSHIP 0x00000040
+#define EXTCNFCTR_EXT_CNF_POINTER 0x0FFF0000
+#define E1000_EXTCNF_CTRL_SWFLAG EXTCNFCTR_MDIO_SW_OWNERSHIP
+
+/* ich8 flash control */
+#define ICH_FLASH_COMMAND_TIMEOUT 5000 /* 5000 uSecs - adjusted */
+#define ICH_FLASH_ERASE_TIMEOUT 3000000 /* Up to 3 seconds - worst case */
+#define ICH_FLASH_CYCLE_REPEAT_COUNT 10 /* 10 cycles */
+#define ICH_FLASH_SEG_SIZE_256 256
+#define ICH_FLASH_SEG_SIZE_4K 4096
+#define ICH_FLASH_SEG_SIZE_64K 65536
+
+#define ICH_CYCLE_READ 0x0
+#define ICH_CYCLE_RESERVED 0x1
+#define ICH_CYCLE_WRITE 0x2
+#define ICH_CYCLE_ERASE 0x3
+
+#define ICH_FLASH_GFPREG 0x0000
+#define ICH_FLASH_HSFSTS 0x0004 /* Flash Status Register */
+#define HSFSTS_DONE 0x0001 /* Flash Cycle Done */
+#define HSFSTS_ERR 0x0002 /* Flash Cycle Error */
+#define HSFSTS_DAEL 0x0004 /* Direct Access error Log */
+#define HSFSTS_ERSZ_MASK 0x0018 /* Block/Sector Erase Size */
+#define HSFSTS_ERSZ_SHIFT 3
+#define HSFSTS_FLINPRO 0x0020 /* flash SPI cycle in Progress */
+#define HSFSTS_FLDVAL 0x4000 /* Flash Descriptor Valid */
+#define HSFSTS_FLLK 0x8000 /* Flash Configuration Lock-Down */
+#define ICH_FLASH_HSFCTL 0x0006 /* Flash control Register */
+#define HSFCTL_GO 0x0001 /* Flash Cycle Go */
+#define HSFCTL_CYCLE_MASK 0x0006 /* Flash Cycle */
+#define HSFCTL_CYCLE_SHIFT 1
+#define HSFCTL_BCOUNT_MASK 0x0300 /* Data Byte Count */
+#define HSFCTL_BCOUNT_SHIFT 8
+#define ICH_FLASH_FADDR 0x0008
+#define ICH_FLASH_FDATA0 0x0010
+#define ICH_FLASH_FRACC 0x0050
+#define ICH_FLASH_FREG0 0x0054
+#define ICH_FLASH_FREG1 0x0058
+#define ICH_FLASH_FREG2 0x005C
+#define ICH_FLASH_FREG3 0x0060
+#define ICH_FLASH_FPR0 0x0074
+#define ICH_FLASH_FPR1 0x0078
+#define ICH_FLASH_SSFSTS 0x0090
+#define ICH_FLASH_SSFCTL 0x0092
+#define ICH_FLASH_PREOP 0x0094
+#define ICH_FLASH_OPTYPE 0x0096
+#define ICH_FLASH_OPMENU 0x0098
+
+#define ICH_FLASH_REG_MAPSIZE 0x00A0
+#define ICH_FLASH_SECTOR_SIZE 4096
+#define ICH_GFPREG_BASE_MASK 0x1FFF
+#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF
+
+/* start of Kate Feng added */
+#define WMREG_GPTC 0x4080 /* Good packets transmitted count */
+#define WMREG_GPRC 0x4074 /* Good packets received count */
+#define WMREG_CRCERRS 0x4000 /* CRC Error Count */
+#define WMREG_RLEC 0x4040 /* Receive Length Error Count */
+/* end of Kate Feng added */
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/pci_map.c b/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/pci_map.c
new file mode 100644
index 0000000000..c238e637d0
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/pci_map.c
@@ -0,0 +1,131 @@
+/* $NetBSD: pci_map.c,v 1.12 2002/05/30 12:06:43 drochner Exp $ */
+
+/*-
+ * Copyright (c) 2004, 2005 Brookhaven National Laboratory
+ * S. Kate Feng <feng1@bnl.gov>
+ *
+ * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum; by William R. Studenmund; by Jason R. Thorpe.
+ *
+ */
+
+/*
+ * PCI device mapping.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <rtems/rtems/types.h>
+
+#include <bsp/pci.h>
+#include <bsp/pcireg.h>
+
+int pci_io_find(int b, int d, int f, int reg,unsigned *basep,unsigned *sizep)
+{
+ uint32_t address, mask;
+
+ if (reg < PCI_MAPREG_START ||
+#if 0
+ /*
+ * Can't do this check; some devices have mapping registers
+ * way out in left field.
+ */
+ reg >= PCI_MAPREG_END ||
+#endif
+ (reg & 3))
+ rtems_panic("pci_io_find: bad request");
+
+ /*
+ * Section 6.2.5.1, `Address Maps', tells us that:
+ *
+ * 1) The builtin software should have already mapped the device in a
+ * reasonable way.
+ *
+ * 2) A device which wants 2^n bytes of memory will hardwire the bottom
+ * n bits of the address to 0. As recommended, we write all 1s and see
+ * what we get back.
+ */
+ pci_read_config_dword(b,d,f,reg, &address);
+ if ( !(address & PCI_MAPREG_TYPE_IO)) return(1);
+ pci_write_config_dword(b,d,f,reg, 0xffffffff);
+ pci_read_config_dword(b,d,f,reg,&mask);
+ pci_write_config_dword(b,d,f,reg, address);
+
+ if ( (*sizep = PCI_MAPREG_IO_SIZE(mask))== 0) {
+ printk("pci_io_find: void region\n");
+ return(1);
+ }
+ *basep = PCI_MAPREG_IO_ADDR(address);
+ return(0);
+}
+
+int pci_mem_find(int b, int d, int f, int reg, unsigned *basep,unsigned *sizep)
+{
+ uint32_t address, mask;
+
+ if (reg < PCI_MAPREG_START ||
+#if 0
+ /*
+ * Can't do this check; some devices have mapping registers
+ * way out in left field.
+ */
+ reg >= PCI_MAPREG_END ||
+#endif
+ (reg & 3))
+ rtems_panic("pci_mem_find: bad request");
+
+ pci_read_config_dword(b,d,f,reg, &address);
+ if (address & PCI_MAPREG_TYPE_IO) {
+ printk("pci_mem_find: expected type mem, found I/O\n");
+ return(1);
+ }
+
+ /*
+ * Section 6.2.5.1, `Address Maps', tells us that:
+ *
+ * 1) The builtin software should have already mapped the device in a
+ * reasonable way.
+ *
+ * 2) A device which wants 2^n bytes of memory will hardwire the bottom
+ * n bits of the address to 0. As recommended, we write all 1s and see
+ * what we get back.
+ */
+ pci_write_config_dword(b,d,f,reg, 0xffffffff);
+ pci_read_config_dword(b,d,f,reg,&mask);
+ pci_write_config_dword(b,d,f,reg, address);
+ if ( (*sizep = PCI_MAPREG_MEM_SIZE(mask))== 0) {
+ printk("pci_io_find: void region\n");
+ return (1);
+ }
+ *basep = PCI_MAPREG_MEM_ADDR(address);
+ return(0);
+}
+
+int pci_get_capability(int b, int d, int f, int capid,int *offset,uint32_t *value)
+{
+ uint32_t reg, ofs;
+
+ /* i82544EI PCI_CAPLISTPTR_REG */
+ pci_read_config_dword(b,d,f,PCI_CAPLISTPTR_REG, &reg);
+ ofs = PCI_CAPLIST_PTR(reg);
+ while (ofs != 0) {
+#ifdef DIAGNOSTIC
+ if ((ofs & 3) || (ofs < 0x40))
+ panic("pci_get_capability");
+#endif
+ pci_read_config_dword(b,d,f,ofs, &reg);
+ if (PCI_CAPLIST_CAP(reg) == capid) {
+ if (offset)
+ *offset = ofs;
+ if (value)
+ *value = reg;
+ return (1);
+ }
+ ofs = PCI_CAPLIST_NEXT(reg);
+ }
+ return (0);
+}
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/pcireg.h b/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/pcireg.h
new file mode 100644
index 0000000000..4a31bbe621
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/pcireg.h
@@ -0,0 +1,384 @@
+/* $NetBSD: pcireg.h,v 1.44 2003/12/02 16:31:06 briggs Exp $ */
+
+/*
+ * Copyright (c) 1995, 1996, 1999, 2000
+ * Christopher G. Demetriou. All rights reserved.
+ * Copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Charles M. Hannum.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * PCI Class and Revision Register; defines type and revision of device.
+ */
+#define PCI_CLASS_REG 0x08
+
+#define PCI_CLASS_SHIFT 24
+#define PCI_CLASS_MASK 0xff
+#define PCI_CLASS(cr) \
+ (((cr) >> PCI_CLASS_SHIFT) & PCI_CLASS_MASK)
+
+#define PCI_SUBCLASS_SHIFT 16
+#define PCI_SUBCLASS_MASK 0xff
+#define PCI_SUBCLASS(cr) \
+ (((cr) >> PCI_SUBCLASS_SHIFT) & PCI_SUBCLASS_MASK)
+
+#define PCI_INTERFACE_SHIFT 8
+#define PCI_INTERFACE_MASK 0xff
+#define PCI_INTERFACE(cr) \
+ (((cr) >> PCI_INTERFACE_SHIFT) & PCI_INTERFACE_MASK)
+
+#define PCI_REVISION_SHIFT 0
+#define PCI_REVISION_MASK 0xff
+#define PCI_REVISION(cr) \
+ (((cr) >> PCI_REVISION_SHIFT) & PCI_REVISION_MASK)
+
+#define PCI_CLASS_CODE(mainclass, subclass, interface) \
+ ((((mainclass) & PCI_CLASS_MASK) << PCI_CLASS_SHIFT) | \
+ (((subclass) & PCI_SUBCLASS_MASK) << PCI_SUBCLASS_SHIFT) | \
+ (((interface) & PCI_INTERFACE_MASK) << PCI_INTERFACE_SHIFT))
+
+/* base classes */
+#define PCI_CLASS_PREHISTORIC 0x00
+#define PCI_CLASS_MASS_STORAGE 0x01
+#define PCI_CLASS_NETWORK 0x02
+#define PCI_CLASS_DISPLAY 0x03
+#define PCI_CLASS_MULTIMEDIA 0x04
+#define PCI_CLASS_MEMORY 0x05
+#define PCI_CLASS_BRIDGE 0x06
+#define PCI_CLASS_COMMUNICATIONS 0x07
+#define PCI_CLASS_SYSTEM 0x08
+#define PCI_CLASS_INPUT 0x09
+#define PCI_CLASS_DOCK 0x0a
+#define PCI_CLASS_PROCESSOR 0x0b
+#define PCI_CLASS_SERIALBUS 0x0c
+#define PCI_CLASS_WIRELESS 0x0d
+#define PCI_CLASS_I2O 0x0e
+#define PCI_CLASS_SATCOM 0x0f
+#define PCI_CLASS_CRYPTO 0x10
+#define PCI_CLASS_DASP 0x11
+#define PCI_CLASS_UNDEFINED 0xff
+
+/* 0x00 prehistoric subclasses */
+#define PCI_SUBCLASS_PREHISTORIC_MISC 0x00
+#define PCI_SUBCLASS_PREHISTORIC_VGA 0x01
+
+/* 0x01 mass storage subclasses */
+#define PCI_SUBCLASS_MASS_STORAGE_SCSI 0x00
+#define PCI_SUBCLASS_MASS_STORAGE_IDE 0x01
+#define PCI_SUBCLASS_MASS_STORAGE_FLOPPY 0x02
+#define PCI_SUBCLASS_MASS_STORAGE_IPI 0x03
+#define PCI_SUBCLASS_MASS_STORAGE_RAID 0x04
+#define PCI_SUBCLASS_MASS_STORAGE_ATA 0x05
+#define PCI_SUBCLASS_MASS_STORAGE_SATA 0x06
+#define PCI_SUBCLASS_MASS_STORAGE_MISC 0x80
+
+/* 0x02 network subclasses */
+#define PCI_SUBCLASS_NETWORK_ETHERNET 0x00
+#define PCI_SUBCLASS_NETWORK_TOKENRING 0x01
+#define PCI_SUBCLASS_NETWORK_FDDI 0x02
+#define PCI_SUBCLASS_NETWORK_ATM 0x03
+#define PCI_SUBCLASS_NETWORK_ISDN 0x04
+#define PCI_SUBCLASS_NETWORK_WORLDFIP 0x05
+#define PCI_SUBCLASS_NETWORK_PCIMGMULTICOMP 0x06
+#define PCI_SUBCLASS_NETWORK_MISC 0x80
+
+/* 0x03 display subclasses */
+#define PCI_SUBCLASS_DISPLAY_VGA 0x00
+#define PCI_SUBCLASS_DISPLAY_XGA 0x01
+#define PCI_SUBCLASS_DISPLAY_3D 0x02
+#define PCI_SUBCLASS_DISPLAY_MISC 0x80
+
+/* 0x04 multimedia subclasses */
+#define PCI_SUBCLASS_MULTIMEDIA_VIDEO 0x00
+#define PCI_SUBCLASS_MULTIMEDIA_AUDIO 0x01
+#define PCI_SUBCLASS_MULTIMEDIA_TELEPHONY 0x02
+#define PCI_SUBCLASS_MULTIMEDIA_MISC 0x80
+
+/* 0x05 memory subclasses */
+#define PCI_SUBCLASS_MEMORY_RAM 0x00
+#define PCI_SUBCLASS_MEMORY_FLASH 0x01
+#define PCI_SUBCLASS_MEMORY_MISC 0x80
+
+/* 0x06 bridge subclasses */
+#define PCI_SUBCLASS_BRIDGE_HOST 0x00
+#define PCI_SUBCLASS_BRIDGE_ISA 0x01
+#define PCI_SUBCLASS_BRIDGE_EISA 0x02
+#define PCI_SUBCLASS_BRIDGE_MC 0x03 /* XXX _MCA? */
+#define PCI_SUBCLASS_BRIDGE_PCI 0x04
+#define PCI_SUBCLASS_BRIDGE_PCMCIA 0x05
+#define PCI_SUBCLASS_BRIDGE_NUBUS 0x06
+#define PCI_SUBCLASS_BRIDGE_CARDBUS 0x07
+#define PCI_SUBCLASS_BRIDGE_RACEWAY 0x08
+#define PCI_SUBCLASS_BRIDGE_STPCI 0x09
+#define PCI_SUBCLASS_BRIDGE_INFINIBAND 0x0a
+#define PCI_SUBCLASS_BRIDGE_MISC 0x80
+
+/* 0x07 communications subclasses */
+#define PCI_SUBCLASS_COMMUNICATIONS_SERIAL 0x00
+#define PCI_SUBCLASS_COMMUNICATIONS_PARALLEL 0x01
+#define PCI_SUBCLASS_COMMUNICATIONS_MPSERIAL 0x02
+#define PCI_SUBCLASS_COMMUNICATIONS_MODEM 0x03
+#define PCI_SUBCLASS_COMMUNICATIONS_GPIB 0x04
+#define PCI_SUBCLASS_COMMUNICATIONS_SMARTCARD 0x05
+#define PCI_SUBCLASS_COMMUNICATIONS_MISC 0x80
+
+/* 0x08 system subclasses */
+#define PCI_SUBCLASS_SYSTEM_PIC 0x00
+#define PCI_SUBCLASS_SYSTEM_DMA 0x01
+#define PCI_SUBCLASS_SYSTEM_TIMER 0x02
+#define PCI_SUBCLASS_SYSTEM_RTC 0x03
+#define PCI_SUBCLASS_SYSTEM_PCIHOTPLUG 0x04
+#define PCI_SUBCLASS_SYSTEM_MISC 0x80
+
+/* 0x09 input subclasses */
+#define PCI_SUBCLASS_INPUT_KEYBOARD 0x00
+#define PCI_SUBCLASS_INPUT_DIGITIZER 0x01
+#define PCI_SUBCLASS_INPUT_MOUSE 0x02
+#define PCI_SUBCLASS_INPUT_SCANNER 0x03
+#define PCI_SUBCLASS_INPUT_GAMEPORT 0x04
+#define PCI_SUBCLASS_INPUT_MISC 0x80
+
+/* 0x0a dock subclasses */
+#define PCI_SUBCLASS_DOCK_GENERIC 0x00
+#define PCI_SUBCLASS_DOCK_MISC 0x80
+
+/* 0x0b processor subclasses */
+#define PCI_SUBCLASS_PROCESSOR_386 0x00
+#define PCI_SUBCLASS_PROCESSOR_486 0x01
+#define PCI_SUBCLASS_PROCESSOR_PENTIUM 0x02
+#define PCI_SUBCLASS_PROCESSOR_ALPHA 0x10
+#define PCI_SUBCLASS_PROCESSOR_POWERPC 0x20
+#define PCI_SUBCLASS_PROCESSOR_MIPS 0x30
+#define PCI_SUBCLASS_PROCESSOR_COPROC 0x40
+
+/* 0x0c serial bus subclasses */
+#define PCI_SUBCLASS_SERIALBUS_FIREWIRE 0x00
+#define PCI_SUBCLASS_SERIALBUS_ACCESS 0x01
+#define PCI_SUBCLASS_SERIALBUS_SSA 0x02
+#define PCI_SUBCLASS_SERIALBUS_USB 0x03
+#define PCI_SUBCLASS_SERIALBUS_FIBER 0x04 /* XXX _FIBRECHANNEL */
+#define PCI_SUBCLASS_SERIALBUS_SMBUS 0x05
+#define PCI_SUBCLASS_SERIALBUS_INFINIBAND 0x06
+#define PCI_SUBCLASS_SERIALBUS_IPMI 0x07
+#define PCI_SUBCLASS_SERIALBUS_SERCOS 0x08
+#define PCI_SUBCLASS_SERIALBUS_CANBUS 0x09
+
+/* 0x0d wireless subclasses */
+#define PCI_SUBCLASS_WIRELESS_IRDA 0x00
+#define PCI_SUBCLASS_WIRELESS_CONSUMERIR 0x01
+#define PCI_SUBCLASS_WIRELESS_RF 0x10
+#define PCI_SUBCLASS_WIRELESS_BLUETOOTH 0x11
+#define PCI_SUBCLASS_WIRELESS_BROADBAND 0x12
+#define PCI_SUBCLASS_WIRELESS_802_11A 0x20
+#define PCI_SUBCLASS_WIRELESS_802_11B 0x21
+#define PCI_SUBCLASS_WIRELESS_MISC 0x80
+
+/* 0x0e I2O (Intelligent I/O) subclasses */
+#define PCI_SUBCLASS_I2O_STANDARD 0x00
+
+/* 0x0f satellite communication subclasses */
+/* PCI_SUBCLASS_SATCOM_??? 0x00 / * XXX ??? */
+#define PCI_SUBCLASS_SATCOM_TV 0x01
+#define PCI_SUBCLASS_SATCOM_AUDIO 0x02
+#define PCI_SUBCLASS_SATCOM_VOICE 0x03
+#define PCI_SUBCLASS_SATCOM_DATA 0x04
+
+/* 0x10 encryption/decryption subclasses */
+#define PCI_SUBCLASS_CRYPTO_NETCOMP 0x00
+#define PCI_SUBCLASS_CRYPTO_ENTERTAINMENT 0x10
+#define PCI_SUBCLASS_CRYPTO_MISC 0x80
+
+/* 0x11 data acquisition and signal processing subclasses */
+#define PCI_SUBCLASS_DASP_DPIO 0x00
+#define PCI_SUBCLASS_DASP_TIMEFREQ 0x01
+#define PCI_SUBCLASS_DASP_SYNC 0x10
+#define PCI_SUBCLASS_DASP_MGMT 0x20
+#define PCI_SUBCLASS_DASP_MISC 0x80
+
+/*
+ * PCI BIST/Header Type/Latency Timer/Cache Line Size Register.
+ */
+#define PCI_BHLC_REG 0x0c
+
+#define PCI_BIST_SHIFT 24
+#define PCI_BIST_MASK 0xff
+#define PCI_BIST(bhlcr) \
+ (((bhlcr) >> PCI_BIST_SHIFT) & PCI_BIST_MASK)
+
+#define PCI_HDRTYPE_SHIFT 16
+#define PCI_HDRTYPE_MASK 0xff
+#define PCI_HDRTYPE(bhlcr) \
+ (((bhlcr) >> PCI_HDRTYPE_SHIFT) & PCI_HDRTYPE_MASK)
+
+#define PCI_HDRTYPE_TYPE(bhlcr) \
+ (PCI_HDRTYPE(bhlcr) & 0x7f)
+#define PCI_HDRTYPE_MULTIFN(bhlcr) \
+ ((PCI_HDRTYPE(bhlcr) & 0x80) != 0)
+
+#define PCI_LATTIMER_SHIFT 8
+#define PCI_LATTIMER_MASK 0xff
+#define PCI_LATTIMER(bhlcr) \
+ (((bhlcr) >> PCI_LATTIMER_SHIFT) & PCI_LATTIMER_MASK)
+
+#define PCI_CACHELINE_SHIFT 0
+#define PCI_CACHELINE_MASK 0xff
+#define PCI_CACHELINE(bhlcr) \
+ (((bhlcr) >> PCI_CACHELINE_SHIFT) & PCI_CACHELINE_MASK)
+
+#define PCI_BHLC_CODE(bist,type,multi,latency,cacheline) \
+ ((((bist) & PCI_BIST_MASK) << PCI_BIST_SHIFT) | \
+ (((type) & PCI_HDRTYPE_MASK) << PCI_HDRTYPE_SHIFT) | \
+ (((multi)?0x80:0) << PCI_HDRTYPE_SHIFT) | \
+ (((latency) & PCI_LATTIMER_MASK) << PCI_LATTIMER_SHIFT) | \
+ (((cacheline) & PCI_CACHELINE_MASK) << PCI_CACHELINE_SHIFT))
+
+/*
+ * PCI header type
+ */
+#define PCI_HDRTYPE_DEVICE 0
+#define PCI_HDRTYPE_PPB 1
+#define PCI_HDRTYPE_PCB 2
+
+/*
+ * Mapping registers
+ */
+#define PCI_MAPREG_START 0x10
+#define PCI_MAPREG_END 0x28
+#define PCI_MAPREG_ROM 0x30
+#define PCI_MAPREG_PPB_END 0x18
+#define PCI_MAPREG_PCB_END 0x14
+
+#define PCI_MAPREG_TYPE(mr) \
+ ((mr) & PCI_MAPREG_TYPE_MASK)
+#define PCI_MAPREG_TYPE_MASK 0x00000001
+
+#define PCI_MAPREG_TYPE_MEM 0x00000000
+#define PCI_MAPREG_TYPE_IO 0x00000001
+#define PCI_MAPREG_ROM_ENABLE 0x00000001
+
+#define PCI_MAPREG_MEM_TYPE(mr) \
+ ((mr) & PCI_MAPREG_MEM_TYPE_MASK)
+#define PCI_MAPREG_MEM_TYPE_MASK 0x00000006
+
+#define PCI_MAPREG_MEM_TYPE_32BIT 0x00000000
+#define PCI_MAPREG_MEM_TYPE_32BIT_1M 0x00000002
+#define PCI_MAPREG_MEM_TYPE_64BIT 0x00000004
+
+#define PCI_MAPREG_MEM_PREFETCHABLE(mr) \
+ (((mr) & PCI_MAPREG_MEM_PREFETCHABLE_MASK) != 0)
+#define PCI_MAPREG_MEM_PREFETCHABLE_MASK 0x00000008
+
+#define PCI_MAPREG_MEM_ADDR(mr) \
+ ((mr) & PCI_MAPREG_MEM_ADDR_MASK)
+#define PCI_MAPREG_MEM_SIZE(mr) \
+ (PCI_MAPREG_MEM_ADDR(mr) & -PCI_MAPREG_MEM_ADDR(mr))
+#define PCI_MAPREG_MEM_ADDR_MASK 0xfffffff0
+
+#define PCI_MAPREG_MEM64_ADDR(mr) \
+ ((mr) & PCI_MAPREG_MEM64_ADDR_MASK)
+#define PCI_MAPREG_MEM64_SIZE(mr) \
+ (PCI_MAPREG_MEM64_ADDR(mr) & -PCI_MAPREG_MEM64_ADDR(mr))
+#define PCI_MAPREG_MEM64_ADDR_MASK 0xfffffffffffffff0ULL
+
+#define PCI_MAPREG_IO_ADDR(mr) \
+ ((mr) & PCI_MAPREG_IO_ADDR_MASK)
+#define PCI_MAPREG_IO_SIZE(mr) \
+ (PCI_MAPREG_IO_ADDR(mr) & -PCI_MAPREG_IO_ADDR(mr))
+#define PCI_MAPREG_IO_ADDR_MASK 0xfffffffc
+
+#define PCI_MAPREG_SIZE_TO_MASK(size) \
+ (-(size))
+
+#define PCI_MAPREG_NUM(offset) \
+ (((unsigned)(offset)-PCI_MAPREG_START)/4)
+
+
+/*
+ * Cardbus CIS pointer (PCI rev. 2.1)
+ */
+#define PCI_CARDBUS_CIS_REG 0x28
+
+/*
+ * Subsystem identification register; contains a vendor ID and a device ID.
+ * Types/macros for PCI_ID_REG apply.
+ * (PCI rev. 2.1)
+ */
+#define PCI_SUBSYS_ID_REG 0x2c
+
+/*
+ * capabilities link list (PCI rev. 2.2)
+ */
+#define PCI_CAPLISTPTR_REG 0x34 /* header type 0 */
+#define PCI_CARDBUS_CAPLISTPTR_REG 0x14 /* header type 2 */
+#define PCI_CAPLIST_PTR(cpr) ((cpr) & 0xff)
+#define PCI_CAPLIST_NEXT(cr) (((cr) >> 8) & 0xff)
+#define PCI_CAPLIST_CAP(cr) ((cr) & 0xff)
+
+#define PCI_CAP_RESERVED0 0x00
+#define PCI_CAP_PWRMGMT 0x01
+#define PCI_CAP_AGP 0x02
+#define PCI_CAP_VPD 0x03
+#define PCI_CAP_SLOTID 0x04
+#define PCI_CAP_MSI 0x05
+#define PCI_CAP_CPCI_HOTSWAP 0x06
+#define PCI_CAP_PCIX 0x07
+#define PCI_CAP_LDT 0x08
+#define PCI_CAP_VENDSPEC 0x09
+#define PCI_CAP_DEBUGPORT 0x0a
+#define PCI_CAP_CPCI_RSRCCTL 0x0b
+#define PCI_CAP_HOTPLUG 0x0c
+#define PCI_CAP_AGP8 0x0e
+#define PCI_CAP_SECURE 0x0f
+#define PCI_CAP_PCIEXPRESS 0x10
+#define PCI_CAP_MSIX 0x11
+
+/*
+ * Vital Product Data; access via capability pointer (PCI rev 2.2).
+ */
+#define PCI_VPD_ADDRESS_MASK 0x7fff
+#define PCI_VPD_ADDRESS_SHIFT 16
+#define PCI_VPD_ADDRESS(ofs) \
+ (((ofs) & PCI_VPD_ADDRESS_MASK) << PCI_VPD_ADDRESS_SHIFT)
+#define PCI_VPD_DATAREG(ofs) ((ofs) + 4)
+#define PCI_VPD_OPFLAG 0x80000000
+
+/*
+ * Power Management Capability; access via capability pointer.
+ */
+
+/* Power Management Capability Register */
+#define PCI_PMCR 0x02
+#define PCI_PMCR_D1SUPP 0x0200
+#define PCI_PMCR_D2SUPP 0x0400
+/* Power Management Control Status Register */
+#define PCI_PMCSR 0x04
+#define PCI_PMCSR_STATE_MASK 0x03
+#define PCI_PMCSR_STATE_D0 0x00
+#define PCI_PMCSR_STATE_D1 0x01
+#define PCI_PMCSR_STATE_D2 0x02
+#define PCI_PMCSR_STATE_D3 0x03
+
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/pci/pci.c b/c/src/lib/libbsp/powerpc/mvme5500/pci/pci.c
index ed8532ec04..729c8a0640 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/pci/pci.c
+++ b/c/src/lib/libbsp/powerpc/mvme5500/pci/pci.c
@@ -34,8 +34,8 @@
#include <stdio.h>
#include <string.h>
-/* #define PCI_DEBUG 1 */
-/* #define PCI_PRINT 1 */
+#define PCI_DEBUG 0
+#define PCI_PRINT 0
/* allow for overriding these definitions */
#ifndef PCI_CONFIG_ADDR
@@ -251,11 +251,6 @@ int pci_initialize()
unsigned char ucBusNumber, ucSlotNumber, ucFnNumber, ucNumFuncs;
unsigned int ulHeader;
unsigned int pcidata, ulClass, ulDeviceID;
-#if PCI_DEBUG
- unsigned short sdata;
- unsigned int data;
-#endif
-
pci_interface();
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/pci/pci_interface.c b/c/src/lib/libbsp/powerpc/mvme5500/pci/pci_interface.c
index c1a56775d4..f19f9bc69c 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/pci/pci_interface.c
+++ b/c/src/lib/libbsp/powerpc/mvme5500/pci/pci_interface.c
@@ -1,11 +1,15 @@
/* pci_interface.c
*
- * Copyright 2004, Brookhaven National Laboratory and
- * Shuchen Kate Feng <feng1@bnl.gov>
+ * Copyright 2004, 2006, 2007 All rights reserved. (NDA items)
+ * Brookhaven National Laboratory and Shuchen Kate Feng <feng1@bnl.gov>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution.
*
+ * 8/17/2006 : S. Kate Feng
+ * uses in_le32()/out_le32(), instead of inl()/outl() so that
+ * it is easier to be ported.
+ *
*/
#include <libcpu/io.h>
#include <rtems/bspIo.h> /* printk */
@@ -15,15 +19,16 @@
#include <bsp/gtreg.h>
#include <bsp/gtpcireg.h>
+#define REG32_READ(reg) in_le32((volatile unsigned int *)(GT64260_REG_BASE+reg))
+#define REG32_WRITE(data, reg) out_le32((volatile unsigned int *)(GT64260_REG_BASE+reg), data)
+
#define PCI_DEBUG 0
/* Please reference the GT64260B datasheet, for the PCI interface,
* Synchronization Barriers and PCI ordering.
*
* Some PCI devices require Synchronization Barriers or PCI ordering
- * for synchronization. For example, the VME-OMS58 motor controller we
- * used at NSLS requires either enhanced CPU Synchronization Barrier
- * or PCI-ordering (only one mechanism allowed. See section 11.1.2).
+ * for synchronization (only one mechanism allowed. See section 11.1.2).
* To use the former mechanism(default), one needs to call
* CPU0_PciEnhanceSync() or CPU1_PciEnhanceSync() to perform software
* synchronization between the CPU and PCI activities.
@@ -39,12 +44,11 @@
* function correctly.
*
*/
-#define PCI_ORDERING
+/*#define PCI_ORDERING*/
-/*#define PCI_DEADLOCK*/
+#define EN_SYN_BAR /* take MOTLoad default for enhanced SYN Barrier mode */
-/* So far, I do not see the need to disable the address pipelining.
-#define DIS_ADDR_PIPELINE*/
+/*#define PCI_DEADLOCK*/
#ifdef PCI_ORDERING
#define PCI_ACCCTLBASEL_VALUE 0x01009000
@@ -86,40 +90,18 @@ void pciAccessInit();
void pci_interface()
{
- unsigned int data;
-
-#if (defined(PCI_ORDERING)||defined(DIS_ADDR_PIPELINE))
- data = inl(0); /* needed : read to flush */
- /* MOTLOad default disables Configuration and I/O Read Sync Barrier
- * which is needed for enhanced CPU sync. barrier */
-#ifdef PCI_ORDERING
- /* enable Configuration Read Sync Barrier and IO read Sync Barrier*/
- data &= ~ConfIOSBDis;
-#endif
-#ifdef DIS_ADDR_PIPELINE
- data &= ~ADDR_PIPELINE;
-
-#if PCI_DEBUG
- printk("data %x\n", data);
-#endif
-#endif
- outl(data, 0);
- /* read polling of the register until the new data is being read */
- while ( inl(0)!=data);
-#endif
#ifdef PCI_DEADLOCK
- outl(0x07fff600, CNT_SYNC_REG);
+ REG32_WRITE(0x07fff600, CNT_SYNC_REG);
#endif
#ifdef PCI_ORDERING
- outl(0xc0060002, DLOCK_ORDER_REG);
- outl(0x07fff600, CNT_SYNC_REG);
-#else
- outl(inl(PCI_CMD_CNTL)|PCI_COMMAND_SB_DIS, PCI_CMD_CNTL);
+ /* Let's leave this to be MOTLOad deafult : 0x80070000
+ REG32_WRITE(0xc0070000, DLOCK_ORDER_REG);*/
+ /* Leave the CNT_SYNC_REG b/c MOTload default had the SyncBarMode set to 1 */
#endif
/* asserts SERR upon various detection */
- outl(0x3fffff, 0xc28);
+ REG32_WRITE(0x3fffff, 0xc28);
pciAccessInit();
}
@@ -133,13 +115,14 @@ void pciAccessInit()
/* MOTLoad combines the two banks of SDRAM into
* one PCI access control because the top = 0x1ff
*/
- data = inl(GT_SCS0_Low_Decode) & 0xfff;
+ data = REG32_READ(GT_SCS0_Low_Decode) & 0xfff;
data |= PCI_ACCCTLBASEL_VALUE;
data &= ~0x300000;
- outl(data, PCI0_ACCESS_CNTL_BASE0_LOW+(PciLocal * 0x80));
+ REG32_WRITE(data, PCI0_ACCESS_CNTL_BASE0_LOW+(PciLocal * 0x80));
#if PCI_DEBUG
- printk("PCI%d_ACCESS_CNTL_BASE0_LOW 0x%x\n",PciLocal,inl(PCI_ACCESS_CNTL_BASE0_LOW+(PciLocal * 0x80)));
+ printk("PCI%d_ACCESS_CNTL_BASE0_LOW 0x%x\n",PciLocal,REG32_READ(PCI_ACCESS_CNTL_BASE0_LOW+(PciLocal * 0x80)));
#endif
+
}
}
@@ -152,14 +135,14 @@ void pciAccessInit()
*/
void CPU0_PciEnhanceSync(unsigned int syncVal)
{
- outl(syncVal,CPU0_SYNC_TRIGGER);
- while (inl(CPU0_SYNC_VIRTUAL));
+ REG32_WRITE(syncVal,CPU0_SYNC_TRIGGER);
+ while (REG32_READ(CPU0_SYNC_VIRTUAL));
}
void CPU1_PciEnhanceSync(unsigned int syncVal)
{
- outl(syncVal,CPU1_SYNC_TRIGGER);
- while (inl(CPU1_SYNC_VIRTUAL));
+ REG32_WRITE(syncVal,CPU1_SYNC_TRIGGER);
+ while (REG32_READ(CPU1_SYNC_VIRTUAL));
}
/* Currently, if PCI_ordering is used for synchronization, configuration
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/pci/pcifinddevice.c b/c/src/lib/libbsp/powerpc/mvme5500/pci/pcifinddevice.c
index 9fcdd61ae2..c3b677d015 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/pci/pcifinddevice.c
+++ b/c/src/lib/libbsp/powerpc/mvme5500/pci/pcifinddevice.c
@@ -1,56 +1,11 @@
/* pcifinddevice.c
*
+ * Copyright 2001, Till Straumann <strauman@slac.stanford.edu>
*
* find a particular PCI device
* (we assume, the firmware configured the PCI bus[es] for us)
*
- */
-
-/*
- * Authorship
- * ----------
- * This software was created by
- * Till Straumann <strauman@slac.stanford.edu>, 2001,
- * Stanford Linear Accelerator Center, Stanford University.
- *
- * Acknowledgement of sponsorship
- * ------------------------------
- * This software was produced by
- * the Stanford Linear Accelerator Center, Stanford University,
- * under Contract DE-AC03-76SFO0515 with the Department of Energy.
- *
- * Government disclaimer of liability
- * ----------------------------------
- * Neither the United States nor the United States Department of Energy,
- * nor any of their employees, makes any warranty, express or implied, or
- * assumes any legal liability or responsibility for the accuracy,
- * completeness, or usefulness of any data, apparatus, product, or process
- * disclosed, or represents that its use would not infringe privately owned
- * rights.
- *
- * Stanford disclaimer of liability
- * --------------------------------
- * Stanford University makes no representations or warranties, express or
- * implied, nor assumes any liability for the use of this software.
- *
- * Stanford disclaimer of copyright
- * --------------------------------
- * Stanford University, owner of the copyright, hereby disclaims its
- * copyright and all other rights in this software. Hence, anyone may
- * freely use it for any purpose without restriction.
- *
- * Maintenance of notices
- * ----------------------
- * In the interest of clarity regarding the origin and status of this
- * SLAC software, this and all the preceding Stanford University notices
- * are to remain affixed to any copy or derivative of this software made
- * or distributed by the recipient and are to be affixed to any copy of
- * software made or distributed by the recipient that contains a copy or
- * derivative of this software.
*
- * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
- */
-/*
* Kate Feng <feng1@bnl.gov>, modified it to support the mvme5500 board.
*
*/
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/preinstall.am b/c/src/lib/libbsp/powerpc/mvme5500/preinstall.am
index 8caab7ae5e..06011b64f2 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/preinstall.am
+++ b/c/src/lib/libbsp/powerpc/mvme5500/preinstall.am
@@ -19,12 +19,12 @@ PREINSTALL_FILES =
CLEANFILES += $(PREINSTALL_FILES)
$(PROJECT_LIB)/$(dirstamp):
- @$(MKDIR_P) $(PROJECT_LIB)
+ @$(mkdir_p) $(PROJECT_LIB)
@: > $(PROJECT_LIB)/$(dirstamp)
PREINSTALL_DIRS += $(PROJECT_LIB)/$(dirstamp)
$(PROJECT_INCLUDE)/$(dirstamp):
- @$(MKDIR_P) $(PROJECT_INCLUDE)
+ @$(mkdir_p) $(PROJECT_INCLUDE)
@: > $(PROJECT_INCLUDE)/$(dirstamp)
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp)
@@ -49,7 +49,7 @@ $(PROJECT_INCLUDE)/coverhd.h: ../../shared/include/coverhd.h $(PROJECT_INCLUDE)/
PREINSTALL_FILES += $(PROJECT_INCLUDE)/coverhd.h
$(PROJECT_INCLUDE)/bsp/$(dirstamp):
- @$(MKDIR_P) $(PROJECT_INCLUDE)/bsp
+ @$(mkdir_p) $(PROJECT_INCLUDE)/bsp
@: > $(PROJECT_INCLUDE)/bsp/$(dirstamp)
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/bsp/$(dirstamp)
@@ -61,9 +61,9 @@ $(PROJECT_INCLUDE)/bsp/uart.h: ../../powerpc/shared/console/uart.h $(PROJECT_INC
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/uart.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/uart.h
-$(PROJECT_INCLUDE)/bsp/vme_am_defs.h: ../../shared/vmeUniverse/vme_am_defs.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
- $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/vme_am_defs.h
-PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/vme_am_defs.h
+$(PROJECT_INCLUDE)/bsp/consoleIo.h: ../../powerpc/shared/console/consoleIo.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/consoleIo.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/consoleIo.h
$(PROJECT_INCLUDE)/bsp/gtpcireg.h: pci/gtpcireg.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/gtpcireg.h
@@ -106,14 +106,22 @@ $(PROJECT_INCLUDE)/bsp/VPD.h: GT64260/VPD.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/VPD.h
if HAS_NETWORKING
-$(PROJECT_INCLUDE)/bsp/GT64260eth.h: network/GT64260eth.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+$(PROJECT_INCLUDE)/bsp/GT64260eth.h: network/if_100MHz/GT64260eth.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/GT64260eth.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/GT64260eth.h
-$(PROJECT_INCLUDE)/bsp/GT64260ethreg.h: network/GT64260ethreg.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+$(PROJECT_INCLUDE)/bsp/GT64260ethreg.h: network/if_100MHz/GT64260ethreg.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/GT64260ethreg.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/GT64260ethreg.h
+$(PROJECT_INCLUDE)/bsp/if_wmreg.h: network/if_1GHz/if_wmreg.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/if_wmreg.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/if_wmreg.h
+
+$(PROJECT_INCLUDE)/bsp/pcireg.h: network/if_1GHz/pcireg.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/pcireg.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/pcireg.h
endif
+
$(PROJECT_INCLUDE)/bsp/VME.h: ../../shared/vmeUniverse/VME.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/VME.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/VME.h
@@ -126,6 +134,10 @@ $(PROJECT_INCLUDE)/bsp/vmeUniverse.h: ../../shared/vmeUniverse/vmeUniverse.h $(P
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/vmeUniverse.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/vmeUniverse.h
+$(PROJECT_INCLUDE)/bsp/vme_am_defs.h: ../../shared/vmeUniverse/vme_am_defs.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/vme_am_defs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/vme_am_defs.h
+
$(PROJECT_INCLUDE)/bsp/vmeUniverseDMA.h: ../../shared/vmeUniverse/vmeUniverseDMA.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/vmeUniverseDMA.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/vmeUniverseDMA.h
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/start/preload.S b/c/src/lib/libbsp/powerpc/mvme5500/start/preload.S
index 8262f41d7c..9da4b1ca7d 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/start/preload.S
+++ b/c/src/lib/libbsp/powerpc/mvme5500/start/preload.S
@@ -1,9 +1,8 @@
/*
- * Mini-loader for the SVGM and MVME5500 BSP.
+ * Mini-loader for the SVGM BSP.
*
* $Id$
*
- * Copyright (C) 2003, 2004
* Author: Till Straumann, 10/2001 <strauman@slac.stanford.edu>
*
* Some ideas are borrowed from the powerpc/shared/bootloader
@@ -11,9 +10,8 @@
* Copyright (C) 1998, 1999 Gabriel Paubert, paubert@iram.es
* Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
*
- *
- * The SVGM firmware is unable to load the RTEMS image below
- * 0x2000 (I believe their stack is growing below 0x1000) ?
+ * The SMON firmware is unable to load the RTEMS image below
+ * 0x2000 (I believe their stack is growing below 0x1000).
*
* The code provided by this file is responsible for the performing
* the following steps:
@@ -23,13 +21,11 @@
* b) will not be overwritten by the moved image
* nor the final BSS segment (rtems clears BSS
* before saving the command line).
- * 2) Initialize and setup the memory controller to prepare the
- * SDRAM before moving the image to it.
- * 3) Move the entire image (including this very file) to
+ * 2) Move the entire image (including this very file) to
* its final location starting at 0x0000.
* It is important to note that _NO_STACK_ is available
* during this step. Also, there is probably no return to
- * Monitor because relocating RTEMS will destroy vital Monitor
+ * SMON because relocating RTEMS will destroy vital SMON
* data (such as its stack).
* 3) Flush the cache to make sure the relocated image is actually
* in memory.
@@ -44,10 +40,10 @@
*
*
* Calling convention:
- * R1: Monitor SP
+ * R1: SMON SP
* R3: command line string start
* R4: command line string end + 1
- * R5: where Monitor put the image
+ * R5: where SMON put the image
* if R5 is 0, the preloader will use its entry point
* as the image starting address.
* See NOTE below.
@@ -74,10 +70,7 @@
*
*/
#if 0
-/* TODO: I dont know where the appropriate CPU model is to be defined
- * when including this to get PPC_CACHE_ALIGNMENT I get an error...
- */
-#include <rtems/score/ppc.h>
+#include <rtems/score/powerpc.h>
#else
#ifndef PPC_CACHE_ALIGNMENT
#define PPC_CACHE_ALIGNMENT 32
@@ -90,8 +83,8 @@
/* Note that major modifications may be needed
* if DESTINATION_ADDR is not 0
*/
-#define KERNELBASE 0x0
-#define INITIAL_STACK 0x78 /* 8-byte aligned */
+#define KERNELBASE 0x0
+#define INITIAL_STACK 0x78 /* 8-byte aligned */
#define CACHE_LINE_SIZE PPC_CACHE_ALIGNMENT /* autodetect doesn't work, see below */
#define ASSUME_RTEMS_INSTALLS_VECTORS /* assume we need not load vectors */
#define DONT_USE_R5_ENTRY /* always dynamically determine the address we're running from */
@@ -108,10 +101,8 @@ preload:
/* find out where we are */
bl here
here:
- /* MOTLoad had MSR_EE turned on. Disable it.*/
- mfmsr r0
- xori r0, r0, MSR_EE
- mtmsr r0
+ xor r0,r0,r0
+ mtmsr r0 /* clear MSR to known state */
mflr r5
addi r5,r5,-(here-preload)
lis r27,_edata@h
@@ -147,10 +138,9 @@ here:
add r16, r5, r27 /* image end + 1 */
cmpw r16, r18
bge ishighenough
- mr r16,r18 /* __rtems_end is higher than
- * the image end
- * (without bss)
- */
+ mr r16,r18 /* __rtems_end is higher than the image end
+ * (without bss)
+ */
ishighenough:
cmpw r16, r3 /* destination start > current string start ? */
ble leaveparms /* string already after dst, leave it */
@@ -165,7 +155,7 @@ leaveparms:
add r7, r6, r17 /* destination + strlen */
#ifndef CACHE_LINE_SIZE
- /* Oh well, Monitor firmware has inhibited the cache, so this
+ /* Oh well, SMON has inhibited the cache, so this
* nice routine doesn't work...
*/
/* figure out the cache line size */
@@ -187,7 +177,7 @@ leaveparms:
li r16,CACHE_LINE_SIZE
#endif
- lis r3,preload@h
+ lis r3,preload@h
ori r3,r3,preload@l
mr r4,r5 /* from-addr */
li r5,_preload_size/* this is never > 16k */
@@ -218,19 +208,19 @@ return_here:
/* OK, now everything should be in place.
* we are ready to start...
*/
- /* R6: start of command line */
- /* R7: end of command line +1 */
-
+
/* setup initial stack for rtems early boot */
- lis r1, INITIAL_STACK
+ li r1,INITIAL_STACK
/* disable the MMU and fire up rtems */
mfmsr r0
- ori r0,r0,MSR_IR|MSR_DR|MSR_IP
+ ori r0,r0,MSR_IR|MSR_DR|MSR_IP|MSR_ME
xori r0,r0,MSR_IR|MSR_DR
mtsrr1 r0
lis r0,__rtems_entry_point@h
ori r0,r0,__rtems_entry_point@l
mtsrr0 r0
+ /* R6: start of command line */
+ /* R7: end of command line +1 */
rfi
/* domove(to, from, nbytes):
@@ -238,7 +228,7 @@ return_here:
* move a R5 bytes from R4 to R3 and flush
* the caches for the destination memory
* region. R16 provides the cache line size.
- * DESTROYS: R0, R17, R18, CTR, CR
+ * DESTROYS: R0, R17, R18, CTR, CR
*/
domove:
addi r0,r5,3 /* convert to word count */
@@ -258,18 +248,18 @@ domove:
beq 3f /* nothing to do */
#endif
#if defined(CACHE_LINE_SIZE) && CACHE_LINE_SIZE > 0
- add r17,r3,r5 /* target end pointer */
+ add r17,r3,r5 /* target end pointer */
subi r0,r16,1
- add r17,r17,r0
+ add r17,r17,r0
andc r17,r17,r0 /* cache aligned target end pointer */
- mr r18,r3
+ mr r18,r3
2: cmpw r18,r17
dcbst 0,r18 /* write out data cache line */
icbi 0,r18 /* invalidate corresponding i-cache line */
- add r18,r18,r16
- blt 2b
- sync /* make sure data is written back */
- isync /* invalidate possibly preloaded instructions */
+ add r18,r18,r16
+ blt 2b
+ sync /* make sure data is written back */
+ isync /* invalidate possibly preloaded instructions */
#endif
3:
blr
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/startup/bspclean.c b/c/src/lib/libbsp/powerpc/mvme5500/startup/bspclean.c
index 04e3c0ea0f..1100ddfcd1 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/startup/bspclean.c
+++ b/c/src/lib/libbsp/powerpc/mvme5500/startup/bspclean.c
@@ -7,10 +7,12 @@
void bsp_cleanup(void)
{
#if AUTO_BOOT
+ /* Till Straumann <strauman@slac.stanford.edu> for SVGM */
void rtemsReboot();
rtemsReboot();
#else
+ /* Kate Feng <feng1@bnl.gov> for the MVME5500 */
printk("\nPrinting a stack trace for your convenience :-)\n");
CPU_print_stack();
printk("RTEMS terminated; Boot manually or turn on AUTO_BOOT.\n");
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/startup/bspstart.c b/c/src/lib/libbsp/powerpc/mvme5500/startup/bspstart.c
index c7b8b68b3b..c9d8375359 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/startup/bspstart.c
+++ b/c/src/lib/libbsp/powerpc/mvme5500/startup/bspstart.c
@@ -14,14 +14,13 @@
* Modified to support the MCP750.
* Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
*
- * Modified to support the Synergy VGM & Motorola PowerPC boards.
- * Many thanks to Till Straumann for providing assistance to port the
- * BSP_pgtbl_xxx().
- * (C) by Till Straumann, <strauman@slac.stanford.edu>, 2002, 2004
- *
- * Modified to support the MVME5500 board
- * (C) by S. Kate Feng <feng1@bnl.gov>, 2003, 2004
+ * Modified to support the Synergy VGM & Motorola PowerPC boards
+ * (C) by Till Straumann, <strauman@slac.stanford.edu>, 2002, 2004, 2005
*
+ * Modified to support the MVME5500 board.
+ * Also, the settings of L1, L2, and L3 caches is not necessary here.
+ * (C) by Brookhaven National Lab., S. Kate Feng <feng1@bnl.gov>, 2003, 2004, 2005
+ *
* $Id$
*/
@@ -62,19 +61,11 @@
/* there is no public Workspace_Free() variant :-( */
#include <rtems/score/wkspace.h>
-uint32_t
-_bsp_sbrk_init(uint32_t heap_start, uint32_t *heap_size_p);
-
-/* provide access to the command line parameters */
-char *BSP_commandline_string = 0;
-
BSP_output_char_function_type BSP_output_char = BSP_output_char_via_serial;
extern void _return_to_ppcbug();
extern unsigned long __rtems_end[];
-extern void L1_caches_enables();
extern unsigned get_L1CR(), get_L2CR(), get_L3CR();
-extern unsigned set_L2CR(unsigned);
extern void bsp_cleanup(void);
extern Triv121PgTbl BSP_pgtbl_setup();
extern void BSP_pgtbl_activate();
@@ -112,6 +103,11 @@ unsigned int BSP_mem_size;
/*
* PCI Bus Frequency
*/
+/*
+ * Start of the heap
+ */
+unsigned int BSP_heap_start;
+
unsigned int BSP_bus_frequency;
/*
* processor clock frequency
@@ -123,23 +119,17 @@ unsigned int BSP_processor_frequency;
unsigned int BSP_time_base_divisor;
unsigned char ConfVPD_buff[200];
+#define CMDLINE_BUF_SIZE 2048
+
+static char cmdline_buf[CMDLINE_BUF_SIZE];
+char *BSP_commandline_string = cmdline_buf;
+
/*
* system init stack and soft ir stack size
*/
#define INIT_STACK_SIZE 0x1000
#define INTR_STACK_SIZE CONFIGURE_INTERRUPT_STACK_MEMORY
-/* calculate the heap start */
-static unsigned long
-heapStart(void)
-{
-unsigned long rval;
- rval = ((uint32_t) __rtems_end) +INIT_STACK_SIZE + INTR_STACK_SIZE;
- if (rval & (CPU_ALIGNMENT-1))
- rval = (rval + CPU_ALIGNMENT) & ~(CPU_ALIGNMENT-1);
- return rval;
-}
-
void BSP_panic(char *s)
{
printk("%s PANIC %s\n",_RTEMS_version, s);
@@ -173,40 +163,7 @@ extern void bsp_postdriver_hook(void); /* see c/src/lib/libbsp/shared/bsppost.c
extern void bsp_libc_init( void *, uint32_t, int );
-/*
- * Function: bsp_pretasking_hook
- * Created: 95/03/10
- *
- * Description:
- * BSP pretasking hook. Called just before drivers are initialized.
- * Used to setup libc and install any BSP extensions.
- *
- * NOTES:
- * Must not use libc (to do io) from here, since drivers are
- * not yet initialized.
- *
- */
-
-void bsp_pretasking_hook(void)
-{
- uint32_t heap_start=heapStart();
- uint32_t heap_size,heap_sbrk_spared;
- extern uint32_t _bsp_sbrk_init(uint32_t, uint32_t*);
-
- heap_size = (BSP_mem_size - heap_start) - BSP_Configuration.work_space_size;
-
- heap_sbrk_spared=_bsp_sbrk_init(heap_start, &heap_size);
-
-#ifdef SHOW_MORE_INIT_SETTINGS
- printk(" HEAP start %x size %x (%x bytes spared for sbrk)\n", heap_start, heap_size, heap_sbrk_spared);
-#endif
-
- bsp_libc_init((void *) 0, heap_size, heap_sbrk_spared);
-
-#ifdef RTEMS_DEBUG
- rtems_debug_enable( RTEMS_DEBUG_ALL_MASK );
-#endif
-}
+extern void bsp_pretasking_hook(void);
void zero_bss()
{
@@ -257,65 +214,12 @@ void
save_boot_params(void *r3, void *r4, void* r5, char *cmdline_start, char *cmdline_end)
{
int i=cmdline_end-cmdline_start;
-CmdLine future_heap=(CmdLine)heapStart();
-
- /* get the string out of the stack area into the future heap region;
- * assume there's enough memory...
- */
- memmove(future_heap->buf,cmdline_start,i);
- /* make sure there's an end of string marker */
- future_heap->buf[i++]=0;
- future_heap->size=i;
-}
-
-
-/* Configure and enable the L3CR */
-void config_enable_L3CR(unsigned l3cr)
-{
- unsigned x;
-
- /* By The Book (numbered steps from section 3.7.3.1 of MPC7450UM) */
- /*
- * 1: Set all L3CR bits for final config except L3E, L3I, L3PE, and
- * L3CLKEN. (also mask off reserved bits in case they were included
- * in L3CR_CONFIG)
- */
- l3cr &= ~(L3CR_L3E|L3CR_L3I|L3CR_LOCK_745x|L3CR_L3PE|L3CR_L3CLKEN|L3CR_RESERVED);
- mtspr(L3CR, l3cr);
-
- /* 2: Set L3CR[5] (otherwise reserved bit) to 1 */
- l3cr |= 0x04000000;
- mtspr(L3CR, l3cr);
-
- /* 3: Set L3CLKEN to 1*/
- l3cr |= L3CR_L3CLKEN;
- mtspr(L3CR, l3cr);
-
- /* 4/5: Perform a global cache invalidate (ref section 3.7.3.6) */
- __asm __volatile("dssall;sync");
- /* L3 cache is already disabled, no need to clear L3E */
- mtspr(L3CR, l3cr|L3CR_L3I);
-
- do {
- x = mfspr(L3CR);
- } while (x & L3CR_L3I);
-
- /* 6: Clear L3CLKEN to 0 */
- l3cr &= ~L3CR_L3CLKEN;
- mtspr(L3CR, l3cr);
-
- /* 7: Perform a 'sync' and wait at least 100 CPU cycles */
- __asm __volatile("sync");
- rtems_bsp_delay_in_bus_cycles(100);
-
- /* 8: Set L3E and L3CLKEN */
- l3cr |= (L3CR_L3E|L3CR_L3CLKEN);
- mtspr(L3CR, l3cr);
-
- /* 9: Perform a 'sync' and wait at least 100 CPU cycles */
- __asm __volatile("sync");
-
- rtems_bsp_delay_in_bus_cycles(100);
+ if ( i >= CMDLINE_BUF_SIZE )
+ i = CMDLINE_BUF_SIZE-1;
+ else if ( i < 0 )
+ i = 0;
+ memmove(cmdline_buf, cmdline_start, i);
+ cmdline_buf[i]=0;
}
/*
@@ -346,6 +250,24 @@ void bsp_start( void )
ppc_cpu_id_t myCpu;
ppc_cpu_revision_t myCpuRevision;
Triv121PgTbl pt=0;
+
+ /* Till Straumann: 4/2005
+ * Need to map the system registers early, so we can printk...
+ * (otherwise we silently die)
+ */
+ /*
+ * Kate Feng : PCI 0 domain memory space, want to leave room for the VME window
+ */
+ setdbat(2, PCI0_MEM_BASE, PCI0_MEM_BASE, 0x10000000, IO_PAGE);
+
+ /* Till Straumann: 2004
+ * map the PCI 0, 1 Domain I/O space, GT64260B registers
+ * and the reserved area so that the size is the power of 2.
+ *
+ */
+ setdbat(3,PCI0_IO_BASE, PCI0_IO_BASE, 0x2000000, IO_PAGE);
+
+
/*
* Get CPU identification dynamically. Note that the get_ppc_cpu_type() function
* store the result in global variables so that it can be used latter...
@@ -353,15 +275,6 @@ void bsp_start( void )
myCpu = get_ppc_cpu_type();
myCpuRevision = get_ppc_cpu_revision();
- /*
- * enables L1 Cache. Note that the L1_caches_enables() codes checks for
- * relevant CPU type so that the reason why there is no use of myCpu...
- *
- * MOTLoad default is good. Otherwise, one would have to disable L2, L3
- * first before settting L1. Then L1->L2->L3.
- *
- L1_caches_enables();*/
-
#ifdef SHOW_LCR1_REGISTER
l1cr = get_L1CR();
printk("Initial L1CR value = %x\n", l1cr);
@@ -390,8 +303,8 @@ void bsp_start( void )
* This could be done latter (e.g in IRQ_INIT) but it helps to understand
* some settings below...
*/
- intrStack = ((uint32_t) __rtems_end) +
- INIT_STACK_SIZE + INTR_STACK_SIZE - PPC_MINIMUM_STACK_FRAME_SIZE;
+ BSP_heap_start = ((uint32_t) __rtems_end) + INIT_STACK_SIZE + INTR_STACK_SIZE;
+ intrStack = BSP_heap_start - PPC_MINIMUM_STACK_FRAME_SIZE;
/* make sure it's properly aligned */
intrStack &= ~(CPU_STACK_ALIGNMENT-1);
@@ -414,16 +327,6 @@ void bsp_start( void )
* access
* More PCI1 memory mapping to be done after BSP_pgtbl_activate.
*/
- /*
- * PCI 0 domain memory space, want to leave room for the VME window
- */
- setdbat(2, PCI0_MEM_BASE, PCI0_MEM_BASE, 0x10000000, IO_PAGE);
-
- /* map the PCI 0, 1 Domain I/O space, GT64260B registers
- * and the reserved area so that the size is the power of 2.
- */
- setdbat(3,PCI0_IO_BASE, PCI0_IO_BASE, 0x2000000, IO_PAGE);
-
printk("-----------------------------------------\n");
printk("Welcome to %s on MVME5500-0163\n", _RTEMS_version );
printk("-----------------------------------------\n");
@@ -485,7 +388,7 @@ void bsp_start( void )
/* P94 : 7455 TB/DECR is clocked by the system bus clock frequency */
Cpu_table.clicks_per_usec = BSP_bus_frequency/(BSP_time_base_divisor * 1000);
Cpu_table.exceptions_in_RAM = TRUE;
- _CPU_Table = Cpu_table;/* <skf> for rtems_bsp_delay() */
+ _CPU_Table = Cpu_table;/* S. Kate Feng <feng1@bnl.gov>, for rtems_bsp_delay() */
printk("BSP_Configuration.work_space_size = %x\n", BSP_Configuration.work_space_size);
work_space_start =
@@ -503,50 +406,10 @@ void bsp_start( void )
*/
BSP_rtems_irq_mng_init(0);
- /*
- * Enable L2 Cache. Note that the set_L2CR(L2CR) codes checks for
- * relevant CPU type (mpc750)...
- *
- * It also takes care of flushing the cache under certain conditions:
- * current going to (E==enable, I==invalidate)
- * E E | I -> __NOT_FLUSHED_, invalidated, stays E
- * E I -> flush & disable, invalidate
- * E E -> nothing, stays E
- * 0 E | I -> not flushed, invalidated, enabled
- * 0 | I -> not flushed, invalidated, stays off
- * 0 E -> not flushed, _NO_INVALIDATE, enabled
- *
- * The first and the last combinations are potentially dangerous!
- *
- * NOTE: we assume the essential cache parameters (speed, size etc.)
- * have been set correctly by the firmware!
- *
- */
#ifdef SHOW_LCR2_REGISTER
l2cr = get_L2CR();
printk("Initial L2CR value = %x\n", l2cr);
#endif
-#if 0
- /* Again, MOTload setup seems to be fine. Otherwise, one would
- * have to disable the L3 cahce, then R2 ->R3
- */
- if ( -1 != (int)l2cr ) {
- /* -1 would mean that this machine doesn't support L2 */
-
- l2cr &= ~( L2CR_LOCK_745x); /* clear 'data only' and 'instruction only' */
- l2cr |= L2CR_L3OH0; /* L3 output hold 0 should be set */
- if ( ! (l2cr & L2CR_L2E) ) {
- /* we are going to enable the L2 - hence we
- * MUST invalidate it first; however, if
- * it was enabled already, we MUST NOT
- * invalidate it!!
- */
- l2cr |= L2CR_L2E | L2CR_L2I;
- l2cr=set_L2CR(l2cr);
- }
- l2cr=set_L2CR(l2cr);
- }
-#endif
#ifdef SHOW_LCR3_REGISTER
/* L3CR needs DEC int. handler installed for bsp_delay()*/
@@ -554,22 +417,6 @@ void bsp_start( void )
printk("Initial L3CR value = %x\n", l3cr);
#endif
-#if 0
- /* Again, use the MOTLoad default for L3CR again */
- if ( -1 != (int)l3cr ) {
- /* -1 would mean that this machine doesn't support L3 */
- /* BSD : %2 , SDRAM late wirte
- l3cr |= L3SIZ_2M|L3CLK_20|L3RT_PIPELINE_LATE; */
- /* MOTLOad :0xDF826000-> %5, 4 clocks sample point,3 p-clocks SP */
- l3cr |= L3CR_L3PE| L3SIZ_2M|L3CLK_50|L3CKSP_4|L3PSP_3;
-
- /* TOCHECK MOTload had L2 cache enabled, try to set nothing first */
- if ( !(l3cr & L3CR_L3E)) {
- l3cr |= L3CR_L3E | L3CR_L3I;
- config_enable_L3CR(l3cr);
- }
- }
-#endif
/* Activate the page table mappings only after
* initializing interrupts because the irq_mng_init()
@@ -604,19 +451,6 @@ void bsp_start( void )
*/
_BSP_clear_hostbridge_errors(0, 1 /*quiet*/);
- /*
- * Initialize VME bridge - needs working PCI
- * and IRQ subsystems...
- */
-#ifdef SHOW_MORE_INIT_SETTINGS
- printk("Going to initialize VME bridge\n");
-#endif
- /* VME initialization is in a separate file so apps which don't use
- * VME or want a different configuration may link against a customized
- * routine.
- */
- BSP_vme_config();
-
/* Read Configuration Vital Product Data (VPD) */
if ( I2Cread_eeprom(0xa8, 4,2, &ConfVPD_buff[0], 150))
printk("I2Cread_eeprom() error \n");
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/startup/pgtbl_activate.c b/c/src/lib/libbsp/powerpc/mvme5500/startup/pgtbl_activate.c
index 3d9d947a3b..8b14f9923e 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/startup/pgtbl_activate.c
+++ b/c/src/lib/libbsp/powerpc/mvme5500/startup/pgtbl_activate.c
@@ -9,52 +9,8 @@
* default activation procedure.
*/
-/*
- * Authorship
- * ----------
- * This software was created by
- * Till Straumann <strauman@slac.stanford.edu>, 4/2002,
- * Stanford Linear Accelerator Center, Stanford University.
- *
- * Acknowledgement of sponsorship
- * ------------------------------
- * This software was produced by
- * the Stanford Linear Accelerator Center, Stanford University,
- * under Contract DE-AC03-76SFO0515 with the Department of Energy.
- *
- * Government disclaimer of liability
- * ----------------------------------
- * Neither the United States nor the United States Department of Energy,
- * nor any of their employees, makes any warranty, express or implied, or
- * assumes any legal liability or responsibility for the accuracy,
- * completeness, or usefulness of any data, apparatus, product, or process
- * disclosed, or represents that its use would not infringe privately owned
- * rights.
- *
- * Stanford disclaimer of liability
- * --------------------------------
- * Stanford University makes no representations or warranties, express or
- * implied, nor assumes any liability for the use of this software.
- *
- * Stanford disclaimer of copyright
- * --------------------------------
- * Stanford University, owner of the copyright, hereby disclaims its
- * copyright and all other rights in this software. Hence, anyone may
- * freely use it for any purpose without restriction.
- *
- * Maintenance of notices
- * ----------------------
- * In the interest of clarity regarding the origin and status of this
- * SLAC software, this and all the preceding Stanford University notices
- * are to remain affixed to any copy or derivative of this software made
- * or distributed by the recipient and are to be affixed to any copy of
- * software made or distributed by the recipient that contains a copy or
- * derivative of this software.
- *
- * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
- */
-
-/* Kate Feng <feng1@bnl.gov> ported it to MVME5500, 4/2004
+/* Author: Till Straumann, <strauman@slac.stanford.edu>, 4/2002
+ * Kate Feng <feng1@bnl.gov> ported it to MVME5500, 4/2004
*/
void
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/startup/reboot.c b/c/src/lib/libbsp/powerpc/mvme5500/startup/reboot.c
index c885a5fcac..d6843a8e4e 100644
--- a/c/src/lib/libbsp/powerpc/mvme5500/startup/reboot.c
+++ b/c/src/lib/libbsp/powerpc/mvme5500/startup/reboot.c
@@ -7,10 +7,10 @@
void rtemsReboot()
{
- printk("\nPrinting a stack trace for your convenience :-)\n");
+ printk("Printing a stack trace for your convenience :-)\n");
CPU_print_stack();
printk("RTEMS terminated; Rebooting ...\n");
- /* Mvme5500 board reset <skf> */
+ /* Mvme5500 board reset : 2004 S. Kate Feng <feng1@bnl.gov> */
out_8((volatile unsigned char*) (GT64260_DEV1_BASE +2), 0x80);
}