changeset 112:02ea4320376c ecos-sw-2000-07-21

Merge from eCos master repository on 2000-07-21-21:01:39-BST
author jlarmour
date Fri, 21 Jul 2000 21:34:11 +0000
parents 211b8a635ce9
children 70a153d1814b
files host/tools/configtool/ChangeLog host/tools/configtool/standalone/win32/Configtool.rc packages/NEWS packages/cygmon/current/ChangeLog packages/cygmon/current/cdl/cygmon.cdl packages/cygmon/current/misc/arm/arm-mon.c packages/cygmon/current/misc/arm/board.h packages/cygmon/current/misc/arm/cpu_info.h packages/cygmon/current/misc/board.h packages/cygmon/current/misc/bplist-dynamic.c packages/cygmon/current/misc/breakpoints.c packages/cygmon/current/misc/bsp/bsp.h packages/cygmon/current/misc/bsp/common/breakpoint.c packages/cygmon/current/misc/bsp/common/gdb-cpu.c packages/cygmon/current/misc/bsp/common/gdb-cpu.h packages/cygmon/current/misc/bsp/common/singlestep.c packages/cygmon/current/misc/bsp/common/syscall.c packages/cygmon/current/misc/bsp/common/syscall.h packages/cygmon/current/misc/bsp/cpu.h packages/cygmon/current/misc/cpu-mon.c packages/cygmon/current/misc/cpu_info.h packages/cygmon/current/misc/ecos_bsp.c packages/cygmon/current/misc/ecos_dummy.c packages/cygmon/current/misc/ledit.c packages/cygmon/current/misc/monitor.c packages/cygmon/current/misc/monitor.h packages/cygmon/current/misc/monitor_cmd.c packages/cygmon/current/misc/tservice.h packages/cygmon/current/misc/utils.c packages/devs/eth/arm/ebsa285/current/ChangeLog packages/devs/eth/arm/ebsa285/current/src/if_ebsa285.c packages/devs/serial/v85x/v850/current/ChangeLog packages/devs/serial/v85x/v850/current/src/v85x_v850_serial.h packages/ecos.db packages/hal/arm/arch/current/ChangeLog packages/hal/arm/arch/current/include/arm_stub.h packages/hal/arm/arch/current/src/vectors.S packages/hal/arm/ebsa285/current/ChangeLog packages/hal/arm/ebsa285/current/src/hal_diag.c packages/hal/arm/pid/current/ChangeLog packages/hal/arm/pid/current/src/pid_misc.c packages/hal/common/current/ChangeLog packages/hal/common/current/cdl/hal.cdl packages/hal/common/current/include/generic-stub.h packages/hal/common/current/include/hal_if.h packages/hal/common/current/include/hal_stub.h packages/hal/common/current/src/bplist-dynamic.c packages/hal/common/current/src/generic-stub.c packages/hal/common/current/src/hal_if.c packages/hal/common/current/src/hal_misc.c packages/hal/common/current/src/hal_stub.c packages/hal/mips/arch/current/ChangeLog packages/hal/mips/arch/current/include/arch.inc packages/hal/mips/arch/current/include/hal_arch.h packages/hal/mips/arch/current/include/hal_intr.h packages/hal/mips/arch/current/include/mips-regs.h packages/hal/mips/arch/current/include/mips-stub.h packages/hal/mips/arch/current/src/context.S packages/hal/mips/arch/current/src/mips-stub.c packages/hal/mips/arch/current/src/vectors.S packages/hal/powerpc/fads/current/ChangeLog packages/hal/powerpc/fads/current/src/hal_aux.c packages/hal/sh/arch/current/ChangeLog packages/hal/sh/arch/current/include/hal_intr.h packages/hal/sh/arch/current/src/hal_misc.c packages/hal/sh/arch/current/src/sh_stub.c packages/hal/sh/arch/current/src/vectors.S packages/hal/v85x/arch/current/ChangeLog packages/hal/v85x/arch/current/src/vectors.S packages/infra/current/ChangeLog packages/infra/current/src/buffer.cxx packages/kernel/current/ChangeLog packages/kernel/current/tests/kflag1.c packages/net/drivers/eth/common/current/ChangeLog packages/net/drivers/eth/common/current/include/eth_drv.h packages/net/tcpip/current/ChangeLog packages/net/tcpip/current/cdl/net.cdl packages/net/tcpip/current/include/machine/param.h packages/net/tcpip/current/include/net/if_bridge.h packages/net/tcpip/current/include/sys/param.h packages/net/tcpip/current/include/sys/sockio.h packages/net/tcpip/current/src/ecos/support.c packages/net/tcpip/current/src/ecos/timeout.c packages/net/tcpip/current/src/lib/bootp_support.c packages/net/tcpip/current/src/lib/dhcp_prot.c packages/net/tcpip/current/src/lib/select.c packages/net/tcpip/current/src/lib/tftp_client.c packages/net/tcpip/current/src/lib/tftp_server.c packages/net/tcpip/current/src/sys/net/if_bridge.c packages/net/tcpip/current/tests/bridge.c packages/net/tcpip/current/tests/dhcp_test.c packages/net/tcpip/current/tests/ftp_test.c packages/net/tcpip/current/tests/multi_lo_select.c packages/net/tcpip/current/tests/ping_test.c
diffstat 94 files changed, 5206 insertions(+), 273 deletions(-) [+]
line wrap: on
line diff
--- a/host/tools/configtool/ChangeLog
+++ b/host/tools/configtool/ChangeLog
@@ -1,3 +1,9 @@
+2000-07-18  John Dallaway  <jld@redhat.com>
+
+	* standalone/win32/Configtool.rc:
+
+	Update IDS_ECOS_SOURCEWARE_URL.
+
 2000-07-03  John Dallaway  <jld@redhat.com>
 
 	* common/win32/CTCommonDoc.cpp:
--- a/host/tools/configtool/standalone/win32/Configtool.rc
+++ b/host/tools/configtool/standalone/win32/Configtool.rc
@@ -199,7 +199,7 @@ BEGIN
     LTEXT           "Copyright © 1998-2000 Red Hat, Inc.",IDC_STATIC,40,36,
                     170,8
     LTEXT           "The eCos engineering team is:",IDC_STATIC,7,50,109,8
-    CTEXT           "\r\nPaul Beskeen\r\nJohn Dallaway\r\nRobert Erskine\r\nNick Garnett\r\nJonathan Larmour\r\nAlex Schuilenburg\r\nJesper Skov\r\nGary Thomas\r\nHugo Tyson\r\nBart Veer",
+    CTEXT           "\r\nPaul Beskeen\r\nJohn Dallaway\r\nRobert Erskine\r\nNick Garnett\r\nEugene Kulesha\r\nJonathan Larmour\r\nAlex Schuilenburg\r\nJesper Skov\r\nJulian Smart\r\nGary Thomas\r\nHugo Tyson\r\nBart Veer",
                     IDC_STATIC_ABOUT,7,69,203,114,SS_SUNKEN,WS_EX_CLIENTEDGE
 END
 
@@ -456,7 +456,7 @@ BEGIN
     IDC_PANECOMBO           "Selects a window for which the font is to be changed."
     IDC_FONT                "Changes the font of the chosen window."
     IDS_ECOS_HOME_URL       "http://www.redhat.com/products/ecos"
-    IDS_ECOS_SOURCEWARE_URL "http://sourceware.cygnus.com/ecos"
+    IDS_ECOS_SOURCEWARE_URL "http://sources.redhat.com/ecos"
     IDS_RED_HAT_HOME_URL    "http://www.redhat.com"
     IDS_UITRON_HOME_URL     "http://www.itron.gr.jp/"
     IDS_ECOS_PR_URL         "http://www.cygnus.com/ecos/ecos-pr.html"
--- a/packages/NEWS
+++ b/packages/NEWS
@@ -1,8 +1,10 @@
+* DHCP support has been added to the TCP/IP support, in addition to the
+  existing BOOTP support
 * CDL now supports type bool and booldata for interfaces
 * CDL now exports extra macros in header files, to indicate package version
   numbers
 * A port of the University of California at Davis (UCD) SNMP stack has been
-  added, including SNMP clients
+  added
 * Hitachi SH7709A variant support added
 * NEC V85x architecture support added
 * NEC Cosmo CEB-V850/SA1 evaluation board platform HAL added
--- a/packages/cygmon/current/ChangeLog
+++ b/packages/cygmon/current/ChangeLog
@@ -1,3 +1,54 @@
+2000-07-14  Drew Moseley  <dmoseley@redhat.com>
+
+	* misc/bsp/mips/gdb-cpu.c: New files. Mips based Cygmon now running on top of eCos HAL.
+	* misc/bsp/mips/gdb-cpu.h: Ditto.
+	* misc/bsp/mips/gdb.h: Ditto.
+	* misc/bsp/mips/insn.h: Ditto.
+	* misc/bsp/mips/singlestep.c: Ditto.
+	* misc/mips/board.h: Ditto.
+	* misc/mips/cpu.h: Ditto.
+	* misc/mips/cpu_info.h: Ditto.
+	* misc/mips/mips-mon.c: Ditto.
+
+	* misc/bsp/common/syscall.c: Added SYS_meminfo call to find out
+	how much RAM we have.
+	* misc/bsp/common/syscall.h: Ditto.
+
+	* misc/bsp/common/breakpoint.c: Added __ECOS__ support.
+
+	* misc/monitor_cmd.c: Cleanup.  Added some more error handling.
+	* misc/utils.c: Ditto.
+
+	* misc/monitor.c: Added basic syscall handling to support libgloss.
+	Added support for using more features of the HAL (ie breakpoints
+	and exceptions).
+	* misc/monitor.h: Ditto.
+	* misc/tservice.h: Ditto.
+	* misc/bsp/bsp.h: Ditto.
+	* misc/arm/cpu_info.h: Ditto.
+
+	* misc/ledit.c: Cleanup.
+
+	* misc/ecos_dummy.c: Support for reset through the HAL.
+
+	* misc/ecos_bsp.c: Filled in uart_control function for setting baud rate
+	through the HAL.  Also added VIRTUAL_VECTOR_SUPPORT and support of the
+	low-level HAL-based serial driver.  Also added set_memsize() support.
+
+	* misc/bplist-dynamic.c: Added option for using breakpoints in the HAL.
+	Also, various cleanups of build warnings, etc.	
+	* misc/breakpoints.c: Ditto.
+
+	* cdl/cygmon.cdl: Allow cygmon to be built for either Arm or Mips.
+	
+	* misc/board.h: Move architecture-dependent things out.
+	* misc/cpu-mon.c: Ditto.
+	* misc/cpu_info.h: Ditto.
+	* misc/bsp/cpu.h: Ditto.
+	* misc/bsp/common/gdb-cpu.c: Ditto.
+	* misc/bsp/common/gdb-cpu.h: Ditto.
+	* misc/bsp/common/singlestep.c: Ditto.
+
 2000-01-28  Jesper Skov  <jskov@redhat.com>
 
 	* misc/Notes_CygMon_PID: Added.
--- a/packages/cygmon/current/cdl/cygmon.cdl
+++ b/packages/cygmon/current/cdl/cygmon.cdl
@@ -89,6 +89,7 @@ cdl_package CYGPKG_CYGMON {
         requires ! CYGSEM_LIBC_PER_THREAD_ERRNO
         requires ! CYGSEM_LIBC_TIME_TIME_WORKING
         requires ! CYGSEM_LIBC_TIME_SETTIME_WORKING
+        requires CYGPKG_HAL_ARM
 
         no_define
         description "This option enables the building of the CygMon ELF image.
@@ -99,33 +100,33 @@ cdl_package CYGPKG_CYGMON {
         make -priority 320 {
             <PREFIX>/bin/cygmon.elf : <PACKAGE>/misc/ecos_bsp.c <PACKAGE>/misc/ecos_dummy.c <PACKAGE>/misc/cpu-mon.c <PACKAGE>/misc/monitor.c <PACKAGE>/misc/monitor_cmd.c <PACKAGE>/misc/ledit.c <PACKAGE>/misc/breakpoints.c <PACKAGE>/misc/bplist-dynamic.c <PACKAGE>/misc/utils.c <PACKAGE>/misc/generic_fmt32.c <PACKAGE>/misc/generic_mem.c <PACKAGE>/misc/bsp/common/bsp.c <PACKAGE>/misc/bsp/common/bsp_if.c <PACKAGE>/misc/bsp/common/shared-data.c <PACKAGE>/misc/bsp/common/sysinfo.c <PACKAGE>/misc/bsp/common/console-io.c <PACKAGE>/misc/bsp/common/debug-io.c <PACKAGE>/misc/bsp/common/sprintf.c <PACKAGE>/misc/bsp/common/syscall.c <PACKAGE>/misc/bsp/common/printf.c <PACKAGE>/misc/bsp/common/vprintf.c <PACKAGE>/misc/bsp/common/breakpoint.c <PACKAGE>/misc/bsp/common/singlestep.c <PACKAGE>/misc/bsp/common/generic-mem.c <PACKAGE>/misc/bsp/common/bsp_cache.c <PACKAGE>/misc/bsp/common/gdb-cpu.c <PACKAGE>/misc/bsp/common/hex-utils.c
             @sh -c "mkdir -p misc/bsp/common $(dir $@)"
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/ecos_bsp.o $(REPOSITORY)/$(PACKAGE)/misc/ecos_bsp.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/ecos_dummy.o $(REPOSITORY)/$(PACKAGE)/misc/ecos_dummy.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/cpu-mon.o $(REPOSITORY)/$(PACKAGE)/misc/cpu-mon.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/monitor.o $(REPOSITORY)/$(PACKAGE)/misc/monitor.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/monitor_cmd.o $(REPOSITORY)/$(PACKAGE)/misc/monitor_cmd.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/ledit.o $(REPOSITORY)/$(PACKAGE)/misc/ledit.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/breakpoints.o $(REPOSITORY)/$(PACKAGE)/misc/breakpoints.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/bplist-dynamic.o $(REPOSITORY)/$(PACKAGE)/misc/bplist-dynamic.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/utils.o $(REPOSITORY)/$(PACKAGE)/misc/utils.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/generic_fmt32.o $(REPOSITORY)/$(PACKAGE)/misc/generic_fmt32.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/generic_mem.o $(REPOSITORY)/$(PACKAGE)/misc/generic_mem.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/bsp/common/bsp.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/bsp.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/bsp/common/bsp_if.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/bsp_if.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/bsp/common/shared-data.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/shared-data.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/bsp/common/sysinfo.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/sysinfo.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/bsp/common/console-io.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/console-io.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/bsp/common/debug-io.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/debug-io.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/bsp/common/sprintf.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/sprintf.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/bsp/common/syscall.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/syscall.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/bsp/common/printf.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/printf.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/bsp/common/vprintf.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/vprintf.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/bsp/common/breakpoint.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/breakpoint.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/bsp/common/singlestep.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/singlestep.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/bsp/common/generic-mem.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/generic-mem.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/bsp/common/bsp_cache.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/bsp_cache.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/bsp/common/gdb-cpu.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/gdb-cpu.c
-            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -DCYG_HAL_ARM -o misc/bsp/common/hex-utils.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/hex-utils.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/ecos_bsp.o $(REPOSITORY)/$(PACKAGE)/misc/ecos_bsp.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/ecos_dummy.o $(REPOSITORY)/$(PACKAGE)/misc/ecos_dummy.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/cpu-mon.o $(REPOSITORY)/$(PACKAGE)/misc/cpu-mon.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/monitor.o $(REPOSITORY)/$(PACKAGE)/misc/monitor.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/monitor_cmd.o $(REPOSITORY)/$(PACKAGE)/misc/monitor_cmd.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/ledit.o $(REPOSITORY)/$(PACKAGE)/misc/ledit.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/breakpoints.o $(REPOSITORY)/$(PACKAGE)/misc/breakpoints.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bplist-dynamic.o $(REPOSITORY)/$(PACKAGE)/misc/bplist-dynamic.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/utils.o $(REPOSITORY)/$(PACKAGE)/misc/utils.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/generic_fmt32.o $(REPOSITORY)/$(PACKAGE)/misc/generic_fmt32.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/generic_mem.o $(REPOSITORY)/$(PACKAGE)/misc/generic_mem.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/bsp.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/bsp.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/bsp_if.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/bsp_if.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/shared-data.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/shared-data.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/sysinfo.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/sysinfo.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/console-io.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/console-io.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/debug-io.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/debug-io.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/sprintf.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/sprintf.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/syscall.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/syscall.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/printf.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/printf.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/vprintf.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/vprintf.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/breakpoint.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/breakpoint.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/singlestep.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/singlestep.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/generic-mem.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/generic-mem.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/bsp_cache.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/bsp_cache.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/gdb-cpu.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/gdb-cpu.c
+            $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/hex-utils.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/hex-utils.c
             $(CC) $(LDFLAGS) -L$(PREFIX)/lib -Ttarget.ld -o $@ $(patsubst $(REPOSITORY)/$(PACKAGE)/%.c,%.o,$^)
         }
     }
--- a/packages/cygmon/current/misc/arm/arm-mon.c
+++ b/packages/cygmon/current/misc/arm/arm-mon.c
@@ -256,6 +256,7 @@ arm_othernames (void)
 
 #include <pkgconf/hal.h>
 #include <cyg/hal/hal_arch.h>
+#include "bsp/common/bsp_if.h"
 
 int
 machine_syscall(HAL_SavedRegisters *regs)
--- a/packages/cygmon/current/misc/arm/board.h
+++ b/packages/cygmon/current/misc/arm/board.h
@@ -67,6 +67,7 @@
 #define __set_breakpoint        set_breakpoint
 #define __remove_breakpoint     clear_breakpoint
 #define __write_mem_safe        memcpy
+#define WRITE_MEM_IS_MEMCPY
 #define _breakinst              bsp_breakinsn
 
 #endif //  __CYGMON_ARM_BOARD_H__
--- a/packages/cygmon/current/misc/arm/cpu_info.h
+++ b/packages/cygmon/current/misc/arm/cpu_info.h
@@ -48,8 +48,12 @@
 
 #define IS_ARM 1
 
-typedef unsigned int uint32 ;
+#ifndef __CYGMON_TYPES
+#define __CYGMON_TYPES
+typedef unsigned int uint32;
 typedef int          int32;
+#endif // __CYGMON_TYPES
+
 
 /* Temporary as long a multiple protypes are copied in multiple files */
 /* This variation does NOT clone the prototypes */
@@ -57,8 +61,6 @@ typedef int          int32;
 #define MAX_NUM_BP 32
 #define MAX_HIST_ENTS 10
 
-typedef int regnames_t;
-
 /* big enuf to store a trap in the BP structure */
 
 #define BP_INST_T_DEFINED 1 
@@ -69,15 +71,14 @@ typedef struct mem_addr {
   unsigned long addr;
 } mem_addr_t ;
 
-typedef unsigned int target_register_t;
+#ifndef TARGET_REGISTER_T_DEFINED
+#define TARGET_REGISTER_T_DEFINED
+typedef unsigned long target_register_t;
+#endif
 
 #if defined(__ARMEB__)
-#define BIG_ENDIAN_TARGET
-#undef  LITTLE_ENDIAN_TARGET
 #define PRINT_INSN print_insn_big_arm
 #else
-#define LITTLE_ENDIAN_TARGET
-#undef  BIG_ENDIAN_TARGET
 #define PRINT_INSN print_insn_little_arm
 #endif
 
--- a/packages/cygmon/current/misc/board.h
+++ b/packages/cygmon/current/misc/board.h
@@ -48,25 +48,12 @@
 #include <pkgconf/hal.h>
 #include <pkgconf/cygmon.h>
 
-#define HAVE_FLOAT_REGS         0
-#define HAVE_DOUBLE_REGS        0
-#define HAVE_CACHE              0 // FIXME
-#define HAVE_USAGE              0 // FIXME
-#define USE_CYGMON_PROTOTYPES   1
-#define NOMAIN                  1
-#define CYGMON_SYSTEM_SERVICES  0 // Not used, fall back to BSP support
-#ifdef CYGDAT_CYGMON_USE_HELP
-#define USE_HELP                1
+#ifdef CYGPKG_HAL_ARM
+#include "arm/board.h"
 #endif
 
-// For breakpoint support
-#define NO_MALLOC               1
-#define MAX_BP_NUM              8
-#include "cpu_info.h"
-#define TRAP_SIZE               4
-#define __set_breakpoint        set_breakpoint
-#define __remove_breakpoint     clear_breakpoint
-#define __write_mem_safe        memcpy
-#define _breakinst              bsp_breakinsn
+#ifdef CYGPKG_HAL_MIPS
+#include "mips/board.h"
+#endif
 
 #endif //  __CYGMON_BOARD_H__
--- a/packages/cygmon/current/misc/bplist-dynamic.c
+++ b/packages/cygmon/current/misc/bplist-dynamic.c
@@ -42,8 +42,11 @@
 //
 //=========================================================================
 
+#include "board.h"
+
+#ifndef USE_ECOS_HAL_BREAKPOINTS
+
 #include <stdlib.h>
-#include "board.h"
 
 #ifndef NO_MALLOC
 #ifndef NO_MALLOC_H
@@ -54,6 +57,10 @@ char *malloc ();
 #endif
 #endif
 
+#ifdef __ECOS__
+#include <cyg/hal/plf_stub.h>
+#endif /* __ECOS__ */
+
 /*
  * A simple target breakpoint list using malloc.
  * To use this package, you must define TRAP_SIZE to be the size
@@ -76,7 +83,10 @@ static struct breakpoint_list *free_bp_l
 static int curr_bp_num = 0;
 #endif
 
+#ifndef BREAKINST_DEFINED
+#define BREAKINST_DEFINED
 extern unsigned char _breakinst[];
+#endif
 
 int
 __set_breakpoint (target_register_t addr)
@@ -139,7 +149,7 @@ int
   if (l->in_memory)
     {
       __write_mem_safe (&l->old_contents[0],
-			l->addr,
+			(void*)l->addr,
 			sizeof (l->old_contents));
     }
 
@@ -157,8 +167,10 @@ int
   return 0;
 }
 
+#include <cyg/hal/generic-stub.h>
+#include <cyg/hal/hal_stub.h>
 void
-__install_breakpoints ()
+__cygmon_install_breakpoints (void)
 {
   struct breakpoint_list *l = breakpoint_list;
 
@@ -168,9 +180,13 @@ void
 	{
 	  int len = sizeof (l->old_contents);
 
-	  if (__read_mem_safe (&l->old_contents[0], l->addr, len) == len)
+	  if (__read_mem_safe (&l->old_contents[0], (void*)l->addr, len) == len)
 	    {
-	      if (__write_mem_safe (&_breakinst[0], l->addr, len) == len)
+#ifdef WRITE_MEM_IS_MEMCPY
+	      if (__write_mem_safe (_breakinst, (void*)l->addr, len) == (void*)l->addr)
+#else
+	      if (__write_mem_safe (_breakinst, (void*)l->addr, len) == len)
+#endif
 		{
 		  l->in_memory = 1;
 		}
@@ -182,7 +198,7 @@ void
 }
 
 void
-__clear_breakpoints ()
+__cygmon_clear_breakpoints (void)
 {
   struct breakpoint_list *l = breakpoint_list;
 
@@ -192,7 +208,11 @@ void
 	{
 	  int len = sizeof (l->old_contents);
 
-	  if (__write_mem_safe (&l->old_contents[0], l->addr, len) == len)
+#ifdef WRITE_MEM_IS_MEMCPY
+      if (__write_mem_safe (_breakinst, (void*)l->addr, len) == (void*)l->addr)
+#else
+	  if (__write_mem_safe (&l->old_contents[0], (void*)l->addr, len) == len)
+#endif
 	    {
 	      l->in_memory = 0;
 	    }
@@ -202,3 +222,4 @@ void
   flush_i_cache ();
 }
 
+#endif // USE_ECOS_HAL_BREAKPOINTS
--- a/packages/cygmon/current/misc/breakpoints.c
+++ b/packages/cygmon/current/misc/breakpoints.c
@@ -42,6 +42,10 @@
 //
 //=========================================================================
 
+#include "board.h"
+
+#ifndef USE_ECOS_HAL_BREAKPOINTS
+
 #include <stdlib.h>
 #ifdef HAVE_BSP
 #include <bsp/bsp.h>
@@ -204,3 +208,4 @@ clear_mon_breakpoint (mem_addr_t locatio
   return error;
 }	
 
+#endif /* USE_ECOS_HAL_BREAKPOINTS */
--- a/packages/cygmon/current/misc/bsp/bsp.h
+++ b/packages/cygmon/current/misc/bsp/bsp.h
@@ -53,7 +53,10 @@
 /*
  * Exception and interrupt handler type.
  */
+#ifndef _BSP_HANDLER_T_DEFINED
+#define _BSP_HANDLER_T_DEFINED
 typedef int (*bsp_handler_t)(int __irq_nr, void *__regs);
+#endif // _BSP_HANDLER_T_DEFINED
 
 /*
  *  Vector descriptor. This is needed for chaining vectors. The interfaces use
@@ -148,18 +151,24 @@ extern bsp_handler_t bsp_install_kill_ha
  * Architecure specific routine to prepare CPU to execute
  * a single machine instruction.
  */
+#ifndef USE_ECOS_HAL_SINGLESTEP
 extern void bsp_singlestep_setup(void *__saved_regs);
+#endif /* USE_ECOS_HAL_SINGLESTEP */
 
 /*
  * Architecure specific routine to cleanup after a single-step
  * completes.
  */
+#ifndef USE_ECOS_HAL_SINGLESTEP
 extern void bsp_singlestep_cleanup(void *__saved_regs);
+#endif /* USE_ECOS_HAL_SINGLESTEP */
 
 /*
  * Architecture specific routine to skip past the current machine instruction.
  */
+#ifndef USE_ECOS_HAL_SINGLESTEP
 extern void bsp_skip_instruction(void *__saved_regs);
+#endif /* USE_ECOS_HAL_SINGLESTEP */
 
 /*
  * Return byte offset within the saved register area of the
@@ -175,12 +184,16 @@ extern int bsp_regsize(int __regno);
 /*
  * Setup the saved registered to establish the given Program Counter.
  */
+#ifndef bsp_set_pc
 extern void bsp_set_pc(unsigned long __pc, void *__saved_regs);
+#endif
 
 /*
  * Get the current Program Counter from the saved registers.
  */
+#ifndef bsp_get_pc
 unsigned long bsp_get_pc(void *__saved_regs);
+#endif
 
 extern int bsp_memory_read(void *__addr,    /* start addr of memory to read */
 			   int  __asid,     /* address space id */
@@ -205,7 +218,9 @@ extern void bsp_get_register(int __regno
  * Architecture specific conversion of raw exception info into
  * a signal value.
  */
+#ifndef bsp_get_signal
 extern int  bsp_get_signal(int __exc_nr, void *__saved_regs);
+#endif
 
 /* light-weight bsp printf to console port */
 extern void bsp_printf(const char *__fmt, ...);
--- a/packages/cygmon/current/misc/bsp/common/breakpoint.c
+++ b/packages/cygmon/current/misc/bsp/common/breakpoint.c
@@ -50,6 +50,10 @@
 #define DEBUG_BREAKPOINT 0
 #endif
 
+#ifdef __ECOS__
+#include <cyg/hal/hal_arch.h>
+#endif /* __ECOS__ */
+
 /*
  *  Trigger a breakpoint exception.
  */
@@ -59,14 +63,24 @@ bsp_breakpoint(void)
 #if DEBUG_BREAKPOINT
     bsp_printf("Before BP\n");
 #endif
-#ifdef __NEED_UNDERSCORE__
+
+#ifdef __ECOS__
+#  ifdef __NEED_UNDERSCORE__
+    HAL_BREAKPOINT(_bsp_breakinsn);
+#  else
+    HAL_BREAKPOINT(bsp_breakinsn);
+#  endif
+#else
+#  ifdef __NEED_UNDERSCORE__
     asm volatile (".globl _bsp_breakinsn\n"
 		  "_bsp_breakinsn:\n");
-#else
+#  else
     asm volatile (".globl bsp_breakinsn\n"
 		  "bsp_breakinsn:\n");
+#  endif
+    BREAKPOINT();
 #endif
-    BREAKPOINT();
+
 #if DEBUG_BREAKPOINT
     bsp_printf("After BP\n");
 #endif
--- a/packages/cygmon/current/misc/bsp/common/gdb-cpu.c
+++ b/packages/cygmon/current/misc/bsp/common/gdb-cpu.c
@@ -43,6 +43,10 @@
 //=========================================================================
 #include <pkgconf/system.h>
 
-#ifdef CYG_HAL_ARM
+#ifdef CYGPKG_HAL_ARM
 #include "bsp/arm/gdb-cpu.c"
 #endif
+
+#ifdef CYGPKG_HAL_MIPS
+#include "bsp/mips/gdb-cpu.c"
+#endif
--- a/packages/cygmon/current/misc/bsp/common/gdb-cpu.h
+++ b/packages/cygmon/current/misc/bsp/common/gdb-cpu.h
@@ -45,7 +45,12 @@
 //=========================================================================
 #include <pkgconf/system.h>
 
-#ifdef CYG_HAL_ARM
+#ifdef CYGPKG_HAL_ARM
 #include "../arm/gdb-cpu.h"
 #endif
+
+#ifdef CYGPKG_HAL_MIPS
+#include "../mips/gdb-cpu.h"
+#endif
+
 #endif // __BSP_COMMON_GDB_CPU_H__
--- a/packages/cygmon/current/misc/bsp/common/singlestep.c
+++ b/packages/cygmon/current/misc/bsp/common/singlestep.c
@@ -43,6 +43,10 @@
 //=========================================================================
 #include <pkgconf/system.h>
 
-#ifdef CYG_HAL_ARM
+#ifdef CYGPKG_HAL_ARM
 #include "bsp/arm/singlestep.c"
 #endif
+
+#ifdef CYGPKG_HAL_MIPS
+#include "bsp/mips/singlestep.c"
+#endif
--- a/packages/cygmon/current/misc/bsp/common/syscall.c
+++ b/packages/cygmon/current/misc/bsp/common/syscall.c
@@ -172,6 +172,32 @@ int
 	*(bsp_shared_t **)arg1 = bsp_shared_data;
 	break;
 
+      case SYS_meminfo:
+        {
+          // Return the top and size of memory.
+          struct bsp_mem_info      mem;
+          int                      i;
+          unsigned long            u, totmem, topmem, numbanks;
+
+          i = totmem = topmem = numbanks = 0;
+          while (bsp_sysinfo(BSP_INFO_MEMORY, i++, &mem) == 0)
+            {
+              if (mem.kind == BSP_MEM_RAM)
+                {
+                  numbanks++;
+                  totmem += mem.nbytes;
+                  u = (unsigned long)mem.virt_start + mem.nbytes;
+                  if (u > topmem)
+                    topmem = u;
+                }
+            }
+          *(unsigned long *)arg1 = totmem;
+          *(unsigned long *)arg2 = topmem;
+          *retval = numbanks;
+        }
+        return 1;
+        break;
+
       default:
 	return 0;
     }    
--- a/packages/cygmon/current/misc/bsp/common/syscall.h
+++ b/packages/cygmon/current/misc/bsp/common/syscall.h
@@ -46,4 +46,5 @@
 
 #define SYS_interrupt   1000
 
+#define SYS_meminfo     1001
 #endif
--- a/packages/cygmon/current/misc/bsp/cpu.h
+++ b/packages/cygmon/current/misc/bsp/cpu.h
@@ -47,8 +47,12 @@
 
 #include <pkgconf/system.h>
 
-#ifdef CYG_HAL_ARM
+#ifdef CYGPKG_HAL_ARM
 #include "arm/cpu.h"
 #endif
 
+#ifdef CYGPKG_HAL_MIPS
+#include "mips/cpu.h"
+#endif
+
 #endif // __BSP_CPU_H__
--- a/packages/cygmon/current/misc/cpu-mon.c
+++ b/packages/cygmon/current/misc/cpu-mon.c
@@ -39,6 +39,10 @@
 
 #include <pkgconf/system.h>   // Configuration header
 
-#ifdef CYG_HAL_ARM
+#ifdef CYGPKG_HAL_ARM
 #include "arm/arm-mon.c"
 #endif
+
+#ifdef CYGPKG_HAL_MIPS
+#include "mips/mips-mon.c"
+#endif
--- a/packages/cygmon/current/misc/cpu_info.h
+++ b/packages/cygmon/current/misc/cpu_info.h
@@ -46,7 +46,11 @@
 #include <pkgconf/system.h>
 #include <pkgconf/hal.h>
 
-#ifdef CYG_HAL_ARM
+#ifdef CYGPKG_HAL_ARM
 #include "arm/cpu_info.h"
 #endif
+
+#ifdef CYGPKG_HAL_MIPS
+#include "mips/cpu_info.h"
+#endif
 #endif // __CYGMON_CPU_INFO_H__
--- a/packages/cygmon/current/misc/ecos_bsp.c
+++ b/packages/cygmon/current/misc/ecos_bsp.c
@@ -45,10 +45,14 @@
 #include <cyg/hal/hal_cache.h>
 #include <cyg/kernel/kapi.h>
 #include <cyg/infra/diag.h>
-#include <cyg/io/io.h>
 #include "bsp/common/bsp_if.h"
+#include <cyg/hal/hal_if.h>
 #include <signal.h>
 #include CYGHWR_MEMORY_LAYOUT_H
+ 
+#ifdef CYGPKG_IO
+#include <cyg/io/io.h>
+#endif
 
 #define STACK_SIZE CYGNUM_HAL_STACK_SIZE_MINIMUM
 static char stack[STACK_SIZE];
@@ -72,7 +76,7 @@ cyg_start( void )
 {
     // Create a main thread, so we can run the scheduler and have time 'pass'
     cyg_thread_create(10,                // Priority - just a number
-                      cygmon_main,       // entry
+                      (cyg_thread_entry_t*)cygmon_main,       // entry
                       0,                 // entry parameter
                       "Cygmon",          // Name
                       &stack[0],         // Stack
@@ -91,11 +95,12 @@ extern void (*__cleanup_vec)(void);
 extern void __install_traps(void);
 #endif
 
+extern int machine_syscall(HAL_SavedRegisters *regs);
 void
 _bsp_handle_exception(cyg_addrword_t data, cyg_code_t num, cyg_addrword_t info)
 {
     if (num == CYGNUM_HAL_EXCEPTION_INTERRUPT) {
-        if (machine_syscall(info)) {
+        if (machine_syscall((HAL_SavedRegisters*)info)) {
             return;
         }
         // Fall through to "normal" exception handling if system call failed
@@ -129,7 +134,7 @@ void
     int d0;
     cyg_exception_set_handler(CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION,
                               _bsp_handle_exception,
-                              &d0,
+                              (cyg_addrword_t)&d0,
                               0,
                               0);
 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
@@ -142,6 +147,8 @@ void
 
 #define FAIL() diag_printf("fail: %s\n", __FUNCTION__);  while (1) ;
 
+#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
+
 struct BSP_IO {
     char            *name;
     cyg_io_handle_t  chan;
@@ -160,6 +167,8 @@ uart_putchar(void *base, char c)
     }
 }
 
+extern int __output_gdb_string (const char *str, int string_len);
+
 // This function is mostly used by the 'write()' system call
 static void
 uart_write(void *base, const char *buf, int len)
@@ -202,7 +211,59 @@ uart_getchar(void *base)
 static int
 uart_control(void *base, int func, ...)
 {
-    // FIXME - need to fill this in!
+    int rc = 0;
+    va_list ap;
+    int arg;
+    struct BSP_IO *io = (struct BSP_IO *)base;
+
+    va_start(ap, func);
+
+    if (func == COMMCTL_SETBAUD)
+    {
+        cyg_serial_info_t buffer = {
+            CYG_SERIAL_BAUD_DEFAULT, 
+            CYG_SERIAL_STOP_DEFAULT, 
+            CYG_SERIAL_PARITY_DEFAULT,
+            CYG_SERIAL_WORD_LENGTH_DEFAULT,
+            CYG_SERIAL_FLAGS_DEFAULT
+        };
+        int len = sizeof(buffer);
+        arg = va_arg(ap, int);
+
+        switch (arg)
+        {
+        case 50:         buffer.baud = CYG_SERIAL_BAUD_RATE(50);       break;
+        case 75:         buffer.baud = CYG_SERIAL_BAUD_RATE(75);       break;
+        case 110:        buffer.baud = CYG_SERIAL_BAUD_RATE(110);      break;
+        case 134:        buffer.baud = CYG_SERIAL_BAUD_RATE(134_5);    break;
+        case 135:        buffer.baud = CYG_SERIAL_BAUD_RATE(134_5);    break;
+        case 150:        buffer.baud = CYG_SERIAL_BAUD_RATE(150);      break;
+        case 200:        buffer.baud = CYG_SERIAL_BAUD_RATE(200);      break;
+        case 300:        buffer.baud = CYG_SERIAL_BAUD_RATE(300);      break;
+        case 600:        buffer.baud = CYG_SERIAL_BAUD_RATE(600);      break;
+        case 1200:       buffer.baud = CYG_SERIAL_BAUD_RATE(1200);     break;
+        case 1800:       buffer.baud = CYG_SERIAL_BAUD_RATE(1800);     break;
+        case 2400:       buffer.baud = CYG_SERIAL_BAUD_RATE(2400);     break;
+        case 3600:       buffer.baud = CYG_SERIAL_BAUD_RATE(3600);     break;
+        case 4800:       buffer.baud = CYG_SERIAL_BAUD_RATE(4800);     break;
+        case 7200:       buffer.baud = CYG_SERIAL_BAUD_RATE(7200);     break;
+        case 9600:       buffer.baud = CYG_SERIAL_BAUD_RATE(9600);     break;
+        case 14400:      buffer.baud = CYG_SERIAL_BAUD_RATE(14400);    break;
+        case 19200:      buffer.baud = CYG_SERIAL_BAUD_RATE(19200);    break;
+        case 38400:      buffer.baud = CYG_SERIAL_BAUD_RATE(38400);    break;
+        case 57600:      buffer.baud = CYG_SERIAL_BAUD_RATE(57600);    break;
+        case 115200:     buffer.baud = CYG_SERIAL_BAUD_RATE(115200);   break;
+        case 230400:     buffer.baud = CYG_SERIAL_BAUD_RATE(230400);   break;
+        default:         buffer.baud = -1; rc = -1;                    break;
+        }
+
+        if ((io->chan) && (buffer.baud != -1)) {
+            rc = cyg_io_set_config(io->chan, CYG_IO_SET_CONFIG_SERIAL_INFO, &buffer, &len);
+        }
+    }
+
+    va_end(ap);
+    return rc;
 }
 
 /*
@@ -242,6 +303,34 @@ void
     }
 }
 
+#else // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
+
+struct bsp_comm_channel _bsp_comm_list[1];
+int _bsp_num_comms = 1;
+
+// Yuck! Two things need doing:
+
+// FIXME: Make bsp code use pointers in the bsp_comm_channel instead
+//        of sub-structures.
+
+// FIXME: Make HAL provide the bsp_comm_info structure - I missed that
+//        initially because it cannot be accessed via the virtual table API.
+void
+_bsp_init_board_comm(void)
+{
+    struct bsp_comm_channel* channel;
+    hal_virtual_comm_table_t* comm;
+
+    channel = &_bsp_comm_list[0];
+    channel->info.name = "fixme";
+    channel->info.kind = BSP_COMM_SERIAL;
+    channel->info.protocol = BSP_PROTO_NONE;
+
+    comm = CYGACC_CALL_IF_DEBUG_PROCS();
+    channel->procs = *(struct bsp_comm_procs*)comm;
+}
+#endif // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
+
 /*
  * Array of memory region descriptors. We just list RAM.
  */
@@ -336,3 +425,9 @@ ecos_bsp_console_getc(void)
         return '?';
     }
 }
+
+void
+ecos_bsp_set_memsize(unsigned long size)
+{
+    _bsp_memory_list[0].nbytes = size;
+}
--- a/packages/cygmon/current/misc/ecos_dummy.c
+++ b/packages/cygmon/current/misc/ecos_dummy.c
@@ -40,6 +40,7 @@
 #include <pkgconf/kernel.h>   // Configuration header
 #include <cyg/kernel/kapi.h>
 #include <cyg/infra/diag.h>
+#include <cyg/hal/plf_stub.h>
 
 // TEMP
 
@@ -50,6 +51,9 @@ void n(void)                            
     while (1) ;                                 \
 }
 
+#ifndef CYGHWR_HAL_RESET_DEFINED
     FAIL(bsp_reset)
+#endif
+
     FAIL(_bsp_gdb_handler)
     FAIL(_bsp_gdb_data)
--- a/packages/cygmon/current/misc/ledit.c
+++ b/packages/cygmon/current/misc/ledit.c
@@ -124,7 +124,7 @@ printHistoryList ()
 static void
 outputParamStr (char *str, int val)
 {
-  char *i = index (str, '%');
+  char *i = strchr (str, '%');
   char *ptr;
   int dist = val;
 
@@ -209,7 +209,7 @@ absMoveCursor (int pos)
 }
 
 static void
-clrScrToEol ()
+clrScrToEol (void)
 {
   int len = linebuf.ebuf - linebuf.buffer;
 
@@ -238,7 +238,7 @@ clrScrToEol ()
 }
 
 static void
-redrawCmd ()
+redrawCmd (void)
 {
   xprintf (terminal.gobol);
   xprintf (linebuf.prompt);
@@ -257,7 +257,7 @@ instCmd (char *ncmd)
 }
 
 static void
-prevCmd () 
+prevCmd (void) 
 {
   if (curl == &currLine)
     {
@@ -287,7 +287,7 @@ prevCmd ()
 }
 
 static void
-nextCmd ()
+nextCmd (void)
 {
   if (curl->next == NULL)
     {
@@ -304,7 +304,7 @@ nextCmd ()
 static int initted = 0;
 
 void
-initVt100 () 
+initVt100 (void) 
 {
   terminal.gobol = "\r";
   terminal.oneleft = "\010";
@@ -319,7 +319,7 @@ initVt100 ()
 }
 
 void
-initDumb ()
+initDumb (void)
 {
   terminal.gobol = "\r";
   terminal.oneleft = "\010";
@@ -398,7 +398,7 @@ deleteEol (int putInCutBuffer)
 }
 
 static void
-deleteCurrChar ()
+deleteCurrChar (void)
 {
   int len = linebuf.ebuf - linebuf.buffer;
   char *ptr;
@@ -423,7 +423,7 @@ deleteCurrChar ()
 }
 
 static void
-deleteChar ()
+deleteChar (void)
 {
   if (linebuf.cursor == 0)
     {
--- a/packages/cygmon/current/misc/monitor.c
+++ b/packages/cygmon/current/misc/monitor.c
@@ -75,22 +75,39 @@ static void monitor_take_control (void);
 
 #if CYGMON_SYSTEM_SERVICES
 extern int process_syscall (int syscall_num);
+#elif defined (USE_ECOS_HAL_EXCEPTIONS)
+static int cygmon_process_syscall (int sigval);
 #endif
 
 int stub_is_active = 0;
 mem_addr_t last_pc;
 
 #ifdef HAVE_BSP
+
+#if !defined(USE_ECOS_HAL_EXCEPTIONS)
 static int mon_dbg_handler(int exc_nr, void *regs);
 static int mon_kill_handler(int exc_nr, void *regs);
+#endif // USE_ECOS_HAL_EXCEPTIONS
 
+#ifndef USE_ECOS_HAL_BREAKPOINTS
 #define __is_breakpoint_function() (get_pc() == (target_register_t)bsp_breakinsn)
+#endif
+
+#ifdef __ECOS__
+/*
+ * This global flag is used by generic-stub.c to communicate to us that we
+ * are processing the breakpoint function within Cygmon itself.
+ */
+int processing_breakpoint_function = 0;
+#endif
 
 /* Global pointer to current set of saved registers. */
 void *mon_saved_regs;
 
 /* Original BSP debug vector replaced by monitor. */
+#if !defined(USE_ECOS_HAL_EXCEPTIONS)
 static bsp_handler_t old_dbg_vec;
+#endif // !defined(USE_ECOS_HAL_EXCEPTIONS)
 
 #else
 static int handle_signal (int signal_val);
@@ -98,8 +115,13 @@ static int handle_signal (int signal_val
 __PFI user_signal_handler = NULL;
 #endif
 
-#ifdef __ECOS__
-extern (*__process_exception_vec)(int);
+#if defined(__ECOS__)
+#include <cyg/hal/hal_stub.h>
+#endif
+
+#if defined(__ECOS__) && !defined(PROCESS_EXCEPTION_VEC_PROTOTYPE_EXISTS)
+#define PROCESS_EXCEPTION_VEC_PROTOTYPE_EXISTS
+extern volatile __PFI (*__process_exception_vec)(int);
 #endif
 
 
@@ -141,8 +163,15 @@ int main (int argc, char **argv)
       version ();
 
       /* replace original BSP debug and kill handler with ours */
+#if !defined(USE_ECOS_HAL_EXCEPTIONS)
       old_dbg_vec = bsp_install_dbg_handler(mon_dbg_handler);
       (void)bsp_install_kill_handler(mon_kill_handler);
+#else
+      /* replace original BSP debug and kill handler with ours using eCos stuff */
+      __process_exception_vec = (__PFI)cygmon_handle_exception;
+      __process_syscall_vec = cygmon_process_syscall;
+      __process_exit_vec = monitor_take_control;
+#endif // __ECOS__
     }
   else
     {
@@ -191,7 +220,7 @@ transfer_to_stub ()
 {
   /* Return back to the exception handler, but the exception handler
      should invoke the stub's exception handler instead of ours. */
-#ifdef HAVE_BSP
+#if defined(HAVE_BSP) && !defined(USE_ECOS_HAL_EXCEPTIONS)
   (void)bsp_install_dbg_handler(old_dbg_vec);
 #else
   __switch_to_stub ();
@@ -212,20 +241,24 @@ clear_user_state (void)
 
   clear_breakpoints ();
 
-#ifdef HAVE_BSP
-  bsp_singlestep_cleanup(mon_saved_regs);
-#else
+#ifndef HAVE_BSP
   user_signal_handler = NULL;
+#endif
+
   __clear_single_step ();
-#endif
 }
 
 static void
 monitor_take_control (void)
 {
   stub_is_active = 0;
+  switch_to_stub_flag = 0;
 
-#ifdef HAVE_BSP
+  // Flush the unget state.  This is because the ecos stub and Cygmon track this
+  // stuff separately.
+  bsp_debug_ungetc('\0');
+
+#if defined(HAVE_BSP) && !defined(USE_ECOS_HAL_EXCEPTIONS)
   /* replace original BSP debug trap handler with ours */
   (void)bsp_install_dbg_handler(mon_dbg_handler);
 #else
@@ -257,6 +290,16 @@ monitor_interrupt_state (void)
 }
 #endif
 
+#if defined(USE_ECOS_HAL_EXCEPTIONS)
+externC HAL_SavedRegisters *_hal_registers;
+extern int machine_syscall(HAL_SavedRegisters *regs);
+static int
+cygmon_process_syscall (int sigval)
+{
+    return machine_syscall(_hal_registers);
+}
+#endif
+
 static int
 cygmon_handle_exception (int sigval)
 {
@@ -291,7 +334,11 @@ cygmon_handle_exception (int sigval)
   pc = get_pc();
   MAKE_STD_ADDR (pc, &last_pc);
 
+#ifdef __ECOS__
+  if ((sigval == SIGTRAP) && (__is_breakpoint_function() || processing_breakpoint_function))
+#else
   if ((sigval == SIGTRAP) && __is_breakpoint_function())
+#endif
     {
       /*
        * This is the initial breakpoint inserted by the BSP
@@ -398,14 +445,16 @@ version (void)
 
 
 #ifdef HAVE_BSP
+#if !defined(USE_ECOS_HAL_EXCEPTIONS)
 static int
 mon_kill_handler(int exc_nr, void *regs)
 {
     monitor_take_control();
     return 1;
 }
+#endif // !defined(USE_ECOS_HAL_EXCEPTIONS)
 
-
+#if !defined(USE_ECOS_HAL_EXCEPTIONS)
 static int
 mon_dbg_handler(int exc_nr, void *regs)
 {
@@ -426,4 +475,6 @@ mon_dbg_handler(int exc_nr, void *regs)
 
     return 1;
 }
+#endif // !defined(USE_ECOS_HAL_EXCEPTIONS)
+
 #endif
--- a/packages/cygmon/current/misc/monitor.h
+++ b/packages/cygmon/current/misc/monitor.h
@@ -55,6 +55,10 @@
 #endif
 #include <monitor_cmd.h>
 
+#ifdef __ECOS__
+#include <cyg/hal/plf_stub.h>
+#endif
+
 #ifndef ASM
 
 #ifdef HAVE_BSP
@@ -66,9 +70,22 @@
 #define xungetchar bsp_debug_ungetc
 #define __getTty() bsp_set_debug_comm(-1)
 #define set_pc(x)  bsp_set_pc((x), mon_saved_regs)
-#define __single_step() bsp_singlestep_setup(mon_saved_regs)
-#define __reset    bsp_reset
+
+#ifndef USE_ECOS_HAL_SINGLESTEP
+#define __single_step()            bsp_singlestep_setup(mon_saved_regs)
+#define __clear_single_step()      bsp_singlestep_cleanup(mon_saved_regs)
+#endif /* USE_ECOS_HAL_SINGLESTEP */
+
+#ifndef USE_ECOS_HAL_BREAKPOINTS
 #define breakpoint() bsp_breakpoint()
+#endif /* USE_ECOS_HAL_BREAKPOINTS */
+
+#if defined(__ECOS__) && defined(CYGHWR_HAL_RESET_DEFINED)
+   extern void __reset(void);
+#else // defined(__ECOS__) && defined(CYGHWR_HAL_RESET_DEFINED)
+#  define __reset    bsp_reset
+#endif // defined(__ECOS__) && defined(CYGHWR_HAL_RESET_DEFINED)
+
 #else
 extern void xprintf(const char *fmt, ...);
 extern void xsprintf(char *str, const char *fmt, ...);
@@ -87,19 +104,23 @@ extern int  getDebugChar(void);
 #endif
 
 
+#ifndef USE_ECOS_HAL_BREAKPOINTS
 struct bp {
   mem_addr_t address;
   bp_inst_t  old_inst;
   char       in_memory;
   struct bp  *next;
 };
+#endif // USE_ECOS_HAL_BREAKPOINTS
 
 struct regstruct
 {
   char *registername;
   int  registernumber;
 #ifdef HAVE_BSP
+#if defined(CYGPKG_HAL_ARM) || !defined(__ECOS__)
   int  registertype;
+#endif // defined(CYGPKG_HAL_ARM) || !defined(__ECOS__)
 #endif
 };
 
@@ -232,6 +253,7 @@ extern target_register_t get_pc(void);
 extern char *get_register_str (regnames_t which, int detail);
 extern void store_register (regnames_t which, char *string);
 
+#ifndef USE_ECOS_HAL_BREAKPOINTS
 /*
  * From breakpoints.c
  */
@@ -240,6 +262,7 @@ extern void install_breakpoints (void);
 extern void clear_breakpoints (void);
 extern int  show_breakpoints (void);
 extern int clear_mon_breakpoint (mem_addr_t location);
+#endif /* USE_ECOS_HAL_BREAKPOINTS */
 
 
 /*
@@ -254,8 +277,8 @@ extern void flush_dis (void);
  */
 #ifdef HAVE_BSP
 extern void initialize_mon(void);
-extern target_regval_t get_register(int regnum);
-extern void put_register(int regnum, target_regval_t val);
+extern target_register_t get_register(regnames_t reg);
+extern void put_register (regnames_t which, target_register_t value);
 #endif
 
 
--- a/packages/cygmon/current/misc/monitor_cmd.c
+++ b/packages/cygmon/current/misc/monitor_cmd.c
@@ -64,6 +64,10 @@
 #include "tservice.h"
 #endif
 
+#ifdef __ECOS__
+#include <cyg/hal/hal_stub.h>
+#endif
+
 #if USE_CYGMON_PROTOTYPES
 /* Use common prototypes */
 /* Some of the composed board.h files compose these
@@ -652,6 +656,13 @@ displayed.\n");
 #endif /* NVRAM_TCP_PORT */
 
 
+#ifdef __ECOS__
+#  if (CYG_BYTEORDER == CYG_LSBFIRST)
+#    define LITTLE_ENDIAN_TARGET
+#  else
+#    define BIG_ENDIAN_TARGET
+#  endif
+#endif
 
 #ifdef LITTLE_ENDIAN_TARGET
 static int swap_bytes = 1;
@@ -683,7 +694,7 @@ get_cmd_size (void)
   int size = 0;
   char *sizestr;
 
-  sizestr = index (argvect[0], '.');
+  sizestr = strchr (argvect[0], '.');
 
   if (sizestr == NULL || sizestr[0] == '\0' || sizestr[1] == '\0')
     {
@@ -1523,7 +1534,10 @@ Removes a previously set breakpoint at m
     {
       mem_addr_t location;
       str2addr (argvect[1], &location);
-      clear_mon_breakpoint (location);
+      if (clear_mon_breakpoint (location))
+      {
+          xprintf("Unable to remove breakpoint at 0x%08lx\n", location.addr);
+      }
     }
   return 0;
 }
@@ -1569,7 +1583,10 @@ Sets a breakpoint at address 4ff5.");
       mem_addr_t location;
       
       str2addr (argvect[1], &location);
-      add_mon_breakpoint (location);
+      if (add_mon_breakpoint (location))
+      {
+          xprintf("Unable to set breakpoint at 0x08lx\n", location.addr);
+      }
     }
   return 0;
 }
@@ -2142,6 +2159,18 @@ Fills the region between 0x10000 and 0x2
       else
         {
           int x;
+	  if (get_memory_display_mode ())
+	    {
+	      /* Gotta swap this puppy. */
+	      int x;
+
+	      for (x = 0; x < (size / 2); x++)
+		{
+		  char tmp = value[x];
+		  value [x] = value [size - 1 - x];
+		  value [size - 1 - x] = tmp;
+		}
+	    }
 
           xprintf ("Writing %d units\n", amt / size + 1);
           for (x = amt / size; x >= 0; x--)
@@ -2416,7 +2445,7 @@ monitor_loop (void)
 	  strcpy (cmd, argvect[0]);
 
 	  /* Function to split off . delimiters. */
-	  ptr = index (cmd, '.');
+	  ptr = strchr (cmd, '.');
 
 	  if (ptr != NULL && *ptr == '.')
 	    *ptr = '\0';
--- a/packages/cygmon/current/misc/tservice.h
+++ b/packages/cygmon/current/misc/tservice.h
@@ -56,10 +56,10 @@ extern int read_memory (mem_addr_t *src,
 extern int write_memory (mem_addr_t *dst, int size, int amt, char *src);
 
 
-
+#ifndef USE_ECOS_HAL_BREAKPOINTS
 extern void set_breakpoint (struct bp *bp);
 extern void clear_breakpoint (struct bp *bp);
-
+#endif // USE_ECOS_HAL_BREAKPOINTS
 
 #ifndef HAVE_BSP
 extern void set_pc (target_register_t pc);
--- a/packages/cygmon/current/misc/utils.c
+++ b/packages/cygmon/current/misc/utils.c
@@ -63,7 +63,7 @@
 #include "generic-stub.h" /* from libstub */
 #endif /* USE_CYGMON_PROTOTYPES */
 
-int switch_to_stub_flag = 0;
+volatile int switch_to_stub_flag = 0;
 
 /* Input routine for the line editor. */
 int
@@ -224,6 +224,11 @@ hex2bytes (char *str, char *dest, int ma
   for (i = 0; i < maxsize; i++)
     dest[i] = 0;
   maxsize--;
+
+  // Don't try and convert 0x prefix
+  if ((str[0] == '0') && (str[1] == 'x'))
+      str += 2;
+
   ptr = str + strlen(str) - 1;
   while (maxsize >= 0 && ptr >= str)
     {
@@ -355,19 +360,11 @@ strdup(const char *str)
 target_register_t
 get_pc(void)
 {
-#ifdef HAVE_BSP
-    target_regval_t pc;
-
-    pc = get_register(REG_PC);
-
-    return pc.i;
-#else
-    return get_register(PC);
-#endif
+    return get_register(REG_PC);
 }
 
 
-#ifdef HAVE_BSP
+#if defined(HAVE_BSP) && !defined(__ECOS__)
 static int
 get_register_type(regnames_t which)
 {
@@ -392,32 +389,7 @@ get_register_str (regnames_t which, int 
       return res;
     }
 #endif
-#ifdef HAVE_BSP
-  {
-    target_regval_t reg;
-
-    reg = get_register (which);
-    switch (get_register_type (which))
-      {
-	case REGTYPE_INT:
-	  return ull2str (reg.i, 16, sizeof(reg.i) * 2);
-	  break;
-#if HAVE_FLOAT_REGS
-	case REGTYPE_FLOAT:
-	  return float2str (reg.f);
-	  break;
-#endif
-#if HAVE_DOUBLE_REGS
-	case REGTYPE_DOUBLE:
-	  return double2str (reg.d);
-	  break;
-#endif
-      }
-    return "...help...";
-  }
-#else
   return int2str (get_register (which), 16, sizeof (target_register_t) * 2);
-#endif
 }
 
 
@@ -428,31 +400,7 @@ store_register (regnames_t which, char *
   if (SPECIAL_REG_STORE(which, string))
     return;
 #endif
-#ifdef HAVE_BSP
-  {
-    target_regval_t reg;
-
-    switch (get_register_type(which))
-      {
-	case REGTYPE_INT:
-	  reg.i = str2int (string, 16);
-	  break;
-#if HAVE_FLOAT_REGS
-	case REGTYPE_FLOAT:
-	  reg.f = str2float (string, 16);
-	  break;
-#endif
-#if HAVE_DOUBLE_REGS
-	case REGTYPE_DOUBLE:
-	  reg.d = str2double (string, 16);
-	  break;
-#endif
-      }
-    put_register (which, reg);
-  }
-#else
   put_register (which, str2int (string, 16));
-#endif
 }
 
 
--- a/packages/devs/eth/arm/ebsa285/current/ChangeLog
+++ b/packages/devs/eth/arm/ebsa285/current/ChangeLog
@@ -1,3 +1,17 @@
+2000-07-18  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* src/if_ebsa285.c (i82559_poll): Fill in the flesh of this, it
+	just calls ISR and DSR repeatedly.
+	(i82559_start): Look in the device record for promiscuous mode
+	flag; it should be passed though the common layer, but it's not
+	[yet] - this change from Andrew Lunn/ASCOM.  Also a fix and delay
+	to the promisc mode code per se.
+
+2000-07-17  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* src/if_ebsa285.c (i82559_poll): New function, just to fill in
+	the interface record; not used.
+
 2000-06-27  Hugo Tyson  <hmt@cygnus.co.uk>
 
 	* cdl/ebsa285_eth_drivers.cdl: Add sesquipedalian option
--- a/packages/devs/eth/arm/ebsa285/current/src/if_ebsa285.c
+++ b/packages/devs/eth/arm/ebsa285/current/src/if_ebsa285.c
@@ -63,6 +63,7 @@
 #include <cyg/hal/drv_api.h>
 #include <netdev.h>
 #include <eth_drv.h>
+#include <net/if.h>  /* Needed for struct ifnet */
 
 #ifdef CYGPKG_IO_PCI
 #include <cyg/io/pci.h>
@@ -398,7 +399,8 @@ ETH_DRV_SC(ebsa285_sc0,
            i82559_ioctl,
            i82559_can_send,
            i82559_send,
-           i82559_recv);
+           i82559_recv,
+           i82559_poll);
 
 NETDEVTAB_ENTRY(ebsa285_netdev0, 
                 "ebsa285-0", 
@@ -417,7 +419,8 @@ ETH_DRV_SC(ebsa285_sc1,
            i82559_ioctl,
            i82559_can_send,
            i82559_send,
-           i82559_recv);
+           i82559_recv,
+           i82559_poll);
 
 NETDEVTAB_ENTRY(ebsa285_netdev1, 
                 "ebsa285-1", 
@@ -927,6 +930,7 @@ static void i82559_start( struct eth_drv
 #ifdef KEEP_STATISTICS
     void *p_statistics;
 #endif
+    struct ifnet *ifp = &sc->sc_arpcom.ac_if;
 
     p_i82559 = (struct i82559 *)sc->driver_private;
     
@@ -976,10 +980,11 @@ static void i82559_start( struct eth_drv
     
     p_i82559->active = 1;
 
-    if ( 0
+    if (( 0
 #ifdef ETH_DRV_FLAGS_PROMISC_MODE
          != (flags & ETH_DRV_FLAGS_PROMISC_MODE)
 #endif
+        ) || (ifp->if_flags & IFF_PROMISC)
         ) {
         eth_set_promiscuous_mode(p_i82559);
     }
@@ -1732,6 +1737,26 @@ void eth_mux_dsr(cyg_vector_t vector, cy
 }
 
 // ------------------------------------------------------------------------
+// Device table entry to operate the chip in a polled mode.
+
+void i82559_poll(struct eth_drv_sc *sc)
+{
+    struct i82559 *p_i82559;
+    p_i82559 = (struct i82559 *)sc->driver_private;
+    
+    IF_BAD_82559( p_i82559 ) {
+#ifdef DEBUG
+        os_printf( "i82559_poll: Bad device pointer %x\n", p_i82559 );
+#endif
+        return;
+    }
+
+    // As it happens, this driver always requests the DSR to be called:
+    (void)eth_mux_isr( CYGNUM_HAL_INTERRUPT_PCI_IRQ, (cyg_addrword_t)p_i82559 );
+    eth_dsr( CYGNUM_HAL_INTERRUPT_PCI_IRQ, 1, (cyg_addrword_t)p_i82559 );
+}
+
+// ------------------------------------------------------------------------
 //
 //  Function : pci_init_find_82559s
 //
@@ -2003,11 +2028,21 @@ static int eth_set_promiscuous_mode(stru
     OUTL(VIRT_TO_BUS(ccs), ioaddr + SCBPointer); 
     OUTW(SCB_M | CU_START, ioaddr + SCBCmd);    
   
+    udelay(10000);
+
     // now check for result ...
     wait_for_cmd_done(ioaddr);   
   
     if ( (!ccs->cb_entry.cb_ok) || (!ccs->cb_entry.cb_complete) )
         return 1; // Failed
+
+    wait_for_cmd_done(ioaddr);
+    /* load pointer to Rx Ring */
+    
+    OUTL(VIRT_TO_BUS(p_i82559->rx_ring[0]),
+         ioaddr + SCBPointer);
+    OUTW(RUC_START, ioaddr + SCBCmd);
+
     return 0; // OK
 }
 
--- a/packages/devs/serial/v85x/v850/current/ChangeLog
+++ b/packages/devs/serial/v85x/v850/current/ChangeLog
@@ -1,3 +1,7 @@
+2000-07-19  Gary Thomas  <gthomas@redhat.com>
+
+	* src/v85x_v850_serial.h: Base baud rate calculations on CPU frequency.
+
 2000-06-22  Hugo Tyson  <hmt@cygnus.co.uk>
 
 	* cdl/<yournamehere>.cdl: Remove the comment on the empty
--- a/packages/devs/serial/v85x/v850/current/src/v85x_v850_serial.h
+++ b/packages/devs/serial/v85x/v850/current/src/v85x_v850_serial.h
@@ -58,7 +58,7 @@ struct serial_port {
     unsigned char txs;         // Transmit shift register
     unsigned char _filler3;
     unsigned char rxs;         // Receive shift register
-    unsigned char _filler4;
+    unsigned char _filler4[5];
     unsigned char brgm;        // Baud rate mode
     unsigned char _filler5;
 };
@@ -114,12 +114,11 @@ static unsigned char select_parity[] = {
     ASIM_Parity_space,            // Space parity
 };
 
-// Baud rate values, based on raw 17MHz clock
-
 static struct v850_baud {
     unsigned char count;
     unsigned char mode;
 } select_baud[] = {
+// Baud rate values, based on raw 17MHz clock
       {0, 0},  // Unused
       {0, 0},  // 50
       {0, 0},  // 75
--- a/packages/ecos.db
+++ b/packages/ecos.db
@@ -179,6 +179,7 @@ package CYGPKG_IO_SERIAL_TX39_JMR3904 {
     description       "TX39 JMR3904 serial device drivers"
 }
 
+
 package CYGPKG_IO_SERIAL_MIPS_VRC4373 {
     alias             { "VRC4373 serial device drivers"
                         devs_serial_mips_vrc4373 vrc4373_serial_driver }
@@ -777,6 +778,8 @@ package CYGPKG_HAL_MIPS_TX39_JMR3904 {
            `target sim --board=jmr3904' should be used from inside gdb."
 }
 
+
+
 package CYGPKG_HAL_MIPS_VR4300 {
 	alias		{ "VR4300 chip HAL" hal_vr4300 vr4300_hal vr4300_arch_hal }
 	directory	hal/mips/vr4300/
--- a/packages/hal/arm/arch/current/ChangeLog
+++ b/packages/hal/arm/arch/current/ChangeLog
@@ -1,3 +1,8 @@
+2000-07-17  Jesper Skov  <jskov@redhat.com>
+
+	* src/vectors.S (start): Hack to allow thumb tests to run in farm
+	until vector table Thumb/ARM API is fixed.
+
 2000-07-07  Jesper Skov  <jskov@redhat.com>
 
 	* src/arm_stub.c: Changes to support CygMon changes.
--- a/packages/hal/arm/arch/current/include/arm_stub.h
+++ b/packages/hal/arm/arch/current/include/arm_stub.h
@@ -53,7 +53,10 @@ extern "C" {
 
 #define REGSIZE( _x_ ) (((_x_) < F0 || (_x_) >= FPS) ? 4 : 12)
 
+#ifndef TARGET_REGISTER_T_DEFINED
+#define TARGET_REGISTER_T_DEFINED
 typedef unsigned long target_register_t;
+#endif
 
 enum regnames {
     R0, R1, R2, R3, R4, R5, R6, R7, 
--- a/packages/hal/arm/arch/current/src/vectors.S
+++ b/packages/hal/arm/arch/current/src/vectors.S
@@ -387,13 +387,17 @@ 2:
         ldr     r2,[r1,#0x24]   
         str     r2,[r0,#0x24]
 #endif
-        
+
+	// FIXME: The line with the thumb check is a hack, allowing
+	// the farm to run test. Problem is that virtual vector table
+	// API needs to be ARM/Thumb consistent. Will fix later.
+#if !defined(__thumb__) || defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
 #if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
     || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
         .extern hal_ctrlc_isr_init
         bl      hal_ctrlc_isr_init
 #endif
-
+#endif
         LED 2
         
         // Run through static constructors
--- a/packages/hal/arm/ebsa285/current/ChangeLog
+++ b/packages/hal/arm/ebsa285/current/ChangeLog
@@ -1,3 +1,8 @@
+2000-07-17  Jesper Skov  <jskov@redhat.com>
+
+	* src/hal_diag.c (cyg_hal_plf_serial_isr): Return value was not
+	always correct.
+
 2000-07-04  Jesper Skov  <jskov@redhat.com>
 
 	* src/plf_stub.c: [deleted]
--- a/packages/hal/arm/ebsa285/current/src/hal_diag.c
+++ b/packages/hal/arm/ebsa285/current/src/hal_diag.c
@@ -248,19 +248,19 @@ cyg_hal_plf_serial_isr(void *__ch_data, 
     CYGARC_HAL_SAVE_GP();
 
     if ( CYGNUM_HAL_INTERRUPT_SERIAL_RX == __vector ) {
-      reg = base->flag_register;
-      // read it anyway just in case - no harm done and we might
-      // prevent an interrup loop
-      c = (char)(base->data_register & 0xFF);
+        reg = base->flag_register;
+        // read it anyway just in case - no harm done and we might
+        // prevent an interrup loop
+        c = (char)(base->data_register & 0xFF);
 
-      cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_SERIAL_RX);
-      *__ctrlc = 0;
-      if ( (reg & SA110_RX_FIFO_STATUS_MASK) != SA110_RX_FIFO_EMPTY ) {
-        if( cyg_hal_is_break( &c , 1 ) )
-          *__ctrlc = 1;
-
+        cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_SERIAL_RX);
+        *__ctrlc = 0;
+        if ( (reg & SA110_RX_FIFO_STATUS_MASK) != SA110_RX_FIFO_EMPTY ) {
+            if( cyg_hal_is_break( &c , 1 ) )
+                *__ctrlc = 1;
+            
+        }
         res = CYG_ISR_HANDLED;
-      }
     }
 
     CYGARC_HAL_RESTORE_GP();
--- a/packages/hal/arm/pid/current/ChangeLog
+++ b/packages/hal/arm/pid/current/ChangeLog
@@ -1,3 +1,8 @@
+2000-07-17  Jesper Skov  <jskov@redhat.com>
+
+	* src/pid_misc.c (hal_hardware_init): Hack to allow thumb tests to
+	run in farm until vector table Thumb/ARM API is fixed.
+
 2000-07-07  Jesper Skov  <jskov@redhat.com>
 
 	* cdl/hal_arm_pid.cdl: CygMon changed to use virtual vectors.
--- a/packages/hal/arm/pid/current/src/pid_misc.c
+++ b/packages/hal/arm/pid/current/src/pid_misc.c
@@ -132,9 +132,13 @@ void hal_hardware_init(void)
     // Any hardware/platform initialization that needs to be done.
     HAL_WRITE_UINT32(CYG_DEVICE_IRQ_EnableClear, 0xFFFF); // Clear all
                                                          // interrupt sources
-
+    // FIXME: The line with the thumb check is a hack, allowing
+    // the farm to run test. Problem is that virtual vector table
+    // API needs to be ARM/Thumb consistent. Will fix later.
+#ifndef __thumb__
     // Set up eCos/ROM interfaces
     hal_if_init();
+#endif
 }
 
 //
--- a/packages/hal/common/current/ChangeLog
+++ b/packages/hal/common/current/ChangeLog
@@ -1,3 +1,45 @@
+2000-07-21  Gary Thomas  <gthomas@redhat.com>
+
+	* src/hal_if.c (CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS): Define to allow
+	the number of channels to be extended by "AUX" packages.
+
+2000-07-20  Drew Moseley  <dmoseley@redhat.com>
+
+	* src/generic-stub.c (stub_format_registers): Make the previous patch
+	effective only if CYGARC_REGSIZE_DIFFERS_FROM_TARGET_REGISTER_T is
+	defined so as to not affect any other targets.
+	* src/hal_stub.c: Ditto.
+
+2000-07-19  Drew Moseley  <dmoseley@redhat.com>
+
+	* src/generic-stub.c (stub_format_registers): Handle the case
+	where GDB is expecting registers larger than we are storing.  ie
+	MIPS gdb expects 64 bit registers even if we are on a 32 bit
+	architecture.  Also, handle the sign-extension correctly if
+	necessary.
+	* src/hal_stub.c (__build_t_packet): Ditto.
+
+2000-07-18  Jesper Skov  <jskov@redhat.com>
+
+	* src/hal_misc.c (hal_default_isr): 
+	Version gets hacked by hal_if_init - check for the hacked value.
+
+2000-07-18  Jesper Skov  <jskov@redhat.com>
+
+	* src/hal_stub.c (__mem_fault_handler): Made volatile.
+	
+2000-07-14  Drew Moseley  <dmoseley@redhat.com>
+
+	* src/generic-stub.c: Cleanups for better coexistence with Cygmon.
+	* include/generic-stub.h: Ditto.
+	* include/hal_if.h: Ditto.
+	* include/hal_stub.h: Ditto.
+	* src/hal_stub.c: Ditto.
+
+	* cdl/hal.cdl: Compile bplist-dynamic.c.
+
+	* src/bplist-dynamic.c: New file for supporting breakpoints in the HAL.
+
 2000-07-14  Gary Thomas  <gthomas@redhat.com>
 
 	* src/hal_if.c (delay_us): Use HAL_DELAY_US() if defined.
--- a/packages/hal/common/current/cdl/hal.cdl
+++ b/packages/hal/common/current/cdl/hal.cdl
@@ -33,7 +33,7 @@
 #
 # Author(s):      bartv
 # Original data:  nickg,jskov,jlarmour
-# Contributors:
+# Contributors:   dmoseley
 # Date:           1999-06-13
 #
 #####DESCRIPTIONEND####
@@ -54,7 +54,7 @@ cdl_package CYGPKG_HAL {
         options that are common to all HAL packages."
     doc           redirect/the-ecos-hardware-abstraction-layer-hal.html
 
-    compile       generic-stub.c thread-packets.c hal_stub.c drv_api.c
+    compile       generic-stub.c thread-packets.c hal_stub.c drv_api.c bplist-dynamic.c
     compile       -library=libextras.a dummy.c
 
     make -priority 250 {
--- a/packages/hal/common/current/include/generic-stub.h
+++ b/packages/hal/common/current/include/generic-stub.h
@@ -94,7 +94,10 @@ extern void put_register (regnames_t whi
 
 /* Set the next instruction to be executed when the user program resumes
    execution to PC. */
+#if !defined(SET_PC_PROTOTYPE_EXISTS) && !defined(set_pc)
+#define SET_PC_PROTOTYPE_EXISTS
 extern void set_pc (target_register_t pc);
+#endif
 
 /* Set the return value of the currently-pending syscall to VALUE. */
 extern void set_syscall_value (target_register_t value);
@@ -115,11 +118,15 @@ extern void __skipinst (void);
 
 /* If the address in the PC register corresponds to the breakpoint()
    instruction, return a non-zero value. */
+#ifndef __is_breakpoint_function
 extern int __is_breakpoint_function (void);
+#endif
 
 /* Execute a breakpoint instruction. Restarting will cause the instruction
    to be skipped. */
+#ifndef breakpoint
 extern void breakpoint (void);
+#endif
 
 /* Return the syscall # corresponding to this system call. */
 extern int __get_syscall_num (void);
@@ -142,9 +149,11 @@ extern int __read_mem_safe (void *buf,
    ADDR is assumed to live in the user program's space. 
    Returns number of bytes successfully read 
    (caller must check to see if less than requested).  */
+#ifndef __write_mem_safe
 extern int __write_mem_safe (void *buf, 
                              void *addr, 
                              int count);
+#endif
 
 /* Set to a non-zero value if a memory fault occurs while 
    __set_mem_fault_trap () is running. */
@@ -189,7 +198,10 @@ typedef void (*__PFV)(void);
    should return zero if it wishes execution to resume from the saved
    register values; a non-zero value indicates that the exception handler
    should be reinvoked. */
+#if !defined(PROCESS_EXCEPTION_VEC_PROTOTYPE_EXISTS)
+#define PROCESS_EXCEPTION_VEC_PROTOTYPE_EXISTS
 extern volatile __PFI __process_exception_vec;
+#endif
 
 /* __process_exit_vec is invoked when a 'k' kill packet is received
    from GDB. */
@@ -292,7 +304,7 @@ extern int __process_packet (char *packe
    Used for printing debug messages. */
 extern void __putDebugStr (char *str);
 
-#ifdef NO_MALLOC
+#if defined(NO_MALLOC) && !defined(MAX_BP_NUM)
 #define MAX_BP_NUM 64 /* Maximum allowed # of breakpoints */
 #endif
 
--- a/packages/hal/common/current/include/hal_if.h
+++ b/packages/hal/common/current/include/hal_if.h
@@ -56,7 +56,10 @@
 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
 
 //--------------------------------------------------------------------------
+#ifndef _BSP_HANDLER_T_DEFINED
+#define _BSP_HANDLER_T_DEFINED
 typedef int (*bsp_handler_t)(int __irq_nr, void *__regs);
+#endif // _BSP_HANDLER_T_DEFINED
 
 //--------------------------------------------------------------------------
 // Communication interface table. CYGNUM_CALL_IF_CONSOLE_PROCS and
--- a/packages/hal/common/current/include/hal_stub.h
+++ b/packages/hal/common/current/include/hal_stub.h
@@ -53,12 +53,19 @@
 
 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
 #define USE_GDBSTUB_PROTOTYPES 0        // avoid stub-tservice.h atm
+#ifndef __ECOS__
 #define __ECOS__                        // use to mark eCos hacks
+#endif
 
 #include <cyg/hal/basetype.h>           // HAL_LABEL_NAME
 #include <cyg/hal/hal_arch.h>           // HAL header
 #include <cyg/infra/cyg_type.h>         // cyg_uint32 and CYG_BYTEORDER
+
+#ifndef __CYGMON_TYPES
+#define __CYGMON_TYPES
 typedef cyg_uint32 uint32;
+typedef cyg_int32  int32;
+#endif // __CYGMON_TYPES
 
 #include <cyg/hal/plf_stub.h>
 #include <cyg/hal/generic-stub.h>
@@ -146,15 +153,22 @@ extern void ungetDebugChar (int ch);
 extern void __reset (void);
 
 // Multi-bp support.
+#ifndef __set_breakpoint
 extern int __set_breakpoint (target_register_t addr);
+#endif
+#ifndef __remove_breakpoint
 extern int __remove_breakpoint (target_register_t addr);
+#endif
 
 /* Install the standard set of trap handlers for the stub. */
 extern void __install_traps (void);
 
 /* Address in text section of a breakpoint instruction.  */
 
+#ifndef BREAKINST_DEFINED
+#define BREAKINST_DEFINED
 extern void CYG_LABEL_NAME(breakinst) (void);
+#endif
 
 /* The opcode for a breakpoint instruction.  */
 
@@ -261,6 +275,12 @@ static inline int strlen( const char *s 
 //-----------------------------------------------------------------------------
 // Repeat the cache definitions here to avoid too much hackery in 
 // generic-stub.h
+/* Flush the instruction cache. */
+extern void flush_i_cache (void);
+
+/* Flush the data cache. */
+extern void __flush_d_cache (void);
+
 typedef enum {
   CACHE_NOOP, CACHE_ENABLE, CACHE_DISABLE, CACHE_FLUSH
 } cache_control_t;
new file mode 100644
--- /dev/null
+++ b/packages/hal/common/current/src/bplist-dynamic.c
@@ -0,0 +1,238 @@
+//==========================================================================
+//
+//      bplist-dynamic.c
+//
+//      Dynamic breakpoint list.
+//      Currently only statically allocated.  (ie NO_MALLOC is assumed)
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    
+// Contributors: dmoseley
+// Date:         2000-07-11
+// Purpose:      Dynamic breakpoint list.
+// Description:  
+//               
+//
+//####DESCRIPTIONEND####
+//
+//=========================================================================
+
+#include <cyg/hal/hal_stub.h>
+
+#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
+
+#if defined(CYGNUM_HAL_BREAKPOINT_LIST_SIZE) && (CYGNUM_HAL_BREAKPOINT_LIST_SIZE > 0)
+
+/*
+ * A simple target breakpoint list without using malloc.
+ * To use this package, you must define HAL_BREAKINST_SIZE to be the size
+ * in bytes of a trap instruction (max if there's more than one),
+ * HAL_BREAKINST to the opcode value of the instruction, and
+ * HAL_BREAKINST_TYPE to be the type necessary to hold the opcode value.
+ */
+
+struct breakpoint_list {
+  target_register_t  addr;
+  char old_contents [HAL_BREAKINST_SIZE];
+  struct breakpoint_list *next;
+  char in_memory;
+} *breakpoint_list = NULL;
+
+static HAL_BREAKINST_TYPE break_inst = HAL_BREAKINST;
+static void *_break_inst = &break_inst;
+
+static struct breakpoint_list bp_list [CYGNUM_HAL_BREAKPOINT_LIST_SIZE];
+static struct breakpoint_list *free_bp_list = NULL;
+static int curr_bp_num = 0;
+
+int
+__set_breakpoint (target_register_t addr)
+{
+  struct breakpoint_list **addent = &breakpoint_list;
+  struct breakpoint_list *l = breakpoint_list;
+  struct breakpoint_list *newent;
+
+  while (l != NULL && l->addr < addr)
+    {
+      addent = &l->next;
+      l =  l->next;
+    }
+
+  if (l != NULL && l->addr == addr)
+    return 2;
+
+  if (free_bp_list != NULL)
+    {
+      newent = free_bp_list;
+      free_bp_list = free_bp_list->next;
+    }
+  else
+    {
+      if (curr_bp_num < CYGNUM_HAL_BREAKPOINT_LIST_SIZE)
+	{
+	  newent = &bp_list[curr_bp_num++];
+	}
+      else
+	{
+	  return 1;
+	}
+    }
+
+  newent->addr = addr;
+  newent->in_memory = 0;
+  newent->next = l;
+  *addent = newent;
+  return 0;
+}
+
+int
+__remove_breakpoint (target_register_t addr)
+{
+  struct breakpoint_list *l = breakpoint_list;
+  struct breakpoint_list *prev = NULL;
+
+  while (l != NULL && l->addr < addr)
+    {
+      prev = l;
+      l = l->next;
+    }
+
+  if ((l == NULL) || (l->addr != addr))
+    return 1;
+
+  if (l->in_memory)
+    {
+      __write_mem_safe (&l->old_contents[0],
+			(void*)l->addr,
+			sizeof (l->old_contents));
+    }
+
+  if (prev == NULL)
+    breakpoint_list = l->next;
+  else
+    prev->next = l->next;
+
+  l->next = free_bp_list;
+  free_bp_list = l;
+
+  return 0;
+}
+
+void
+__install_breakpoint_list (void)
+{
+  struct breakpoint_list *l = breakpoint_list;
+
+  while (l != NULL)
+    {
+      if (! l->in_memory)
+	{
+	  int len = sizeof (l->old_contents);
+	  if (__read_mem_safe (&l->old_contents[0], (void*)l->addr, len) == len)
+	    {
+	      if (__write_mem_safe (_break_inst, (void*)l->addr, len) == len)
+		{
+		  l->in_memory = 1;
+		}
+	    }
+
+	}
+      l = l->next;
+    }
+  flush_i_cache ();
+}
+
+void
+__clear_breakpoint_list ()
+{
+  struct breakpoint_list *l = breakpoint_list;
+
+  while (l != NULL)
+    {
+      if (l->in_memory)
+	{
+	  int len = sizeof (l->old_contents);
+	  if (__write_mem_safe (&l->old_contents[0], (void*)l->addr, len) == len)
+	    {
+	      l->in_memory = 0;
+	    }
+	}
+      l = l->next;
+    }
+  flush_i_cache ();
+}
+
+int
+__display_breakpoint_list (void (*print_func)(target_register_t))
+{
+  struct breakpoint_list *l = breakpoint_list;
+
+  while (l != NULL)
+    {
+      print_func(l->addr);
+      l = l->next;
+    }
+
+  return 0;
+}
+
+#else  // (CYGNUM_HAL_BREAKPOINT_LIST_SIZE == 0) or UNDEFINED
+
+#include <cyg/hal/hal_stub.h>           // Our header
+
+int
+__set_breakpoint (target_register_t addr)
+{
+  return 1;
+}
+
+int
+__remove_breakpoint (target_register_t addr)
+{
+  return 1;
+}
+
+void
+__install_breakpoint_list (void)
+{
+}
+
+void
+__clear_breakpoint_list (void)
+{
+}
+
+int
+__display_breakpoint_list (void (*print_func)(target_register_t))
+{
+}
+#endif // (CYGNUM_HAL_BREAKPOINT_LIST_SIZE > 0)
+
+#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
+
--- a/packages/hal/common/current/src/generic-stub.c
+++ b/packages/hal/common/current/src/generic-stub.c
@@ -757,6 +757,10 @@ unlock_thread_scheduler ()
 #endif /* DEBUG_THREADS */
 }
 
+#ifdef CYGPKG_CYGMON
+extern int processing_breakpoint_function;
+#endif
+
 void
 __handle_exception (void)
 {
@@ -791,7 +795,16 @@ void
 #endif // __ECOS__
 
   if (__is_breakpoint_function ())
+  {
+#ifdef CYGPKG_CYGMON
+    processing_breakpoint_function = 1;
+#endif
     __skipinst ();
+  } else {
+#ifdef CYGPKG_CYGMON
+    processing_breakpoint_function = 0;
+#endif
+  }
 
 #ifndef __ECOS__
   if (__cleanup_vec != NULL)
@@ -890,10 +903,26 @@ stub_format_registers(char *ptr)
             } else if (sizeof (addr) < REGSIZE (regnum)) {
                 int off = REGSIZE (regnum) - sizeof (addr);
                 int x;
+                char extend_val = 0;
 
+#if defined(CYGARC_REGSIZE_DIFFERS_FROM_TARGET_REGISTER_T) && defined(CYGARC_SIGN_EXTEND_REGISTERS)
+                {
+                    unsigned long bits_in_addr = (sizeof(addr) << 3);  // ie Size in bytes * 8
+                    target_register_t sign_bit_mask = (1 << (bits_in_addr - 1));
+                    if ((addr & sign_bit_mask) == sign_bit_mask)
+                        extend_val = ~0;
+                }
+#endif
+
+#if defined(__LITTLE_ENDIAN__) || defined(_LITTLE_ENDIAN)
                 for (x = 0; x < off; x++)
-                    dummyDat[x] = 0;
+                    dummyDat[x + sizeof(addr)] = extend_val;
+                memcpy (dummyDat, &addr, sizeof (addr));
+#else
+                for (x = 0; x < off; x++)
+                    dummyDat[x] = extend_val;
                 memcpy (dummyDat + off, &addr, sizeof (addr));
+#endif
                 vptr = dummyDat;
             }
         }
@@ -1439,6 +1468,13 @@ void
 __switch_to_stub (void)
 {
   __process_exception_vec = process_exception;
+#ifdef CYGPKG_CYGMON
+  // Cygmon will have consumed the '$' character for this packet.
+  // Let's put one in the unget buffer.
+  // Actually, Cygmon does an unget, but since it uses different
+  // unget handling, we need to do this here.
+  ungetDebugChar('$');
+#endif
 }
 
 #if ! defined(BOARD_SPECIFIC_STUB_INIT)
--- a/packages/hal/common/current/src/hal_if.c
+++ b/packages/hal/common/current/src/hal_if.c
@@ -161,7 +161,15 @@ nop_service(void)
 //----------------------------------
 // Comm controls
 
-static hal_virtual_comm_table_t comm_channels[CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS+1];
+#ifdef CYGNUM_HAL_VIRTUAL_VECTOR_AUX_CHANNELS
+#define CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS \
+  (CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS+CYGNUM_HAL_VIRTUAL_VECTOR_AUX_CHANNELS)
+#else
+#define CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS \
+  CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS
+#endif
+
+static hal_virtual_comm_table_t comm_channels[CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS+1];
 
 static int
 set_debug_comm(int __comm_id)
@@ -173,7 +181,7 @@ set_debug_comm(int __comm_id)
     CYGARC_HAL_SAVE_GP();
 
     CYG_ASSERT(__comm_id >= CYGNUM_CALL_IF_SET_COMM_ID_MANGLER
-               && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS,
+               && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS,
                "Invalid channel");
 
     switch (__comm_id) {
@@ -231,7 +239,7 @@ set_console_comm(int __comm_id)
     CYGARC_HAL_SAVE_GP();
 
     CYG_ASSERT(__comm_id >= CYGNUM_CALL_IF_SET_COMM_ID_MANGLER
-               && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS,
+               && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS,
                "Invalid channel");
 
     switch (__comm_id) {
@@ -422,7 +430,7 @@ hal_if_init(void)
         for (i = 0; i < CYGNUM_CALL_IF_TABLE_SIZE; i++)
             hal_virtual_vector_table[i] = (CYG_ADDRWORD) &nop_service;
 
-        for (j = 0; j < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS+1; j++)
+        for (j = 0; j < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS+1; j++)
             for (i = 0; i < CYGNUM_COMM_IF_TABLE_SIZE; i++)
                 comm_channels[j][i] = (CYG_ADDRWORD) &nop_service;
 
--- a/packages/hal/common/current/src/hal_misc.c
+++ b/packages/hal/common/current/src/hal_misc.c
@@ -131,7 +131,7 @@ hal_default_isr(CYG_ADDRWORD vector, CYG
     int gdb_vector = -1;
     // This check only to avoid crash on older stubs in case of unhandled
     // interrupts. It is a bit messy, but required in a transition period.
-    if (CYGNUM_CALL_IF_TABLE_VERSION == CYGACC_CALL_IF_VERSION()) {
+    if (CYGNUM_CALL_IF_TABLE_VERSION+1 == CYGACC_CALL_IF_VERSION()) {
         hal_virtual_comm_table_t* comm = CYGACC_CALL_IF_DEBUG_PROCS();
         gdb_vector = CYGACC_COMM_IF_CONTROL(*comm, __COMMCTL_DBG_ISR_VECTOR);
     }
--- a/packages/hal/common/current/src/hal_stub.c
+++ b/packages/hal/common/current/src/hal_stub.c
@@ -63,6 +63,11 @@
 #include <cyg/hal/dbg-threads-api.h>    // dbg_currthread_id
 #endif
 
+#ifdef USE_LONG_NAMES_FOR_ENUM_REGNAMES
+#define PC REG_PC
+#define SP REG_SP
+#endif
+
 //-----------------------------------------------------------------------------
 // Extra eCos data.
 
@@ -579,10 +584,6 @@ unsigned long
 }
 #endif
 
-// FIXME: Add support for multiple breakpoints (libstub/bplist-dynamic.c)
-int __set_breakpoint (target_register_t addr)    { return 0; }
-int __remove_breakpoint (target_register_t addr) { return 0; }
-
 //-----------------------------------------------------------------------------
 // Write the 'T' packet in BUFFER. SIGVAL is the signal the program received.
 void 
@@ -590,9 +591,6 @@ void
 {
     target_register_t addr;
     char *ptr = buf;
-    target_register_t sp;
-
-    sp = (target_register_t) get_register (SP);
 
     *ptr++ = 'T';
     *ptr++ = __tohex (sigval >> 4);
@@ -636,13 +634,54 @@ void
     *ptr++ = __tohex (PC);
     *ptr++ = ':';
     addr = get_register (PC);
+#ifdef CYGARC_REGSIZE_DIFFERS_FROM_TARGET_REGISTER_T
+    ptr = __mem2hex((char *)&addr, ptr, sizeof(addr), 0);
+    if (sizeof(addr) < REGSIZE(PC))
+    {
+        // GDB is expecting REGSIZE(PC) number of bytes.
+        // We only have sizeof(addr) number.  Let's fill
+        // the appropriate number of bytes intelligently.
+        target_register_t extend_val = 0;
+#ifdef CYGARC_SIGN_EXTEND_REGISTERS
+        {
+            unsigned long bits_in_addr = (sizeof(addr) << 3);  // ie Size in bytes * 8
+            target_register_t sign_bit_mask = (1 << (bits_in_addr - 1));
+            if ((addr & sign_bit_mask) == sign_bit_mask)
+                extend_val = ~0;
+        }
+#endif
+        ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(PC) - sizeof(addr), 0);
+    }
+#else
     ptr = __mem2hex((char *)&addr, ptr, REGSIZE(PC), 0);
+#endif
     *ptr++ = ';';
 
     *ptr++ = __tohex (SP >> 4);
     *ptr++ = __tohex (SP);
     *ptr++ = ':';
-    ptr = __mem2hex((char *)&sp, ptr, REGSIZE(SP), 0);
+    addr = (target_register_t) get_register (SP);
+#ifdef CYGARC_REGSIZE_DIFFERS_FROM_TARGET_REGISTER_T
+    ptr = __mem2hex((char *)&addr, ptr, sizeof(addr), 0);
+    if (sizeof(addr) < REGSIZE(SP))
+    {
+        // GDB is expecting REGSIZE(SP) number of bytes.
+        // We only have sizeof(addr) number.  Let's fill
+        // the appropriate number of bytes intelligently.
+        target_register_t extend_val = 0;
+#ifdef CYGARC_SIGN_EXTEND_REGISTERS
+        {
+            unsigned long bits_in_addr = (sizeof(addr) << 3);  // ie Size in bytes * 8
+            target_register_t sign_bit_mask = (1 << (bits_in_addr - 1));
+            if ((addr & sign_bit_mask) == sign_bit_mask)
+                extend_val = ~0;
+        }
+#endif
+        ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(SP) - sizeof(addr), 0);
+    }
+#else
+    ptr = __mem2hex((char *)&addr, ptr, REGSIZE(SP), 0);
+#endif
     *ptr++ = ';';
     
     *ptr++ = 0;
@@ -716,7 +755,7 @@ int
 //-----------------------------------------------------------------------------
 // Memory accessor functions.
 
-void *__mem_fault_handler = (void *)0;
+volatile void *__mem_fault_handler = (void *)0;
 
 /* These are the "arguments" to __do_read_mem and __do_write_mem, 
    which are passed as globals to avoid squeezing them thru
--- a/packages/hal/mips/arch/current/ChangeLog
+++ b/packages/hal/mips/arch/current/ChangeLog
@@ -1,3 +1,21 @@
+2000-07-14  Drew Moseley  <dmoseley@redhat.com>
+
+	* src/vectors.S: Added hal_reset_vector_first_code and
+	hal_early_init macros.
+
+	* src/mips-stub.c (__install_breakpoints): Also install any
+	breakpoints in the list.
+
+	* include/mips-regs.h: Added a few new register definitions.
+
+	* include/hal_intr.h: Added CYGNUM_HAL_EXCEPTION_INTERRUPT.
+
+	* include/hal_arch.h: Added some macros for jumping between cached
+	and uncached.
+
+	* include/mips-stub.h: Renamed some enums to work around namespace
+	corruption.  Added breakpoint support in the HAL.
+
 2000-06-08  Jesper Skov  <jskov@redhat.com>
 
 	* src/hal_misc.c (hal_arch_default_isr): Removed what's now a
--- a/packages/hal/mips/arch/current/include/arch.inc
+++ b/packages/hal/mips/arch/current/include/arch.inc
@@ -34,7 +34,7 @@
 #######DESCRIPTIONBEGIN####
 ##
 ## Author(s): 	nickg
-## Contributors:	nickg
+## Contributors:	nickg, dmoseley
 ## Date:	1997-10-16
 ## Purpose:	Architecture definitions.
 ## Description:	This file contains various definitions and macros that are
@@ -59,7 +59,7 @@
 
 #if defined(CYG_HAL_STARTUP_RAM)
 # if defined(CYGPKG_HAL_MIPS_SIM) || !defined(CYGSEM_HAL_USE_ROM_MONITOR)
-#  define INITIAL_SR	0x1000ff00	/* CP0 usable, Ints enabled	*/
+#  define INITIAL_SR	0x1000ff00	/* CP0 usable, Ints enabled, master interrupt disable	*/
 # else
 #  define INITIAL_SR	0x1040ff00	/* as above + ROM vectors used	*/
 # endif	
@@ -152,6 +152,7 @@
 	
 	# Initialize CPU
 	.macro	hal_cpu_init
+
 	mtc0	zero,cause		# zero cause reg
 	nop
 	la	v0,INITIAL_SR		# initialize status register
--- a/packages/hal/mips/arch/current/include/hal_arch.h
+++ b/packages/hal/mips/arch/current/include/hal_arch.h
@@ -35,7 +35,7 @@
 //#####DESCRIPTIONBEGIN####
 //
 // Author(s):    nickg
-// Contributors: nickg
+// Contributors: nickg, dmoseley
 // Date:         1999-02-17
 // Purpose:      Define architecture abstractions
 // Usage:        #include <cyg/hal/hal_arch.h>
@@ -44,6 +44,7 @@
 //
 //==========================================================================
 
+#ifndef __ASSEMBLER__
 #include <pkgconf/hal.h>
 #include <cyg/infra/cyg_type.h>
 
@@ -195,6 +196,7 @@ externC void hal_thread_load_context( CY
 // happen if executed.
 // HAL_BREAKINST is the value of the breakpoint instruction and
 // HAL_BREAKINST_SIZE is its size in bytes.
+// HAL_BREAKINST_TYPE is the type.
 
 #define HAL_BREAKPOINT(_label_)                 \
 asm volatile (" .globl  " #_label_ ";"          \
@@ -206,6 +208,8 @@ asm volatile (" .globl  " #_label_ ";"  
 
 #define HAL_BREAKINST_SIZE      4
 
+#define HAL_BREAKINST_TYPE      cyg_uint32
+
 //--------------------------------------------------------------------------
 // Thread register state manipulation for GDB support.
 
@@ -368,6 +372,26 @@ externC void hal_idle_thread_action(cyg_
 
 #endif
 
+#endif /* __ASSEMBLER__ */
+
+// Convenience macros for accessing memory cached or uncached
+#define CYGARC_KSEG_MASK                               (0xE0000000)
+#define CYGARC_KSEG_CACHED                             (0x80000000)
+#define CYGARC_KSEG_UNCACHED                           (0xA0000000)
+#define CYGARC_KSEG_CACHED_BASE                        (0x80000000)
+#define CYGARC_KSEG_UNCACHED_BASE                      (0xA0000000)
+#define CYGARC_CACHED_ADDRESS(x)                       (((x) & ~CYGARC_KSEG_MASK) | CYGARC_KSEG_CACHED)
+#define CYGARC_UNCACHED_ADDRESS(x)                     (((x) & ~CYGARC_KSEG_MASK) | CYGARC_KSEG_UNCACHED)
+#define CYGARC_PHYSICAL_ADDRESS(x)                     ((x) & ~CYGARC_KSEG_MASK)
+#ifdef __ASSEMBLER__
+#define CYGARC_ADDRESS_REG_CACHED(reg)                 \
+        and     reg, reg, ~CYGARC_KSEG_MASK;           \
+        or      reg, reg, CYGARC_KSEG_CACHED
+#define CYGARC_ADDRESS_REG_UNCACHED(reg)               \
+        and     reg, reg, ~CYGARC_KSEG_MASK;           \
+        or      reg, reg, CYGARC_KSEG_UNCACHED
+#endif /* __ASSEMBLER__ */
+
 //--------------------------------------------------------------------------
 // Macros for switching context between two eCos instances (jump from
 // code in ROM to code in RAM or vice versa).
--- a/packages/hal/mips/arch/current/include/hal_intr.h
+++ b/packages/hal/mips/arch/current/include/hal_intr.h
@@ -128,6 +128,8 @@
 #define CYGNUM_HAL_EXCEPTION_OVERFLOW       CYGNUM_HAL_VECTOR_OVERFLOW
 #define CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO    CYGNUM_HAL_VECTOR_DIV_BY_ZERO
 
+#define CYGNUM_HAL_EXCEPTION_INTERRUPT      CYGNUM_HAL_VECTOR_BREAKPOINT
+
 // Min/Max exception numbers and how many there are
 #define CYGNUM_HAL_EXCEPTION_MIN                1
 #define CYGNUM_HAL_EXCEPTION_MAX                CYGNUM_HAL_VSR_MAX
--- a/packages/hal/mips/arch/current/include/mips-regs.h
+++ b/packages/hal/mips/arch/current/include/mips-regs.h
@@ -34,7 +34,7 @@
 //#####DESCRIPTIONBEGIN####
 //
 // Author(s):     Red Hat, nickg
-// Contributors:  Red Hat, nickg
+// Contributors:  Red Hat, nickg, dmoseley
 // Date:          1998-06-08
 // Purpose:       
 // Description:   Register defines for MIPS processors
@@ -62,6 +62,7 @@
 
 #define zero            $0
 #define at              $1              /* assembler temporary */
+#define atmp            $1              /* assembler temporary */
 #define v0              $2              /* value holders */
 #define v1              $3
 #define a0              $4              /* arguments */
@@ -97,6 +98,7 @@
 /* MIPS registers, numbered in the order in which gdb expects to see them. */
 #define ZERO            0
 #define AT              1
+#define ATMP            1
 #define V0              2
 #define V1              3
 #define A0              4
@@ -181,6 +183,8 @@
 #define C0_STATUS       $12             /* Processor Status */
 #define C0_CAUSE        $13             /* Exception Cause */
 #define C0_EPC          $14             /* Exception PC */
+#define C0_WATCHLO      $18             /* Watchpoint LO */
+#define C0_WATCHHI      $19             /* Watchpoint HI */
 #define C0_XCONTEXT     $20             /* XContext */
 #define C0_ECC          $26             /* ECC */
 #define C0_CACHEERR     $27             /* CacheErr */
--- a/packages/hal/mips/arch/current/include/mips-stub.h
+++ b/packages/hal/mips/arch/current/include/mips-stub.h
@@ -34,7 +34,7 @@
 //#####DESCRIPTIONBEGIN####
 //
 // Author(s):     Red Hat, nickg
-// Contributors:  Red Hat, nickg
+// Contributors:  Red Hat, nickg, dmoseley
 // Date:          1998-06-08
 // Purpose:       
 // Description:   MIPS-specific definitions for generic stub
@@ -65,13 +65,14 @@ extern "C" {
 #endif
 
 enum regnames {
-        ZERO,   AT,     V0,     V1,     A0,     A1,     A2,     A3,
-        T0,     T1,     T2,     T3,     T4,     T5,     T6,     T7,
-        S0,     S1,     S2,     S3,     S4,     S5,     S6,     S7,
-        T8,     T9,     K0,     K1,     GP,     SP,     S8,     RA,
-        SR,     LO,     HI,     BAD,    CAUSE,  PC,
-        CONFIG = 84,    CACHE,  DEBUG,  DEPC,   EPC
+        REG_ZERO,   REG_AT,     REG_V0,     REG_V1,     REG_A0,     REG_A1,     REG_A2,     REG_A3,
+        REG_T0,     REG_T1,     REG_T2,     REG_T3,     REG_T4,     REG_T5,     REG_T6,     REG_T7,
+        REG_S0,     REG_S1,     REG_S2,     REG_S3,     REG_S4,     REG_S5,     REG_S6,     REG_S7,
+        REG_T8,     REG_T9,     REG_K0,     REG_K1,     REG_GP,     REG_SP,     REG_S8,     REG_RA,
+        REG_SR,     REG_LO,     REG_HI,     REG_BAD,    REG_CAUSE,  REG_PC,
+        REG_CONFIG = 84,    REG_CACHE,  REG_DEBUG,  REG_DEPC,   REG_EPC
 };
+#define USE_LONG_NAMES_FOR_ENUM_REGNAMES
 
 typedef enum regnames regnames_t;
 
@@ -89,19 +90,26 @@ extern void put_register (regnames_t whi
 
 /* Set the currently-saved pc register value to PC. This also updates NPC
    as needed. */
+#if !defined(SET_PC_PROTOTYPE_EXISTS) && !defined(set_pc)
+#define SET_PC_PROTOTYPE_EXISTS
 extern void set_pc (target_register_t pc);
+#endif
 
 /* Set things up so that the next user resume will execute one instruction.
    This may be done by setting breakpoints or setting a single step flag
    in the saved user registers, for example. */
+#ifndef __single_step
 void __single_step (void);
+#endif
 
 /* Clear the single-step state. */
 void __clear_single_step (void);
 
 /* If the breakpoint we hit is in the breakpoint() instruction, return a
    non-zero value. */
+#ifndef __is_breakpoint_function
 extern int __is_breakpoint_function (void);
+#endif
 
 /* Skip the current instruction. */
 extern void __skipinst (void);
@@ -110,6 +118,10 @@ extern void __install_breakpoints (void)
 
 extern void __clear_breakpoints (void);
 
+extern void __install_breakpoint_list (void);
+
+extern void __clear_breakpoint_list (void);
+
 #ifdef __cplusplus
 }      /* extern "C" */
 #endif
--- a/packages/hal/mips/arch/current/src/context.S
+++ b/packages/hal/mips/arch/current/src/context.S
@@ -46,6 +46,10 @@
 
 #include <cyg/hal/arch.inc>
 
+#ifdef at
+#undef at
+#endif
+
 #------------------------------------------------------------------------------
 # hal_thread_switch_context
 # Switch thread contexts
--- a/packages/hal/mips/arch/current/src/mips-stub.c
+++ b/packages/hal/mips/arch/current/src/mips-stub.c
@@ -348,10 +348,14 @@ void __install_breakpoints ()
       __data_cache (CACHE_FLUSH) ;
       __instruction_cache (CACHE_FLUSH) ;
     }
+
+  /* Install the breakpoints in the breakpoint list */
+  __install_breakpoint_list();
 }
 
 void __clear_breakpoints (void)
 {
+  __clear_breakpoint_list();
 }
 
 
--- a/packages/hal/mips/arch/current/src/vectors.S
+++ b/packages/hal/mips/arch/current/src/vectors.S
@@ -32,7 +32,7 @@
 #######DESCRIPTIONBEGIN####
 ##
 ## Author(s): 	nickg
-## Contributors:	nickg
+## Contributors:	nickg, dmoseley
 ## Date:	1998-02-04
 ## Purpose:	MIPS exception vectors
 ## Description:	This file defines the code placed into the exception
@@ -52,7 +52,11 @@
 #endif
 			
 #include <cyg/hal/arch.inc>	
-			
+#include <cyg/hal/hal_arch.h>	
+	
+#ifdef at
+#undef at
+#endif
 	.extern cyg_instrument
 
 ##-----------------------------------------------------------------------------
@@ -67,6 +71,12 @@
 FUNC_START(reset_vector)
 
 #ifndef CYG_HAL_STARTUP_RAM
+#  if defined(CYGPKG_HAL_RESET_VECTOR_FIRST_CODE)
+	hal_reset_vector_first_code
+#  endif
+#  if defined(CYGPKG_HAL_EARLY_INIT)
+	hal_early_init
+#  endif
 	# Decide whether this is an NMI, cold or warm boot.
 
 	mfc0	k0,status		# get status reg
@@ -92,6 +102,7 @@ 2:
 	mtc0	k0,config0		# to disable cache
 #endif	
 	lar	v0,_start		# jump to start
+	CYGARC_ADDRESS_REG_UNCACHED(v0)
 	jr	v0
 	nop				# (delay slot)
 
--- a/packages/hal/powerpc/fads/current/ChangeLog
+++ b/packages/hal/powerpc/fads/current/ChangeLog
@@ -1,3 +1,8 @@
+2000-07-17  Jesper Skov  <jskov@redhat.com>
+
+	* src/hal_aux.c (hal_platform_init): Don't call hal_if_init just
+	yet.
+
 2000-06-26  Jesper Skov  <jskov@redhat.com>
 
 	* cdl/hal_powerpc_fads.cdl: Removed ROM_DEBUG_CHANNEL option.
--- a/packages/hal/powerpc/fads/current/src/hal_aux.c
+++ b/packages/hal/powerpc/fads/current/src/hal_aux.c
@@ -60,7 +60,9 @@ CYGARC_MEMDESC_TABLE CYGBLD_ATTRIB_WEAK 
 void
 hal_platform_init(void)
 {
+#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
     hal_if_init();
+#endif
 }
 
 // EOF hal_aux.c
--- a/packages/hal/sh/arch/current/ChangeLog
+++ b/packages/hal/sh/arch/current/ChangeLog
@@ -1,3 +1,24 @@
+2000-07-20  Jesper Skov  <jskov@redhat.com>
+
+	* src/sh_stub.c (__single_step): Skip trap instructions.
+
+2000-07-18  Gary Thomas  <gthomas@redhat.com>
+
+	* src/vectors.S (__reset): Change calculation of uncached startup
+	address.
+
+2000-07-17  Gary Thomas  <gthomas@redhat.com>
+
+	* src/hal_misc.c (cyg_hal_exception_handler): Handle exception caused by
+	GDB stubs memory accesses.
+
+2000-07-16  Gary Thomas  <gthomas@redhat.com>
+
+	* include/hal_intr.h: Define HAL_DELAY_US() - see below.
+
+	* src/hal_misc.c (hal_delay_us): New function.  Used in ROM/stand-alone
+	applications when there is no kernel.
+
 2000-06-30  Jesper Skov  <jskov@redhat.com>
 
 	* src/vectors.S (__reset): Jump to VMA for RAM startup.
--- a/packages/hal/sh/arch/current/include/hal_intr.h
+++ b/packages/hal/sh/arch/current/include/hal_intr.h
@@ -759,6 +759,9 @@ externC cyg_uint8 cyg_hal_ILVL_table[];
 #define HAL_CLOCK_LATENCY( _pvalue_ ) HAL_CLOCK_READ(_pvalue_)
 #endif
 
+extern void hal_delay_us(int);
+#define HAL_DELAY_US(n) hal_delay_us(n)
+
 #endif // __ASSEMBLER__
 
 //--------------------------------------------------------------------------
--- a/packages/hal/sh/arch/current/src/hal_misc.c
+++ b/packages/hal/sh/arch/current/src/hal_misc.c
@@ -51,7 +51,7 @@
 
 #include <cyg/hal/hal_arch.h>           // HAL header
 #include <cyg/hal/hal_cache.h>          // HAL cache
-#if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \
+#if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) || \
     defined(CYGPKG_HAL_EXCEPTIONS)
 # include <cyg/hal/hal_intr.h>           // HAL interrupts/exceptions
 #endif
@@ -95,11 +95,20 @@ cyg_hal_invoke_constructors (void)
 externC void __handle_exception (void);
 
 externC HAL_SavedRegisters *_hal_registers;
+#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
+externC volatile void *__mem_fault_handler;
+#endif
 
 void
 cyg_hal_exception_handler(HAL_SavedRegisters *regs)
 {
 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
+    if (__mem_fault_handler && 
+        ((regs->event >= CYGNUM_HAL_EXCEPTION_TLBMISS_ACCESS) &&
+         (regs->event <= CYGNUM_HAL_EXCEPTION_DATA_WRITE))) {
+        regs->pc = (unsigned long)__mem_fault_handler;
+        return; // Caught an exception inside stubs        
+    }
 
     // Set the pointer to the registers of the current exception
     // context. At entry the GDB stub will expand the
@@ -209,5 +218,33 @@ hal_variant_init(void)
 {
 }
 
+// Low-level delay (in microseconds)
+
+void
+hal_delay_us(int usecs)
+{
+    unsigned char _tstr;  // Current clock control
+    volatile unsigned char *tstr = (volatile unsigned char *)CYGARC_REG_TSTR;
+    volatile unsigned long *tcnt = (volatile unsigned long *)CYGARC_REG_TCNT1;
+    volatile unsigned long *tcor = (volatile unsigned long *)CYGARC_REG_TCOR1;
+    unsigned long clocks_per_us = (CYGHWR_HAL_SH_BOARD_SPEED+(4-1))/4;  // Rounded up
+    int diff, diff2;
+    cyg_uint32 val1, val2;
+
+    _tstr = *tstr;
+    *tstr |= CYGARC_REG_TSTR_STR1;  // Enable channel 1
+    while (usecs-- > 0) {
+        diff = 0;
+        while (diff < clocks_per_us) {
+            val1 = *tcnt;
+            while ((val2 = *tcnt) == val1) ;
+            diff2 = val2 - val1;
+            if (diff2 < 0) diff2 += *tcor;
+            diff += diff2;
+        }
+    }
+    *tstr = _tstr;                  // Restore timer to previous state
+}
+
 //---------------------------------------------------------------------------
 // End of hal_misc.c
--- a/packages/hal/sh/arch/current/src/sh_stub.c
+++ b/packages/hal/sh/arch/current/src/sh_stub.c
@@ -223,7 +223,7 @@ void __single_step (void)
     } else if (opcode == RTE_INSTR) {
         instrMem = (short *) get_register(SP);
     } else if ((opcode & TRAPA_MASK) == TRAPA_INSTR) {
-        instrMem = (short *) ((opcode & ~TRAPA_MASK) << 2);
+        instrMem += 1;                  // skip traps
     } else {
         instrMem += 1;
     }
--- a/packages/hal/sh/arch/current/src/vectors.S
+++ b/packages/hal/sh/arch/current/src/vectors.S
@@ -111,7 +111,7 @@
 #ifdef CYG_HAL_STARTUP_RAM
         .long   __reset_platform
 #else
-        .long   __reset_platform-__reset+0xA0000000
+        .long   __reset_platform+0x20000000  // Uncached "shadow" address
 #endif
                 
 #---------------------------------------------------------------------------
--- a/packages/hal/v85x/arch/current/ChangeLog
+++ b/packages/hal/v85x/arch/current/ChangeLog
@@ -1,3 +1,8 @@
+2000-07-21  Gary Thomas  <gthomas@redhat.com>
+
+	* src/vectors.S (_hal_plf_reset_board): Needs to be defined in all
+	configurations.
+
 2000-06-27  Jesper Skov  <jskov@redhat.com>
 
 	* src/vectors.S:
--- a/packages/hal/v85x/arch/current/src/vectors.S
+++ b/packages/hal/v85x/arch/current/src/vectors.S
@@ -446,7 +446,6 @@ 10:
 call_via_r1:    
         jmp     [r1]
                                         
-#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
 //
 // Reset the board
 //
@@ -454,7 +453,6 @@ call_via_r1:
 _hal_plf_reset_board:   
         di                      // Turn off interrupts
         jmp     [r0]            // Restart machine        
-#endif
 
 #if !defined(CYGSEM_HAL_NEC_INLINE_INTERRUPT_FUNCTIONS)
         .globl  _hal_disable_interrupts
--- a/packages/infra/current/ChangeLog
+++ b/packages/infra/current/ChangeLog
@@ -1,3 +1,10 @@
+2000-07-18  Jonathan Larmour  <jlarmour@redhat.co.uk>
+
+	* src/buffer.cxx (increment_buffer_pos): Reset buffer pos *before*
+	we try to print the buffer
+	Thanks to Chris Morrow (cmorrow at YottaYotta.com ) for spotting
+	the problem.
+
 2000-04-12  Jesper Skov  <jskov@redhat.com>
 
 	* cdl/infra.cdl: Allow build flags to be tweaked.
--- a/packages/infra/current/src/buffer.cxx
+++ b/packages/infra/current/src/buffer.cxx
@@ -374,11 +374,10 @@ static void increment_buffer_pos()
 #elif defined(CYGDBG_INFRA_DEBUG_TRACE_BUFFER_HALT)
         cyg_infra_trace_buffer_enable = false;
 #elif defined(CYGDBG_INFRA_DEBUG_TRACE_BUFFER_PRINT)
+        cyg_infra_trace_buffer_pos = 0;
         print_trace_buffer();
-        cyg_infra_trace_buffer_pos = 0;
-        cyg_infra_trace_buffer_wrap = false;
-#else        
-#error No trace buffer full mode set        
+#else
+#error No trace buffer full mode set
 #endif
     }
 
--- a/packages/kernel/current/ChangeLog
+++ b/packages/kernel/current/ChangeLog
@@ -1,3 +1,10 @@
+2000-07-17  Gary Thomas  <gthomas@redhat.com>
+
+	* tests/kflag1.c (FIRST_THREAD_WAIT_TIME): Parameterize thread 
+	synchronization wait times (for understanding) and adjust for
+	incredibly slow platforms.  [Previous value allowed for the test
+	to get out of sync because the code ran so slowly]
+
 2000-06-23  Hugo Tyson  <hmt@cygnus.co.uk>
 
 	* include/kapi.h (cyg_scheduler_read_lock): New function, to
--- a/packages/kernel/current/tests/kflag1.c
+++ b/packages/kernel/current/tests/kflag1.c
@@ -63,6 +63,9 @@ static cyg_flag_t f2;
 #endif
 
 static volatile cyg_ucount8 q = 0;
+#define FIRST_THREAD_WAIT_TIME   5
+#define SECOND_THREAD_WAIT_TIME 10
+#define THIRD_THREAD_WAIT_TIME  20
 
 static void entry0( cyg_addrword_t data )
 {
@@ -98,7 +101,7 @@ static void entry0( cyg_addrword_t data 
     cyg_flag_wait( &f2, 0x2, CYG_FLAG_WAITMODE_OR);    
     CYG_TEST_CHECK(20==q,"bad synchronization");
     cyg_flag_timed_wait( &f2, 0x10, CYG_FLAG_WAITMODE_AND,
-                         cyg_current_time()+20);
+                         cyg_current_time()+THIRD_THREAD_WAIT_TIME);
     CYG_TEST_CHECK(21==q++,"bad synchronization");
 #endif
     cyg_flag_wait( &f0, 1, CYG_FLAG_WAITMODE_OR);
@@ -159,7 +162,7 @@ static void entry1( cyg_addrword_t data 
     cyg_flag_setbits( &f2, 0x2);                    // synchronize with t0,t2
     CYG_TEST_CHECK(20==q,"bad synchronization");
     cyg_flag_timed_wait( &f2, 0x20, CYG_FLAG_WAITMODE_AND,
-                         cyg_current_time()+10);
+                         cyg_current_time()+SECOND_THREAD_WAIT_TIME);
     CYG_TEST_CHECK(22==q++,"bad synchronization");
 #endif
 
@@ -176,7 +179,7 @@ static void entry2( cyg_addrword_t data 
     cyg_flag_wait( &f2, 0x2, CYG_FLAG_WAITMODE_OR);
     CYG_TEST_CHECK(20==q,"bad synchronization");
     CYG_TEST_CHECK(0==cyg_flag_timed_wait( &f2, 0x40, CYG_FLAG_WAITMODE_AND,
-                                           cyg_current_time()+2),
+                                           cyg_current_time()+FIRST_THREAD_WAIT_TIME),
                    "timed wait() wrong");
     CYG_TEST_CHECK(20==q++,"bad synchronization");
     // Now wake t0 before it times out
--- a/packages/net/drivers/eth/common/current/ChangeLog
+++ b/packages/net/drivers/eth/common/current/ChangeLog
@@ -1,3 +1,8 @@
+2000-07-15  Gary Thomas  <gthomas@redhat.com>
+
+	* include/eth_drv.h: Add [initial] extensions to let this
+	layer work either in an eCos environment or stand-alone.
+
 2000-06-23  Hugo Tyson  <hmt@cygnus.co.uk>
 
 	* src/eth_drv.c (eth_drv_send): Do not consume an SG entry for
--- a/packages/net/drivers/eth/common/current/include/eth_drv.h
+++ b/packages/net/drivers/eth/common/current/include/eth_drv.h
@@ -45,7 +45,7 @@
 // Contributors: gthomas
 // Date:         2000-01-10
 // Purpose:      
-// Description:  
+// Description:  High level networking driver interfaces
 //              
 //
 //####DESCRIPTIONEND####
@@ -57,6 +57,9 @@
 #ifndef _ETH_DRV_H_
 #define _ETH_DRV_H_
 
+#include <pkgconf/system.h>
+
+#ifdef CYGPKG_NET
 #include <sys/param.h>
 #include <sys/socket.h>
 
@@ -74,6 +77,7 @@
 #include <net/bpf.h>
 #include <net/bpfdesc.h>
 #endif
+#endif
 
 struct eth_drv_sg {
     CYG_ADDRESS  buf;
@@ -110,8 +114,16 @@ struct eth_drv_funs {
     void (*recv)(struct eth_drv_sc *sc,
                  struct eth_drv_sg *sg_list,
                  int sg_len);
+    // Poll for interrupts/device service
+    void (*poll)(struct eth_drv_sc *sc);
 };
 
+#ifndef CYGPKG_NET
+struct arpcom {
+    unsigned char esa[6];
+};
+#endif
+
 struct eth_drv_sc {
     struct eth_drv_funs *funs;
     void                *driver_private;
@@ -119,21 +131,27 @@ struct eth_drv_sc {
     struct arpcom       sc_arpcom; /* ethernet common */
 };
 
-#define ETH_DRV_SC(sc,priv,name,start,stop,control,can_send,send,recv) \
+#define ETH_DRV_SC(sc,priv,name,start,stop,control,can_send,send,recv,poll) \
 static void start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags); \
 static void stop(struct eth_drv_sc *sc); \
 static int  control(struct eth_drv_sc *sc, unsigned long key, void *data, int data_length); \
 static int  can_send(struct eth_drv_sc *sc); \
 static void send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int total, unsigned long key); \
 static void recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len); \
-static struct eth_drv_funs sc##_funs = {start, stop, control, can_send, send, recv}; \
+static void poll(struct eth_drv_sc *sc); \
+static struct eth_drv_funs sc##_funs = {start, stop, control, can_send, send, recv, poll}; \
 struct eth_drv_sc sc = {&sc##_funs, priv, name};
 
 void eth_drv_init(struct eth_drv_sc *sc, unsigned char *enaddr);
 void eth_drv_recv(struct eth_drv_sc *sc, int total_len);
 void eth_drv_tx_done(struct eth_drv_sc *sc, unsigned long key, int status);
 
+
 // Control 'key's
 #define ETH_DRV_SET_MAC_ADDRESS 0x0100
 
+#ifndef ETHER_ADDR_LEN
+#define ETHER_ADDR_LEN 6
+#endif
+
 #endif // _ETH_DRV_H_
--- a/packages/net/tcpip/current/ChangeLog
+++ b/packages/net/tcpip/current/ChangeLog
@@ -1,3 +1,113 @@
+2000-07-21  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* src/sys/net/if_bridge.c: Move the include of stdio.h lower,
+	apparently it confuses local x86 compilers if their host tree is
+	malformed.  Or something.
+
+2000-07-21  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* cdl/net.cdl: Add a lot of description about the way the various
+	fields are used in interface initialization: specifically that
+	"server" so-called is just "someone to talk to" in the absence of
+	bootp - and our tests depend on it!
+
+	* src/lib/bootp_support.c (init_net): Only set up a route if the
+	route address is nonzero - or all manner of confusion occurs with
+	multiple interfaces and route that sends to 0.0.0.0...
+	For setting up the default route, use
+	      (SIOCADDRT, 0, 0, TAG_GATEWAY)
+	rather than the bogus
+	      (SIOCADDRT, yiaddr & netmask, netmask, TAG_GATEWAY)
+	that we did before.
+
+	* tests/ftp_test.c (ftp_test): Try it with eth1 if available also.
+
+	* tests/ping_test.c (ping_host): If a ping fails, reset the packet
+	size to small just in case the huge packet size is what's causing
+	confusion - helps it as a debug tool.
+
+	* tests/dhcp_test.c (net_test): It didn't compile if DHCP is
+	disabled!  Doh.  Same change as ping_test also.
+
+2000-07-19  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* src/lib/tftp_server.c (tftpd_read_file): Deal with a) [assumed]
+	timeouts on the select, and b) ACKs for old packets.
+	[CASE 104052 and CASE 104055]
+
+2000-07-19  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* src/lib/select.c (_cyg_select): Return 0 and do not perturb
+	errno when the timeout occurs.  That matches the man page!
+	[CASE 104054]
+
+2000-07-19  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* include/machine/param.h: Be more defensive against warnings from
+	external defines such as __linux__/__bsdi__/__FreeBSD__/...
+	[CASE 104090]
+
+2000-07-19  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* tests/multi_lo_select.c: New test program to test for proper
+	broadcast behaviour of select() implementation.  Took some
+	fiddling to get it to work, but it really did fail before the
+	select change below.
+
+	* cdl/net.cdl: Build the new test.
+
+	* src/lib/select.c (_cyg_select): Don't use the CLR flag in the
+	flag wait because that gives unicast semantics.  Flags have
+	producer-does-all-the-work behaviour, so setting a value then
+	clearing it right afterwards does the right thing, with broadcast
+	semantics so long as no waiter has set the CLR part.
+	[CASE 104058]
+
+2000-07-18  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	All part of the bridge contribution from Andrew Lunn/ASCOM
+	(andrew.lunn@ascom.ch).  Bridginess is controlled by NBRIDGE which
+	is itself controlled by CDL option CYGPKG_NET_NBRIDGE aka "Number
+	of bridge buffers?"
+
+	* include/machine/param.h: Add proper definition of untimeout().
+
+	* include/sys/sockio.h (SIOCBRDGFRL): Add this and the other 2
+	bridge ioctl() call definitions. 
+
+	* include/sys/param.h (splhigh): Added.
+
+	* src/ecos/timeout.c (untimeout): Implement this properly, it was
+	never used before.
+
+	* src/ecos/support.c: implement cyg_splhigh(), call bridgeintr()
+	when it is scheduled and bridgeattach() if configured.
+
+	* tests/bridge.c: New "test" file - implements an ethernet bridge.
+	Contributed by Andrew Lunn/ASCOM, from the usual OpenBSD external
+	source original.
+
+	* include/net/if_bridge.h: New file, contributed by Andrew Lunn/
+	ASCOM, from OpenBSD original.  (Actually did exist in eCos source
+	tree but was not released)
+
+	* src/sys/net/if_bridge.c: New file, contributed by Andrew Lunn/
+	ASCOM, from OpenBSD original.
+
+	* cdl/net.cdl: Build the new files.
+
+2000-07-18  Gary Thomas  <gthomas@redhat.com>
+
+	* src/lib/tftp_client.c (tftp_get): Fix edge condition when 
+	penultimate block is full and end of file which implies that
+	the last block has zero data bytes.
+
+2000-07-18  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* src/lib/dhcp_prot.c: Ignore NAK messages from the wrong server -
+	we get these because the REQUEST for our chosen IP is broadcast,
+	so other servers think we've asked to use the wrong IP.
+
 2000-07-14  Hugo Tyson  <hmt@cygnus.co.uk>
 
 	* include/bootp.h: export init_loopback_interface();
--- a/packages/net/tcpip/current/cdl/net.cdl
+++ b/packages/net/tcpip/current/cdl/net.cdl
@@ -68,6 +68,7 @@ cdl_package CYGPKG_NET {
 	sys/net/radix.c \
 	sys/net/if_ethersubr.c \
 	sys/net/if_loop.c \
+	sys/net/if_bridge.c \
 	sys/netinet/igmp.c \
 	sys/netinet/raw_ip.c \
 	sys/netinet/in.c  \
@@ -262,7 +263,9 @@ cdl_package CYGPKG_NET {
         flavor  data
         default_value 0
         description   "
-            This option controls the number of bridge buffers."
+            This option controls the number of bridge buffers and indeed
+	    whether bridging code is enabled at all via 'standard'
+	    symbol NBRIDGE."
         define_proc {
             puts $::cdl_header "#define NBRIDGE CYGPKG_NET_NBRIDGE"
         }
@@ -362,17 +365,20 @@ cdl_package CYGPKG_NET {
 		    tests/tftp_server_test \
 		    tests/tcp_echo \
 		    tests/set_mac_address \
+		    tests/bridge \
 		    tests/flood \
 		    tests/ping_test \
 		    tests/dhcp_test \
 		    tests/ping_lo_test \
 		    tests/tcp_lo_test \
 		    tests/udp_lo_test \
+		    tests/multi_lo_select \
 		    tests/tcp_lo_select"
 	    :
 	            "tests/ping_lo_test \
 		    tests/tcp_lo_test \
 		    tests/udp_lo_test \
+		    tests/multi_lo_select \
 		    tests/tcp_lo_select"
 	}
 	    description   "
@@ -422,13 +428,23 @@ cdl_package CYGPKG_NET {
         cdl_component CYGHWR_NET_DRIVER_ETH0_MANUAL {
             display "Initialize 'eth0' manually?"
             default_value 0
-            implements CYGHWR_NET_DRIVER_ETH0_SETUP	
+            implements CYGHWR_NET_DRIVER_ETH0_SETUP
+	    description "
+	        If this option is selected, the eCos library provides no
+	        initialization code for this interface; you must perform
+	        all the initialization in the application, by means of
+	        appropriate ioctl() calls, or by calling init_net() with an
+	        appropriate bootp record you have constructed yourself."
         }
 
         cdl_component CYGHWR_NET_DRIVER_ETH0_BOOTP {
             display "Use BOOTP/DHCP to initialize 'eth0'?"
             default_value 1
             implements CYGHWR_NET_DRIVER_ETH0_SETUP	
+	    description "
+	        If this option is selected, init_all_network_interfaces()
+	        will use DHCP or BOOTP to acquire initialization data for
+	        this interface, and then set it up accordingly."
 
             cdl_option CYGHWR_NET_DRIVER_ETH0_DHCP {
                 display "Use DHCP rather than BOOTP for 'eth0'?"
@@ -449,6 +465,29 @@ cdl_package CYGPKG_NET {
             implements CYGHWR_NET_DRIVER_ETH0_SETUP	
             no_define
 
+	    description "
+	        These options let you configure all the initialization data
+	        that init_all_network_interfaces() will use
+	        for 'eth0' statically.  Be careful when doing this, because
+	        if you run the same application image on multiple boards,
+	        they will have identical IP addresses and so on; this is a
+	        Bad Thing.
+	        The values you set are inserted in a bootp-style record
+	        that is fed into a common setup routine to configure the
+	        interface.  That routine does not in fact use the 'Server
+	        IP address' field.
+	        The bootp record is also available to application code, and
+	        some eCos networking test programs use the 'Server IP
+	        address' field to mean 'a machine we can interact with' for
+	        example to ping or perform ftp with.  That is the rationale
+	        for its inclusion here.
+	        The gateway address is used to set up a default route if
+	        nonzero.  If you have more than one interface, setting up
+	        more than one default route is will cause malfunctions.  A
+	        gateway address of 0.0.0.0 can be set to prevent that route
+	        setup.  Of course, your application can add real routes
+	        once the interface(s) initialization is complete."
+
             cdl_option CYGHWR_NET_DRIVER_ETH0_ADDRS_IP {
                 display "IP address for 'eth0'"
                 flavor  data
@@ -470,7 +509,7 @@ cdl_package CYGPKG_NET {
             cdl_option CYGHWR_NET_DRIVER_ETH0_ADDRS_GATEWAY {
                 display "Gateway/router IP address for 'eth0'"
                 flavor  data
-                default_value { "192.168.1.101" }
+                default_value { "192.168.1.1" }
             }
 
             cdl_option CYGHWR_NET_DRIVER_ETH0_ADDRS_SERVER {
@@ -501,12 +540,22 @@ cdl_package CYGPKG_NET {
             display "Initialize 'eth1' manually?"
             default_value 0
             implements CYGHWR_NET_DRIVER_ETH1_SETUP	
+	    description "
+	        If this option is selected, the eCos library provides no
+	        initialization code for this interface; you must perform
+	        all the initialization in the application, by means of
+	        appropriate ioctl() calls, or by calling init_net() with an
+	        appropriate bootp record you have constructed yourself."
         }
 
         cdl_component CYGHWR_NET_DRIVER_ETH1_BOOTP {
             display "Use BOOTP/DHCP to initialize 'eth1'?"
             default_value 1
             implements CYGHWR_NET_DRIVER_ETH1_SETUP	
+	    description "
+	        If this option is selected, init_all_network_interfaces()
+	        will use DHCP or BOOTP to acquire initialization data for
+	        this interface, and then set it up accordingly."
 
             cdl_option CYGHWR_NET_DRIVER_ETH1_DHCP {
                 display "Use DHCP rather than BOOTP for 'eth1'?"
@@ -527,6 +576,31 @@ cdl_package CYGPKG_NET {
             implements CYGHWR_NET_DRIVER_ETH1_SETUP	
             no_define
 
+	    description "
+	        These options let you configure all the initialization data
+	        that init_all_network_interfaces() will use
+	        for 'eth1' statically.  Be careful when doing this, because
+	        if you run the same application image on multiple boards,
+	        they will have identical IP addresses and so on; this is a
+	        Bad Thing.
+	        The values you set are inserted in a bootp-style record
+	        that is fed into a common setup routine to configure the
+	        interface.  That routine does not in fact use the 'Server
+	        IP address' field.
+	        The bootp record is also available to application code, and
+	        some eCos networking test programs use the 'Server IP
+	        address' field to mean 'a machine we can interact with' for
+	        example to ping or perform ftp with.  That is the rationale
+	        for its inclusion here.
+	        The gateway address is used to set up a default route if
+	        nonzero.  If you have more than one interface, setting up
+	        more than one default route is will cause malfunctions.  A
+	        gateway address of 0.0.0.0 can be set to prevent that route
+	        setup.  Of course, your application can add real routes
+	        once the interface(s) initialization is complete.
+	        This interface 'eth1' has no route set up in the default
+	        configuration."
+
             cdl_option CYGHWR_NET_DRIVER_ETH1_ADDRS_IP {
                 display "IP address for 'eth1'"
                 flavor  data
@@ -548,7 +622,7 @@ cdl_package CYGPKG_NET {
             cdl_option CYGHWR_NET_DRIVER_ETH1_ADDRS_GATEWAY {
                 display "Gateway/router IP address for 'eth1'"
                 flavor  data
-                default_value { "192.168.1.101" }
+                default_value { "0.0.0.0" }
             }
 
             cdl_option CYGHWR_NET_DRIVER_ETH1_ADDRS_SERVER {
--- a/packages/net/tcpip/current/include/machine/param.h
+++ b/packages/net/tcpip/current/include/machine/param.h
@@ -80,6 +80,24 @@
 #define ALIGN(p)        (((u_int)(p) + ALIGNBYTES) &~ ALIGNBYTES)
 
 // These symbols are used in the IPV6 stuff
+// (be more defensive about external setup)
+#ifdef __linux__
+#undef __linux__
+#endif
+#ifdef __bsdi__
+#undef __bsdi__
+#endif
+#ifdef __FreeBSD__
+#undef __FreeBSD__
+#endif
+#ifdef __OpenBSD__
+#undef __OpenBSD__
+#endif
+#ifdef __NetBSD__
+#undef __NetBSD__
+#endif
+
+
 #define __linux__   0
 #define __bsdi__    0
 #define __FreeBSD__ 0
@@ -127,7 +145,7 @@ struct net_stats {
 // timeout support
 typedef void (timeout_fun)(void *);
 extern cyg_uint32 timeout(timeout_fun *fun, void *arg, cyg_int32 delta);
-
+extern void untimeout(timeout_fun *fun, void *arg);
 extern int uiomove(caddr_t cp, int n, struct uio *uio);
 extern int copyout(const void *s, void *d, size_t len);
 extern int copyin(const void *s, void *d, size_t len);
new file mode 100644
--- /dev/null
+++ b/packages/net/tcpip/current/include/net/if_bridge.h
@@ -0,0 +1,197 @@
+//==========================================================================
+//
+//      include/net/if_bridge.h
+//
+//     
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//####BSDCOPYRIGHTBEGIN####
+//
+// -------------------------------------------
+//
+// Portions of this software may have been derived from OpenBSD or other sources,
+// and are covered by the appropriate copyright disclaimers included herein.
+//
+// -------------------------------------------
+//
+//####BSDCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Jason L. Wright (jason@thought.net)
+// Contributors: andrew.lunn@ascom.ch (Andrew Lunn), hmt
+// Date:         2000-07-18
+// Purpose:      Ethernet bridge
+// Description:  
+//              
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+
+/*	$OpenBSD: if_bridge.h,v 1.12 2000/01/25 22:06:27 jason Exp $	*/
+
+/*
+ * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
+ * 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 Jason L. Wright
+ * 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.
+ */
+
+/*
+ * Bridge control request: add/delete member interfaces.
+ */
+struct ifbreq {
+	char		ifbr_name[IFNAMSIZ];	/* bridge ifs name */
+	char		ifbr_ifsname[IFNAMSIZ];	/* member ifs name */
+	u_int32_t	ifbr_ifsflags;		/* member ifs flags */
+};
+/* SIOCBRDGIFFLGS, SIOCBRDGIFFLGS */
+#define	IFBIF_LEARNING	0x1	/* ifs can learn */
+#define	IFBIF_DISCOVER	0x2	/* ifs sends packets w/unknown dest */
+#define IFBIF_BLOCKNONIP 0x04	/* ifs blocks non-IP/ARP traffic in/out */
+/* SIOCBRDGFLUSH */
+#define	IFBF_FLUSHDYN	0x0	/* flush dynamic addresses only */
+#define	IFBF_FLUSHALL	0x1	/* flush all addresses from cache */
+
+/*
+ * Interface list structure
+ */
+struct ifbifconf {
+	char		ifbic_name[IFNAMSIZ];	/* bridge ifs name */
+	u_int32_t	ifbic_len;		/* buffer size */
+	union {
+		caddr_t	ifbicu_buf;
+		struct	ifbreq *ifbicu_req;
+	} ifbic_ifbicu;
+#define	ifbic_buf	ifbic_ifbicu.ifbicu_buf
+#define	ifbic_req	ifbic_ifbicu.ifbicu_req
+};
+
+/*
+ * Bridge address request
+ */
+struct ifbareq {
+	char			ifba_name[IFNAMSIZ];	/* bridge name */
+	char			ifba_ifsname[IFNAMSIZ];	/* destination ifs */
+	u_int8_t		ifba_age;		/* address age */
+	u_int8_t		ifba_flags;		/* address flags */
+	struct ether_addr	ifba_dst;		/* destination addr */
+};
+
+#define	IFBAF_TYPEMASK		0x03		/* address type mask */
+#define	IFBAF_DYNAMIC		0x00		/* dynamically learned */
+#define	IFBAF_STATIC		0x01		/* static address */
+
+struct ifbaconf {
+	char			ifbac_name[IFNAMSIZ];	/* bridge ifs name */
+	u_int32_t		ifbac_len;		/* buffer size */
+	union {
+		caddr_t	ifbacu_buf;			/* buffer */
+		struct ifbareq *ifbacu_req;		/* request pointer */
+	} ifbac_ifbacu;
+#define	ifbac_buf	ifbac_ifbacu.ifbacu_buf
+#define	ifbac_req	ifbac_ifbacu.ifbacu_req
+};
+
+/*
+ * Bridge cache size get/set
+ */
+struct ifbcachereq {
+	char			ifbc_name[IFNAMSIZ];	/* bridge ifs name */
+	u_int32_t		ifbc_size;		/* cache size */
+};
+
+/*
+ * Bridge cache timeout get/set
+ */
+struct ifbcachetoreq {
+	char			ifbct_name[IFNAMSIZ];	/* bridge ifs name */
+	u_int32_t		ifbct_time;		/* cache time (sec) */
+};
+
+/*
+ * Bridge mac rules
+ */
+struct ifbrlreq {
+	char			ifbr_name[IFNAMSIZ];	/* bridge ifs name */
+	char			ifbr_ifsname[IFNAMSIZ];	/* member ifs name */
+	u_int8_t		ifbr_action;		/* disposition */
+	u_int8_t		ifbr_flags;		/* flags */
+	struct ether_addr	ifbr_src;		/* source mac */
+	struct ether_addr	ifbr_dst;		/* destination mac */
+};
+#define	BRL_ACTION_BLOCK	0x01			/* block frame */
+#define	BRL_ACTION_PASS		0x02			/* pass frame */
+#define	BRL_FLAG_IN		0x08			/* input rule */
+#define	BRL_FLAG_OUT		0x04			/* output rule */
+#define	BRL_FLAG_SRCVALID	0x02			/* src valid */
+#define	BRL_FLAG_DSTVALID	0x01			/* dst valid */
+
+struct ifbrlconf {
+	char		ifbrl_name[IFNAMSIZ];	/* bridge ifs name */
+	char		ifbrl_ifsname[IFNAMSIZ];/* member ifs name */
+	u_int32_t	ifbrl_len;		/* buffer size */
+	union {
+		caddr_t	ifbrlu_buf;
+		struct	ifbrlreq *ifbrlu_req;
+	} ifbrl_ifbrlu;
+#define	ifbrl_buf	ifbrl_ifbrlu.ifbrlu_buf
+#define	ifbrl_req	ifbrl_ifbrlu.ifbrlu_req
+};
+
+#ifdef _KERNEL
+void	bridge_ifdetach __P((struct ifnet *));
+struct mbuf *bridge_input __P((struct ifnet *, struct ether_header *,
+    struct mbuf *));
+int	bridge_output __P((struct ifnet *, struct mbuf *, struct sockaddr *,
+    struct rtentry *rt));
+#endif /* _KERNEL */
--- a/packages/net/tcpip/current/include/sys/param.h
+++ b/packages/net/tcpip/current/include/sys/param.h
@@ -349,11 +349,13 @@ extern cyg_uint32  cyg_splimp(void);
 extern cyg_uint32  cyg_splnet(void);
 extern cyg_uint32  cyg_splclock(void);
 extern cyg_uint32  cyg_splsoftnet(void);
+extern cyg_uint32  cyg_splhigh(void);
 extern void        cyg_splx(cyg_uint32);
 #define splimp     cyg_splimp
 #define splnet     cyg_splnet
 #define splclock   cyg_splclock
 #define splsoftnet cyg_splsoftnet
+#define splhigh    cyg_splhigh
 #define splx       cyg_splx
 #endif
 
--- a/packages/net/tcpip/current/include/sys/sockio.h
+++ b/packages/net/tcpip/current/include/sys/sockio.h
@@ -171,6 +171,10 @@
 #define	SIOCBRDGDADDR	_IOWR('i', 71, struct ifbareq)	/* delete addr */
 #define	SIOCBRDGFLUSH	_IOWR('i', 72, struct ifbreq)	/* flush addr cache */
 
+#define SIOCBRDGARL     _IOWR('i', 77, struct ifbrlreq) /* add bridge rule */
+#define SIOCBRDGFRL     _IOWR('i', 78, struct ifbrlreq) /* flush brdg rules */
+#define SIOCBRDGGRL     _IOWR('i', 79, struct ifbrlconf)/* get bridge rules */
+
 #define	SIOCSIFMTU	 _IOW('i', 127, struct ifreq)	/* set ifnet mtu */
 #define	SIOCGIFMTU	_IOWR('i', 126, struct ifreq)	/* get ifnet mtu */
 #define	SIOCSIFASYNCMAP  _IOW('i', 125, struct ifreq)	/* set ppp asyncmap */
--- a/packages/net/tcpip/current/src/ecos/support.c
+++ b/packages/net/tcpip/current/src/ecos/support.c
@@ -203,6 +203,21 @@ cyg_splnet(void)
     return old_ints;
 }
 
+cyg_uint32
+#ifdef CYGIMPL_TRACE_SPLX   
+cyg_splhigh(const char *file, const int line)
+#else
+cyg_splhigh(void)
+#endif
+{
+    // splhigh did SPLSOFTNET in the contrib, so this is the same
+    return cyg_splsoftnet(
+#ifdef CYGIMPL_TRACE_SPLX   
+        file, line
+#endif
+        );
+}
+
 //
 // Prevent all other stack processing, including interrupts (DSRs), etc.
 //
@@ -734,6 +749,12 @@ cyg_netint(cyg_addrword_t param)
             ip6intr();
         }
 #endif
+#if NBRIDGE > 0
+        if (curisr & (1 << NETISR_BRIDGE)) {
+            // Pending bridge input
+            bridgeintr();
+        }
+#endif
         splx(s);
     }
 }
@@ -746,6 +767,7 @@ cyg_netint(cyg_addrword_t param)
 extern void cyg_do_net_init(void);  // Linker magic to execute this function as 'init'
 extern void ifinit(void);
 extern void loopattach(int);
+extern void bridgeattach(int);
 
 void
 cyg_net_init(void)
@@ -796,6 +818,9 @@ cyg_net_init(void)
     loopattach(0);
 #endif
 #endif
+#if NBRIDGE > 0
+    bridgeattach(0);
+#endif
     // Start up the network processing
     ifinit();
     domaininit();
--- a/packages/net/tcpip/current/src/ecos/timeout.c
+++ b/packages/net/tcpip/current/src/ecos/timeout.c
@@ -131,14 +131,17 @@ timeout(timeout_fun *fun, void *arg, cyg
 }
 
 void
-untimeout(cyg_uint32 stamp)
+untimeout(timeout_fun *fun, void * arg)
 {
-    if (stamp != 0) {
-        timeout_entry *e = (timeout_entry *)stamp;
-        if (e->fun != 0) {
+  int i;
+  timeout_entry *e = timeouts;
+
+  for (i = 0; i < NTIMEOUTS; i++, e++) {
+    if (e->delta && (e->fun == fun) && (e->arg == arg)) {
             e->delta = 0;
             e->fun = 0;
-            e->arg = 0;
+      return;
         }
     }
 }
+
--- a/packages/net/tcpip/current/src/lib/bootp_support.c
+++ b/packages/net/tcpip/current/src/lib/bootp_support.c
@@ -454,27 +454,33 @@ init_net(const char *intf, struct bootp 
 
     // Set up routing
     if (get_bootp_option(bp, TAG_GATEWAY, &gateway)) {
-        memset(&route, 0, sizeof(route));
-        addrp->sin_family = AF_INET;
-        addrp->sin_port = 0;
-        addrp->sin_addr.s_addr = *(unsigned int *)&bp->bp_yiaddr & *(unsigned int *)&netmask;
-        memcpy(&route.rt_dst, addrp, sizeof(*addrp));
-        addrp->sin_addr = netmask;
-        memcpy(&route.rt_genmask, addrp, sizeof(*addrp));
-        addrp->sin_addr = gateway;
-        memcpy(&route.rt_gateway, addrp, sizeof(*addrp));
+        // ...and it's a nonzero address...
+        if ( 0 != gateway.s_addr ) {
+            memset(&route, 0, sizeof(route));
+            addrp->sin_family = AF_INET;
+            addrp->sin_port = 0;
+            addrp->sin_addr.s_addr = 0; // Use 0,0,GATEWAY for the default route
+            memcpy(&route.rt_dst, addrp, sizeof(*addrp));
+            addrp->sin_addr.s_addr = 0;
+            memcpy(&route.rt_genmask, addrp, sizeof(*addrp));
+            addrp->sin_addr = gateway;
+            memcpy(&route.rt_gateway, addrp, sizeof(*addrp));
 
-        route.rt_dev = ifr.ifr_name;
-        route.rt_flags = RTF_UP|RTF_GATEWAY;
-        route.rt_metric = 0;
+            route.rt_dev = ifr.ifr_name;
+            route.rt_flags = RTF_UP|RTF_GATEWAY;
+            route.rt_metric = 0;
 
-        if (ioctl(s, SIOCADDRT, &route)) {
-            diag_printf("Route - dst: %s", inet_ntoa(((struct sockaddr_in *)&route.rt_dst)->sin_addr));
-            diag_printf(", mask: %s", inet_ntoa(((struct sockaddr_in *)&route.rt_genmask)->sin_addr));
-            diag_printf(", gateway: %s\n", inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr));
-            if (errno != EEXIST) {
-                perror("SIOCADDRT 3");
-                return false;
+            if (ioctl(s, SIOCADDRT, &route)) {
+                diag_printf("Route - dst: %s",
+                  inet_ntoa(((struct sockaddr_in *)&route.rt_dst)->sin_addr));
+                diag_printf(", mask: %s",
+                  inet_ntoa(((struct sockaddr_in *)&route.rt_genmask)->sin_addr));
+                diag_printf(", gateway: %s\n",
+                  inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr));
+                if (errno != EEXIST) {
+                    perror("SIOCADDRT 3");
+                    return false;
+                }
             }
         }
     }
--- a/packages/net/tcpip/current/src/lib/dhcp_prot.c
+++ b/packages/net/tcpip/current/src/lib/dhcp_prot.c
@@ -41,6 +41,8 @@
 //
 //========================================================================*/
 
+#define nDHCP_CHATTER // report as we go along?
+
 #include <pkgconf/system.h>
 #include <pkgconf/net.h>
 
@@ -634,12 +636,15 @@ do_dhcp(const char *intf, struct bootp *
                     *pstate = DHCPSTATE_BOUND;
                     break;
                 }
-                if ( DHCPNAK == msgtype ) { // we're bounced!
+                if ( DHCPNAK == msgtype // Same server?
+                     && received->bp_siaddr.s_addr == xmit->bp_siaddr.s_addr) {
+                    // we're bounced!
                     *pstate = DHCPSTATE_INIT;  // So back the start of the rigmarole.
                     reset_timeout( &tv );
                     break;
                 }
-                // otherwise it's something else, maybe another offer.
+                // otherwise it's something else, maybe another offer, or a bogus
+                // NAK from someone we are not asking!
                 // Just listen again, which implicitly discards it.
             }
             break;
--- a/packages/net/tcpip/current/src/lib/select.c
+++ b/packages/net/tcpip/current/src/lib/select.c
@@ -139,20 +139,19 @@ static int
                 return 0;
             }
             flag = cyg_flag_timed_wait(&select_flag, wait_flag,
-                                       CYG_FLAG_WAITMODE_OR|CYG_FLAG_WAITMODE_CLR,
+                                       CYG_FLAG_WAITMODE_OR,
                                        then);
         } else {
             // Wait forever (until something happens)
             flag = cyg_flag_wait(&select_flag, wait_flag,
-                                 CYG_FLAG_WAITMODE_OR|CYG_FLAG_WAITMODE_CLR);
+                                 CYG_FLAG_WAITMODE_OR);
         }
         if (flag & SELECT_ABORT) {
             errno = EINTR;
             return -1;
         }
         if (!flag) {
-            errno = ETIMEDOUT;
-            return -1;
+            return 0; // meaning no activity, ergo timeout occurred
         }
     }
     errno = ENOSYS;
@@ -179,7 +178,8 @@ selwakeup(struct selinfo *info)
     cyg_scheduler_lock();  // Need this test to be indivisible
     if (cyg_flag_waiting(&select_flag)) {
         // Signal any threads doing a 'select()' that I/O may be possible
-        cyg_flag_setbits(&select_flag, SELECT_WAKE); 
+        cyg_flag_setbits(&select_flag, SELECT_WAKE);
+        cyg_flag_maskbits(&select_flag,    0      ); // clear all
     }
     cyg_scheduler_unlock();
 }
@@ -217,6 +217,7 @@ cyg_select_abort(void)
     if (cyg_flag_waiting(&select_flag)) {
         // Signal any threads doing a 'select()' that I/O may be possible
         cyg_flag_setbits(&select_flag, SELECT_ABORT); 
+        cyg_flag_maskbits(&select_flag,    0       ); // clear all
     }
     cyg_scheduler_unlock();
 }
--- a/packages/net/tcpip/current/src/lib/tftp_client.c
+++ b/packages/net/tcpip/current/src/lib/tftp_client.c
@@ -208,7 +208,7 @@ tftp_get(char *filename,
                     close(s);
                     return -1;
                 }
-                if ((actual_len > 0) && (actual_len < SEGSIZE)) {
+                if ((actual_len >= 0) && (actual_len < SEGSIZE)) {
                     // End of data
                     close(s);
                     return res;
--- a/packages/net/tcpip/current/src/lib/tftp_server.c
+++ b/packages/net/tcpip/current/src/lib/tftp_server.c
@@ -234,6 +234,7 @@ tftpd_read_file(struct tftp_server *serv
                 ok = false;
                 break;
             }
+        repeat_select:
             timeout.tv_sec = TFTP_TIMEOUT_PERIOD;
             timeout.tv_usec = 0;
             FD_ZERO(&fds);
@@ -243,17 +244,26 @@ tftpd_read_file(struct tftp_server *serv
                     ok = false;
                     break;
                 }
+                continue; // retry the send, using up one retry.
             }
             data_len = sizeof(data_in);
             client_len = sizeof(client_addr);
             if ((data_len = recvfrom(s, data_in, data_len, 0, 
-                                     (struct sockaddr *)&client_addr, &client_len)) < 0) {
-                // What happened?
-                ok = false;
-                break;
+                                     (struct sockaddr *)&client_addr,
+                                     &client_len)) < 0) {
+                // What happened?  Maybe someone lied to us...
+                continue; // retry the send, using up one retry.
+            }
+            if ((ntohs(response->th_opcode) == ACK) &&
+                (ntohs(response->th_block) < block)) {
+                // Then it is a repeat ACK for an old block; listen again,
+                // but do not repeat sending the current block, and do not
+                // use up a retry count.
+                goto repeat_select;
             }
             if ((ntohs(response->th_opcode) == ACK) &&
                 (ntohs(response->th_block) == block)) {
+                // Happy!  Break out of the retries loop.
                 break;
             }
         }
new file mode 100644
--- /dev/null
+++ b/packages/net/tcpip/current/src/sys/net/if_bridge.c
@@ -0,0 +1,2034 @@
+//==========================================================================
+//
+//      sys/net/if_bridge.c
+//
+//     
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//####BSDCOPYRIGHTBEGIN####
+//
+// -------------------------------------------
+//
+// Portions of this software may have been derived from OpenBSD or other sources,
+// and are covered by the appropriate copyright disclaimers included herein.
+//
+// -------------------------------------------
+//
+//####BSDCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Jason L. Wright (jason@thought.net)  
+// Contributors: andrew.lunn@ascom.ch (Andrew Lunn), hmt
+// Date:         2000-07-18
+// Purpose:      Ethernet bridge
+// Description:  
+//              
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+
+/*	$OpenBSD: if_bridge.c,v 1.25 2000/01/25 22:06:27 jason Exp $	*/
+
+/*
+ * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
+ * 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 Jason L. Wright
+ * 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.
+ */
+
+#ifdef __ECOS
+#include <pkgconf/net.h>
+#else
+#include "bridge.h"
+#include "bpfilter.h"
+#include "enc.h"
+#endif
+
+#if NBRIDGE > 0
+
+#include <sys/param.h>
+#ifndef __ECOS
+#include <sys/proc.h>
+#include <sys/systm.h>
+#endif
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/errno.h>
+#ifndef __ECOS
+#include <sys/device.h>
+#endif
+#include <sys/kernel.h>
+#include <machine/cpu.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/if_llc.h>
+#include <net/route.h>
+#include <net/netisr.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_ipsp.h>
+
+#ifndef __ECOS
+#include <net/if_enc.h>
+#endif
+#ifdef IPFILTER
+#include <netinet/ip_fil_compat.h>
+#include <netinet/ip_fil.h>
+#endif
+#endif
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+
+#include <net/if_bridge.h>
+
+#ifdef __ECOS
+#include <stdio.h> /* for sprintf */
+#endif
+
+#ifndef	BRIDGE_RTABLE_SIZE
+#define	BRIDGE_RTABLE_SIZE	1024
+#endif
+#define	BRIDGE_RTABLE_MASK	(BRIDGE_RTABLE_SIZE - 1)
+
+/*
+ * Maximum number of addresses to cache
+ */
+#ifndef BRIDGE_RTABLE_MAX
+#define BRIDGE_RTABLE_MAX	100
+#endif
+
+/*
+ * Timeout (in seconds) for entries learned dynamically
+ */
+#ifndef BRIDGE_RTABLE_TIMEOUT
+#define BRIDGE_RTABLE_TIMEOUT	240
+#endif
+
+/*
+ * This really should be defined in if_llc.h but in case it isn't.
+ */
+#ifndef llc_snap
+#define llc_snap        llc_un.type_snap
+#endif
+
+extern int ifqmaxlen;
+
+/*
+ * Bridge filtering rules
+ */
+struct brl_node {
+	SIMPLEQ_ENTRY(brl_node)	brl_next;	/* next rule */
+	struct ether_addr	brl_src;	/* source mac address */
+	struct ether_addr	brl_dst;	/* destination mac address */
+	u_int8_t		brl_action;	/* what to do with match */
+	u_int8_t		brl_flags;	/* comparision flags */
+};
+
+/*
+ * Bridge interface list
+ */
+struct bridge_iflist {
+	LIST_ENTRY(bridge_iflist)	next;		/* next in list */
+	SIMPLEQ_HEAD(, brl_node)	bif_brlin;	/* input rules */
+	SIMPLEQ_HEAD(, brl_node)	bif_brlout;	/* output rules */
+	struct				ifnet *ifp;	/* member interface */
+	u_int32_t			bif_flags;	/* member flags */
+};
+
+/*
+ * Bridge route node
+ */
+struct bridge_rtnode {
+	LIST_ENTRY(bridge_rtnode)	brt_next;	/* next in list */
+	struct				ifnet *brt_if;	/* destination ifs */
+	u_int8_t			brt_flags;	/* address flags */
+	u_int8_t			brt_age;	/* age counter */
+	struct				ether_addr brt_addr;	/* dst addr */
+};
+
+/*
+ * Software state for each bridge
+ */
+struct bridge_softc {
+	struct				ifnet sc_if;	/* the interface */
+	u_int32_t			sc_brtmax;	/* max # addresses */
+	u_int32_t			sc_brtcnt;	/* current # addrs */
+	u_int32_t			sc_brttimeout;	/* timeout ticks */
+	LIST_HEAD(, bridge_iflist)	sc_iflist;	/* interface list */
+	LIST_HEAD(bridge_rthead, bridge_rtnode)	*sc_rts;/* hash table */
+};
+
+/*
+ * Ethernet header and SNAP header
+ */
+struct ehllc {
+	struct ether_header eh;
+	struct llc llc;
+};
+
+struct bridge_softc bridgectl[NBRIDGE];
+
+void	bridgeattach __P((int));
+int	bridge_ioctl __P((struct ifnet *, u_long, caddr_t));
+void	bridge_start __P((struct ifnet *));
+void	bridgeintr_frame __P((struct bridge_softc *, struct mbuf *));
+void	bridge_broadcast __P((struct bridge_softc *, struct ifnet *,
+    struct ether_header *, struct mbuf *));
+void	bridge_stop __P((struct bridge_softc *));
+void	bridge_init __P((struct bridge_softc *));
+int	bridge_bifconf __P((struct bridge_softc *, struct ifbifconf *));
+
+int	bridge_rtfind __P((struct bridge_softc *, struct ifbaconf *));
+void	bridge_rtage __P((void *));
+void	bridge_rttrim __P((struct bridge_softc *));
+void	bridge_rtdelete __P((struct bridge_softc *, struct ifnet *));
+int	bridge_rtdaddr __P((struct bridge_softc *, struct ether_addr *));
+int	bridge_rtflush __P((struct bridge_softc *, int));
+struct ifnet *	bridge_rtupdate __P((struct bridge_softc *,
+    struct ether_addr *, struct ifnet *ifp, int, u_int8_t));
+struct ifnet *	bridge_rtlookup __P((struct bridge_softc *,
+    struct ether_addr *));
+u_int32_t	bridge_hash __P((struct ether_addr *));
+struct mbuf *bridge_blocknonip __P((struct mbuf *));
+int		bridge_addrule __P((struct bridge_iflist *,
+    struct ifbrlreq *, int out));
+int		bridge_flushrule __P((struct bridge_iflist *));
+int	bridge_brlconf __P((struct bridge_softc *, struct ifbrlconf *));
+u_int8_t bridge_filterrule __P((struct brl_node *, struct ether_header *));
+
+#define	ETHERADDR_IS_IP_MCAST(a) \
+	/* struct etheraddr *a;	*/				\
+	((a)->ether_addr_octet[0] == 0x01 &&			\
+	 (a)->ether_addr_octet[1] == 0x00 &&			\
+	 (a)->ether_addr_octet[2] == 0x5e)
+
+
+#if defined(INET) && (defined(IPFILTER) || defined(IPFILTER_LKM))
+/*
+ * Filter hooks
+ */
+#define	BRIDGE_FILTER_PASS	0
+#define	BRIDGE_FILTER_DROP	1
+int	bridge_filter __P((struct bridge_softc *, struct ifnet *,
+    struct ether_header *, struct mbuf **));
+#endif
+
+void
+bridgeattach(unused)
+	int unused;
+{
+	int i;
+	struct ifnet *ifp;
+
+	for (i = 0; i < NBRIDGE; i++) {
+		bridgectl[i].sc_brtmax = BRIDGE_RTABLE_MAX;
+		bridgectl[i].sc_brttimeout = BRIDGE_RTABLE_TIMEOUT;
+		LIST_INIT(&bridgectl[i].sc_iflist);
+		ifp = &bridgectl[i].sc_if;
+		sprintf(ifp->if_xname, "bridge%d", i);
+		ifp->if_softc = &bridgectl[i];
+		ifp->if_mtu = ETHERMTU;
+		ifp->if_ioctl = bridge_ioctl;
+		ifp->if_output = bridge_output;
+		ifp->if_start = bridge_start;
+		ifp->if_type = IFT_PROPVIRTUAL;
+		ifp->if_snd.ifq_maxlen = ifqmaxlen;
+		ifp->if_hdrlen = sizeof(struct ether_header);
+		if_attach(ifp);
+#if NBPFILTER > 0
+		bpfattach(&bridgectl[i].sc_if.if_bpf, ifp,
+		    DLT_EN10MB, sizeof(struct ether_header));
+#endif
+	}
+}
+
+int
+bridge_ioctl(ifp, cmd, data)
+	struct ifnet *ifp;
+	u_long cmd;
+	caddr_t	data;
+{
+#ifndef __ECOS
+	struct proc *prc = curproc;		/* XXX */
+#endif
+	struct ifnet *ifs;
+	struct bridge_softc *sc = (struct bridge_softc *)ifp->if_softc;
+	struct ifbreq *req = (struct ifbreq *)data;
+	struct ifbaconf *baconf = (struct ifbaconf *)data;
+	struct ifbareq *bareq = (struct ifbareq *)data;
+	struct ifbcachereq *bcachereq = (struct ifbcachereq *)data;
+	struct ifbifconf *bifconf = (struct ifbifconf *)data;
+	struct ifbcachetoreq *bcacheto = (struct ifbcachetoreq *)data;
+	struct ifbrlreq *brlreq = (struct ifbrlreq *)data;
+	struct ifbrlconf *brlconf = (struct ifbrlconf *)data;
+	struct ifreq ifreq;
+	int error = 0, s;
+	struct bridge_iflist *p;
+
+	s = splimp();
+	switch (cmd) {
+	case SIOCBRDGADD:
+#ifndef __ECOS          
+		if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
+			break;
+#endif
+		ifs = ifunit(req->ifbr_ifsname);
+		if (ifs == NULL) {			/* no such interface */
+			error = ENOENT;
+			break;
+		}
+		if (ifs->if_bridge == (caddr_t)sc) {
+			error = EEXIST;
+			break;
+		}
+		if (ifs->if_bridge != NULL) {
+			error = EBUSY;
+			break;
+		}
+
+		if (ifs->if_type == IFT_ETHER) {
+			if ((ifs->if_flags & IFF_UP) == 0) {
+				/*
+				 * Bring interface up long enough to set
+				 * promiscuous flag, then shut it down again.
+				 */
+				strncpy(ifreq.ifr_name, req->ifbr_ifsname,
+				    sizeof(ifreq.ifr_name) - 1);
+				ifreq.ifr_name[sizeof(ifreq.ifr_name) - 1] = '\0';
+				ifs->if_flags |= IFF_UP;
+				ifreq.ifr_flags = ifs->if_flags;
+				error = (*ifs->if_ioctl)(ifs, SIOCSIFFLAGS,
+				    (caddr_t)&ifreq);
+				if (error != 0)
+					break;
+
+				error = ifpromisc(ifs, 1);
+				if (error != 0)
+					break;
+
+				strncpy(ifreq.ifr_name, req->ifbr_ifsname,
+				    sizeof(ifreq.ifr_name) - 1);
+				ifreq.ifr_name[sizeof(ifreq.ifr_name) - 1] = '\0';
+				ifs->if_flags &= ~IFF_UP;
+				ifreq.ifr_flags = ifs->if_flags;
+				error = (*ifs->if_ioctl)(ifs, SIOCSIFFLAGS,
+				    (caddr_t)&ifreq);
+				if (error != 0) {
+					ifpromisc(ifs, 0);
+					break;
+				}
+			} else {
+				error = ifpromisc(ifs, 1);
+				if (error != 0)
+					break;
+			}
+		}
+		else if (ifs->if_type == IFT_ENC) {
+#ifndef __ECOS
+#if NENC > 0
+			/* Can't bind enc0 to a bridge */
+			if (ifs->if_softc == &encif[0])
+				return EINVAL;
+#endif /* NENC */
+#endif
+		}
+		else {
+			error = EINVAL;
+			break;
+		}
+
+		p = (struct bridge_iflist *) malloc(
+		    sizeof(struct bridge_iflist), M_DEVBUF, M_NOWAIT);
+		if (p == NULL && ifs->if_type == IFT_ETHER) {
+			error = ENOMEM;
+			ifpromisc(ifs, 0);
+			break;
+		}
+
+		p->ifp = ifs;
+		p->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER;
+		SIMPLEQ_INIT(&p->bif_brlin);
+		SIMPLEQ_INIT(&p->bif_brlout);
+		LIST_INSERT_HEAD(&sc->sc_iflist, p, next);
+		ifs->if_bridge = (caddr_t)sc;
+		break;
+	case SIOCBRDGDEL:
+#ifndef __ECOS
+		if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
+			break;
+#endif
+		p = LIST_FIRST(&sc->sc_iflist);
+		while (p != NULL) {
+			if (strncmp(p->ifp->if_xname, req->ifbr_ifsname,
+			    sizeof(p->ifp->if_xname)) == 0) {
+				p->ifp->if_bridge = NULL;
+
+				error = ifpromisc(p->ifp, 0);
+
+				LIST_REMOVE(p, next);
+				bridge_rtdelete(sc, p->ifp);
+				bridge_flushrule(p);
+				free(p, M_DEVBUF);
+				break;
+			}
+			p = LIST_NEXT(p, next);
+		}
+		if (p == NULL) {
+			error = ENOENT;
+			break;
+		}
+		break;
+	case SIOCBRDGIFS:
+		error = bridge_bifconf(sc, bifconf);
+		break;
+	case SIOCBRDGGIFFLGS:
+		ifs = ifunit(req->ifbr_ifsname);
+		if (ifs == NULL) {
+			error = ENOENT;
+			break;
+		}
+		if ((caddr_t)sc != ifs->if_bridge) {
+			error = ESRCH;
+			break;
+		}
+		p = LIST_FIRST(&sc->sc_iflist);
+		while (p != NULL && p->ifp != ifs) {
+			p = LIST_NEXT(p, next);
+		}
+		if (p == NULL) {
+			error = ESRCH;
+			break;
+		}
+		req->ifbr_ifsflags = p->bif_flags;
+		break;
+	case SIOCBRDGSIFFLGS:
+#ifndef __ECOS
+		if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
+			break;
+#endif
+		ifs = ifunit(req->ifbr_ifsname);
+		if (ifs == NULL) {
+			error = ENOENT;
+			break;
+		}
+		if ((caddr_t)sc != ifs->if_bridge) {
+			error = ESRCH;
+			break;
+		}
+		p = LIST_FIRST(&sc->sc_iflist);
+		while (p != NULL && p->ifp != ifs) {
+			p = LIST_NEXT(p, next);
+		}
+		if (p == NULL) {
+			error = ESRCH;
+			break;
+		}
+		p->bif_flags = req->ifbr_ifsflags;
+		break;
+	case SIOCBRDGRTS:
+		error = bridge_rtfind(sc, baconf);
+		break;
+	case SIOCBRDGFLUSH:
+#ifndef __ECOS
+		if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
+			break;
+#endif
+		error = bridge_rtflush(sc, req->ifbr_ifsflags);
+		break;
+	case SIOCBRDGSADDR:
+#ifndef __ECOS
+		if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
+			break;
+#endif
+		ifs = ifunit(bareq->ifba_ifsname);
+		if (ifs == NULL) {			/* no such interface */
+			error = ENOENT;
+			break;
+		}
+
+		if (ifs->if_bridge == NULL ||
+		    ifs->if_bridge != (caddr_t)sc) {
+			error = ESRCH;
+			break;
+		}
+
+		ifs = bridge_rtupdate(sc, &bareq->ifba_dst, ifs, 1,
+		    bareq->ifba_flags);
+		if (ifs == NULL)
+			error = ENOMEM;
+		break;
+	case SIOCBRDGDADDR:
+#ifndef __ECOS
+		if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
+			break;
+#endif
+		error = bridge_rtdaddr(sc, &bareq->ifba_dst);
+		break;
+	case SIOCBRDGGCACHE:
+		bcachereq->ifbc_size = sc->sc_brtmax;
+		break;
+	case SIOCBRDGSCACHE:
+#ifndef __ECOS
+		if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
+			break;
+#endif
+		sc->sc_brtmax = bcachereq->ifbc_size;
+		bridge_rttrim(sc);
+		break;
+	case SIOCBRDGSTO:
+#ifndef __ECOS
+		if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
+			break;
+#endif
+		sc->sc_brttimeout = bcacheto->ifbct_time;
+		untimeout(bridge_rtage, sc);
+		if (bcacheto->ifbct_time != 0)
+			timeout(bridge_rtage, sc, sc->sc_brttimeout);
+		break;
+	case SIOCBRDGGTO:
+		bcacheto->ifbct_time = sc->sc_brttimeout;
+		break;
+	case SIOCSIFFLAGS:
+		if ((ifp->if_flags & IFF_UP) == IFF_UP)
+			bridge_init(sc);
+
+		if ((ifp->if_flags & IFF_UP) == 0)
+			bridge_stop(sc);
+
+		break;
+	case SIOCBRDGARL:
+#ifndef __ECOS
+		if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
+			break;
+#endif
+		ifs = ifunit(brlreq->ifbr_ifsname);
+		if (ifs == NULL) {
+			error = ENOENT;
+			break;
+		}
+		if (ifs->if_bridge == NULL ||
+		    ifs->if_bridge != (caddr_t)sc) {
+			error = ESRCH;
+			break;
+		}
+		p = LIST_FIRST(&sc->sc_iflist);
+		while (p != NULL && p->ifp != ifs) {
+			p = LIST_NEXT(p, next);
+		}
+		if (p == NULL) {
+			error = ESRCH;
+			break;
+		}
+		if ((brlreq->ifbr_action != BRL_ACTION_BLOCK &&
+		    brlreq->ifbr_action != BRL_ACTION_PASS) ||
+		    (brlreq->ifbr_flags & (BRL_FLAG_IN|BRL_FLAG_OUT)) == 0) {
+			error = EINVAL;
+			break;
+		}
+		if (brlreq->ifbr_flags & BRL_FLAG_IN) {
+			error = bridge_addrule(p, brlreq, 0);
+			if (error)
+				break;
+		}
+		if (brlreq->ifbr_flags & BRL_FLAG_OUT) {
+			error = bridge_addrule(p, brlreq, 1);
+			if (error)
+				break;
+		}
+		break;
+	case SIOCBRDGFRL:
+#ifndef __ECOS
+		if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
+			break;
+#endif
+		ifs = ifunit(brlreq->ifbr_ifsname);
+		if (ifs == NULL) {
+			error = ENOENT;
+			break;
+		}
+		if (ifs->if_bridge == NULL ||
+		    ifs->if_bridge != (caddr_t)sc) {
+			error = ESRCH;
+			break;
+		}
+		p = LIST_FIRST(&sc->sc_iflist);
+		while (p != NULL && p->ifp != ifs) {
+			p = LIST_NEXT(p, next);
+		}
+		if (p == NULL) {
+			error = ESRCH;
+			break;
+		}
+		error = bridge_flushrule(p);
+		break;
+	case SIOCBRDGGRL:
+		error = bridge_brlconf(sc, brlconf);
+		break;
+	default:
+		error = EINVAL;
+	}
+	splx(s);
+	return (error);
+}
+
+/* Detach an interface from a bridge.  */
+void
+bridge_ifdetach(ifp)
+	struct ifnet *ifp;
+{
+	struct bridge_softc *bsc = (struct bridge_softc *)ifp->if_bridge;
+	struct bridge_iflist *bif;
+
+	for (bif = LIST_FIRST(&bsc->sc_iflist); bif;
+	    bif = LIST_NEXT(bif, next))
+		if (bif->ifp == ifp) {
+			LIST_REMOVE(bif, next);
+			bridge_rtdelete(bsc, ifp);
+			bridge_flushrule(bif);
+			free(bif, M_DEVBUF);
+			break;
+		}
+}
+
+int
+bridge_bifconf(sc, bifc)
+	struct bridge_softc *sc;
+	struct ifbifconf *bifc;
+{
+	struct bridge_iflist *p;
+	u_int32_t total = 0, i;
+	int error = 0;
+	struct ifbreq breq;
+
+	p = LIST_FIRST(&sc->sc_iflist);
+	while (p != NULL) {
+		total++;
+		p = LIST_NEXT(p, next);
+	}
+
+	if (bifc->ifbic_len == 0) {
+		i = total;
+		goto done;
+	}
+
+	p = LIST_FIRST(&sc->sc_iflist);
+	i = 0;
+	while (p != NULL && bifc->ifbic_len > i * sizeof(breq)) {
+		strncpy(breq.ifbr_name, sc->sc_if.if_xname,
+		    sizeof(breq.ifbr_name)-1);
+		breq.ifbr_name[sizeof(breq.ifbr_name) - 1] = '\0';
+		strncpy(breq.ifbr_ifsname, p->ifp->if_xname,
+		    sizeof(breq.ifbr_ifsname)-1);
+		breq.ifbr_ifsname[sizeof(breq.ifbr_ifsname) - 1] = '\0';
+		breq.ifbr_ifsflags = p->bif_flags;
+		error = copyout((caddr_t)&breq,
+		    (caddr_t)(bifc->ifbic_req + i), sizeof(breq));
+		if (error)
+			goto done;
+		p = LIST_NEXT(p, next);
+		i++;
+		bifc->ifbic_len -= sizeof(breq);
+	}
+done:
+	bifc->ifbic_len = i * sizeof(breq);
+	return (error);
+}
+
+int
+bridge_brlconf(sc, bc)
+	struct bridge_softc *sc;
+	struct ifbrlconf *bc;
+{
+	struct ifnet *ifp;
+	struct bridge_iflist *ifl;
+	struct brl_node *n;
+	struct ifbrlreq req;
+	int error = 0;
+	u_int32_t i, total=0;
+
+	ifp = ifunit(bc->ifbrl_ifsname);
+	if (ifp == NULL)
+		return (ENOENT);
+	if (ifp->if_bridge == NULL || ifp->if_bridge != (caddr_t)sc)
+		return (ESRCH);
+	ifl = LIST_FIRST(&sc->sc_iflist);
+	while (ifl != NULL && ifl->ifp != ifp)
+		ifl = LIST_NEXT(ifl, next);
+	if (ifl == NULL)
+		return (ESRCH);
+
+	n = SIMPLEQ_FIRST(&ifl->bif_brlin);
+	while (n != NULL) {
+		total++;
+		n = SIMPLEQ_NEXT(n, brl_next);
+	}
+	n = SIMPLEQ_FIRST(&ifl->bif_brlout);
+	while (n != NULL) {
+		total++;
+		n = SIMPLEQ_NEXT(n, brl_next);
+	}
+
+	if (bc->ifbrl_len == 0) {
+		i = total;
+		goto done;
+	}
+
+	i = 0;
+	n = SIMPLEQ_FIRST(&ifl->bif_brlin);
+	while (n != NULL && bc->ifbrl_len > i * sizeof(req)) {
+		strncpy(req.ifbr_name, sc->sc_if.if_xname,
+		    sizeof(req.ifbr_name) - 1);
+		req.ifbr_name[sizeof(req.ifbr_name) - 1] = '\0';
+		strncpy(req.ifbr_ifsname, ifl->ifp->if_xname,
+		    sizeof(req.ifbr_ifsname) - 1);
+		req.ifbr_ifsname[sizeof(req.ifbr_ifsname) - 1] = '\0';
+		req.ifbr_action = n->brl_action;
+		req.ifbr_flags = n->brl_flags;
+		req.ifbr_src = n->brl_src;
+		req.ifbr_dst = n->brl_dst;
+		error = copyout((caddr_t)&req,
+		    (caddr_t)(bc->ifbrl_buf + (i * sizeof(req))), sizeof(req));
+		if (error)
+			goto done;
+		n = SIMPLEQ_NEXT(n, brl_next);
+		i++;
+		bc->ifbrl_len -= sizeof(req);
+	}
+
+	n = SIMPLEQ_FIRST(&ifl->bif_brlout);
+	while (n != NULL && bc->ifbrl_len > i * sizeof(req)) {
+		strncpy(req.ifbr_name, sc->sc_if.if_xname,
+		    sizeof(req.ifbr_name) - 1);
+		req.ifbr_name[sizeof(req.ifbr_name) - 1] = '\0';
+		strncpy(req.ifbr_ifsname, ifl->ifp->if_xname,
+		    sizeof(req.ifbr_ifsname) - 1);
+		req.ifbr_ifsname[sizeof(req.ifbr_ifsname) - 1] = '\0';
+		req.ifbr_action = n->brl_action;
+		req.ifbr_flags = n->brl_flags;
+		req.ifbr_src = n->brl_src;
+		req.ifbr_dst = n->brl_dst;
+		error = copyout((caddr_t)&req,
+		    (caddr_t)(bc->ifbrl_buf + (i * sizeof(req))), sizeof(req));
+		if (error)
+			goto done;
+		n = SIMPLEQ_NEXT(n, brl_next);
+		i++;
+		bc->ifbrl_len -= sizeof(req);
+	}
+
+done:
+	bc->ifbrl_len = i * sizeof(req);
+	return (error);
+}
+
+void
+bridge_init(sc)
+	struct bridge_softc *sc;
+{
+	struct ifnet *ifp = &sc->sc_if;
+	int i, s;
+
+	if ((ifp->if_flags & IFF_RUNNING) == IFF_RUNNING)
+		return;
+
+	s = splhigh();
+	if (sc->sc_rts == NULL) {
+		sc->sc_rts = (struct bridge_rthead *)malloc(
+		    BRIDGE_RTABLE_SIZE * (sizeof(struct bridge_rthead)),
+		    M_DEVBUF, M_NOWAIT);
+		if (sc->sc_rts == NULL) {
+			splx(s);
+			return;
+		}
+		for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) {
+			LIST_INIT(&sc->sc_rts[i]);
+		}
+	}
+	ifp->if_flags |= IFF_RUNNING;
+	splx(s);
+
+	if (sc->sc_brttimeout != 0)
+		timeout(bridge_rtage, sc, sc->sc_brttimeout * hz);
+}
+
+/*
+ * Stop the bridge and deallocate the routing table.
+ */
+void
+bridge_stop(sc)
+	struct bridge_softc *sc;
+{
+	struct ifnet *ifp = &sc->sc_if;
+
+	/*
+	 * If we're not running, there's nothing to do.
+	 */
+	if ((ifp->if_flags & IFF_RUNNING) == 0)
+		return;
+
+	untimeout(bridge_rtage, sc);
+
+	bridge_rtflush(sc, IFBF_FLUSHDYN);
+
+	ifp->if_flags &= ~IFF_RUNNING;
+}
+
+/*
+ * Send output from the bridge.  The mbuf has the ethernet header
+ * already attached.  We must enqueue or free the mbuf before exiting.
+ */
+int
+bridge_output(ifp, m, sa, rt)
+	struct ifnet *ifp;
+	struct mbuf *m;
+	struct sockaddr *sa;
+	struct rtentry *rt;
+{
+	struct ether_header *eh;
+	struct ifnet *dst_if;
+	struct ether_addr *src, *dst;
+	struct bridge_softc *sc;
+	struct bridge_iflist *p;
+	struct mbuf *mc;
+	int s;
+
+	if (m->m_len < sizeof(*eh)) {
+		m = m_pullup(m, sizeof(*eh));
+		if (m == NULL)
+			return (0);
+	}
+	eh = mtod(m, struct ether_header *);
+	dst = (struct ether_addr *)&eh->ether_dhost[0];
+	src = (struct ether_addr *)&eh->ether_shost[0];
+	sc = (struct bridge_softc *)ifp->if_bridge;
+
+	s = splimp();
+
+	/*
+	 * If bridge is down, but original output interface is up,
+	 * go ahead and send out that interface.  Otherwise the packet
+	 * is dropped below.
+	 */
+	if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
+		dst_if = ifp;
+		goto sendunicast;
+	}
+
+	/*
+	 * If the packet is a broadcast or we don't know a better way to
+	 * get there, send to all interfaces.
+	 */
+	dst_if = bridge_rtlookup(sc, dst);
+	if (dst_if == NULL || eh->ether_dhost[0] & 1) {
+		for (p = LIST_FIRST(&sc->sc_iflist); p != NULL;
+		    p = LIST_NEXT(p, next)) {
+			if ((p->ifp->if_flags & IFF_RUNNING) == 0)
+				continue;
+
+			if (IF_QFULL(&p->ifp->if_snd)) {
+				sc->sc_if.if_oerrors++;
+				continue;
+			}
+
+			mc = m_copym(m, 0, M_COPYALL, M_NOWAIT);
+			if (mc == NULL) {
+				sc->sc_if.if_oerrors++;
+				continue;
+			}
+
+			sc->sc_if.if_opackets++;
+			sc->sc_if.if_obytes += m->m_pkthdr.len;
+			IF_ENQUEUE(&p->ifp->if_snd, mc);
+			if ((p->ifp->if_flags & IFF_OACTIVE) == 0)
+				(*p->ifp->if_start)(p->ifp);
+		}
+		m_freem(m);
+		splx(s);
+		return (0);
+	}
+
+sendunicast:
+	if ((dst_if->if_flags & IFF_RUNNING) == 0) {
+		m_freem(m);
+		splx(s);
+		return (0);
+	}
+	if (IF_QFULL(&dst_if->if_snd)) {
+		sc->sc_if.if_oerrors++;
+		m_freem(m);
+		splx(s);
+		return (0);
+	}
+	sc->sc_if.if_opackets++;
+	sc->sc_if.if_obytes += m->m_pkthdr.len;
+	IF_ENQUEUE(&dst_if->if_snd, m);
+	if ((dst_if->if_flags & IFF_OACTIVE) == 0)
+		(*dst_if->if_start)(dst_if);
+	splx(s);
+	return (0);
+}
+
+/*
+ * Start output on the bridge.  This function should never be called.
+ */
+void
+bridge_start(ifp)
+	struct ifnet *ifp;
+{
+}
+
+void
+bridgeintr(void)
+{
+	struct bridge_softc *sc;
+	struct mbuf *m;
+	int i, s;
+
+	for (i = 0; i < NBRIDGE; i++) {
+		sc = &bridgectl[i];
+		for (;;) {
+			s = splimp();
+			IF_DEQUEUE(&sc->sc_if.if_snd, m);
+			splx(s);
+			if (m == NULL)
+				break;
+			bridgeintr_frame(sc, m);
+		}
+	}
+}
+
+/*
+ * Loop through each bridge interface and process their input queues.
+ */
+void
+bridgeintr_frame(sc, m)
+	struct bridge_softc *sc;
+	struct mbuf *m;
+{
+	int s;
+	struct ifnet *src_if, *dst_if;
+	struct bridge_iflist *ifl;
+	struct ether_addr *dst, *src;
+	struct ether_header *eh;
+
+	if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
+		m_freem(m);
+		return;
+	}
+
+	src_if = m->m_pkthdr.rcvif;
+
+#if NBPFILTER > 0
+	if (sc->sc_if.if_bpf)
+		bpf_mtap(sc->sc_if.if_bpf, m);
+#endif
+
+	sc->sc_if.if_lastchange = time;
+	sc->sc_if.if_ipackets++;
+	sc->sc_if.if_ibytes += m->m_pkthdr.len;
+
+	ifl = LIST_FIRST(&sc->sc_iflist);
+	while (ifl != NULL && ifl->ifp != src_if) {
+		ifl = LIST_NEXT(ifl, next);
+	}
+	if (ifl == NULL) {
+		m_freem(m);
+		return;
+	}
+
+	if (m->m_len < sizeof(*eh)) {
+		m = m_pullup(m, sizeof(*eh));
+		if (m == NULL)
+			return;
+	}
+	eh = mtod(m, struct ether_header *);
+	dst = (struct ether_addr *)&eh->ether_dhost[0];
+	src = (struct ether_addr *)&eh->ether_shost[0];
+
+	/*
+	 * If interface is learning, and if source address
+	 * is not broadcast or multicast, record it's address.
+	 */
+	if ((ifl->bif_flags & IFBIF_LEARNING) &&
+	    (eh->ether_shost[0] & 1) == 0 &&
+	    !(eh->ether_shost[0] == 0 &&
+	      eh->ether_shost[1] == 0 &&
+	      eh->ether_shost[2] == 0 &&
+	      eh->ether_shost[3] == 0 &&
+	      eh->ether_shost[4] == 0 &&
+	      eh->ether_shost[5] == 0))
+		bridge_rtupdate(sc, src, src_if, 0, IFBAF_DYNAMIC);
+
+	/*
+	 * If packet is unicast, destined for someone on "this"
+	 * side of the bridge, drop it.
+	 */
+	if (m->m_flags & (M_BCAST | M_MCAST)) {
+		dst_if = bridge_rtlookup(sc, dst);
+		if (dst_if == src_if) {
+			m_freem(m);
+			return;
+		}
+	} else
+		dst_if = NULL;
+
+	/*
+	 * Multicast packets get handled a little differently:
+	 * If interface is:
+	 *	-link0,-link1	(default) Forward all multicast
+	 *			as broadcast.
+	 *	-link0,link1	Drop non-IP multicast, forward
+	 *			as broadcast IP multicast.
+	 *	link0,-link1	Drop IP multicast, forward as
+	 *			broadcast non-IP multicast.
+	 *	link0,link1	Drop all multicast.
+	 */
+	if (m->m_flags & M_MCAST) {
+		if ((sc->sc_if.if_flags &
+		    (IFF_LINK0 | IFF_LINK1)) ==
+		    (IFF_LINK0 | IFF_LINK1)) {
+			m_freem(m);
+			return;
+		}
+		if (sc->sc_if.if_flags & IFF_LINK0 &&
+		    ETHERADDR_IS_IP_MCAST(dst)) {
+			m_freem(m);
+			return;
+		}
+		if (sc->sc_if.if_flags & IFF_LINK1 &&
+		    !ETHERADDR_IS_IP_MCAST(dst)) {
+			m_freem(m);
+			return;
+		}
+	}
+
+	if (ifl->bif_flags & IFBIF_BLOCKNONIP) {
+		m = bridge_blocknonip(m);
+		if (m == NULL)
+			return;
+		eh = mtod(m, struct ether_header *);
+		dst = (struct ether_addr *)&eh->ether_dhost[0];
+		src = (struct ether_addr *)&eh->ether_shost[0];
+	}
+
+	if (SIMPLEQ_FIRST(&ifl->bif_brlin) &&
+	    bridge_filterrule(SIMPLEQ_FIRST(&ifl->bif_brlin), eh) ==
+	    BRL_ACTION_BLOCK) {
+		m_freem(m);
+		return;
+	}
+
+#if defined(INET) && (defined(IPFILTER) || defined(IPFILTER_LKM))
+	if (bridge_filter(sc, src_if, eh, &m) == BRIDGE_FILTER_DROP) {
+		if (m != NULL)
+			m_freem(m);
+		return;
+	}
+#endif
+
+	/*
+	 * If the packet is a multicast or broadcast OR if we don't
+	 * know any better, forward it to all interfaces.
+	 */
+	if ((m->m_flags & (M_BCAST | M_MCAST)) || dst_if == NULL) {
+		sc->sc_if.if_imcasts++;
+		bridge_broadcast(sc, src_if, eh, m);
+		return;
+	}
+
+	/*
+	 * At this point, we're dealing with a unicast frame going to a
+	 * different interface
+	 */
+	if ((dst_if->if_flags & IFF_RUNNING) == 0) {
+		m_freem(m);
+		return;
+	}
+	ifl = LIST_FIRST(&sc->sc_iflist);
+	while (ifl != NULL && ifl->ifp != dst_if)
+		ifl = LIST_NEXT(ifl, next);
+	if (SIMPLEQ_FIRST(&ifl->bif_brlout) &&
+	    bridge_filterrule(SIMPLEQ_FIRST(&ifl->bif_brlout), eh) ==
+	    BRL_ACTION_BLOCK) {
+		m_freem(m);
+		return;
+	}
+	s = splimp();
+	if (IF_QFULL(&dst_if->if_snd)) {
+		sc->sc_if.if_oerrors++;
+		m_freem(m);
+		splx(s);
+		return;
+	}
+	sc->sc_if.if_opackets++;
+	sc->sc_if.if_obytes += m->m_pkthdr.len;
+	IF_ENQUEUE(&dst_if->if_snd, m);
+	if ((dst_if->if_flags & IFF_OACTIVE) == 0)
+		(*dst_if->if_start)(dst_if);
+	splx(s);
+}
+
+/*
+ * Receive input from an interface.  Rebroadcast if necessary to other
+ * bridge members.
+ */
+struct mbuf *
+bridge_input(ifp, eh, m)
+	struct ifnet *ifp;
+	struct ether_header *eh;
+	struct mbuf *m;
+{
+	struct bridge_softc *sc;
+	int s;
+	struct bridge_iflist *ifl;
+	struct arpcom *ac;
+	struct ether_header *neh;
+	struct mbuf *mc;
+
+	/*
+	 * Make sure this interface is a bridge member.
+	 */
+	if (ifp == NULL || ifp->if_bridge == NULL || m == NULL)
+		return (m);
+
+	sc = (struct bridge_softc *)ifp->if_bridge;
+	if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
+		return (m);
+
+	if (m->m_flags & (M_BCAST | M_MCAST)) {
+		/*
+		 * make a copy of 'm' with 'eh' tacked on to the
+		 * beginning.  Return 'm' for local processing
+		 * and enqueue the copy.  Schedule netisr.
+		 */
+		mc = m_copym2(m, 0, M_COPYALL, M_NOWAIT);
+		if (mc == NULL)
+			return (m);
+		M_PREPEND(mc, sizeof(*eh), M_DONTWAIT);
+		if (mc == NULL)
+			return (m);
+		neh = mtod(mc, struct ether_header *);
+		bcopy(eh, neh, sizeof(struct ether_header));
+		s = splimp();
+		if (IF_QFULL(&sc->sc_if.if_snd)) {
+			m_freem(mc);
+			splx(s);
+			return (m);
+		}
+		IF_ENQUEUE(&sc->sc_if.if_snd, mc);
+		splx(s);
+		schednetisr(NETISR_BRIDGE);
+		return (m);
+	}
+
+	/*
+	 * Unicast, make sure it's not for us.
+	 */
+	ifl = LIST_FIRST(&sc->sc_iflist);
+	while (ifl != NULL) {
+		if (ifl->ifp->if_type == IFT_ETHER) {
+			ac = (struct arpcom *)ifl->ifp;
+			if (bcmp(ac->ac_enaddr, eh->ether_dhost,
+			    ETHER_ADDR_LEN) == 0) {
+				bridge_rtupdate(sc,
+				    (struct ether_addr *)&eh->ether_dhost[0],
+				    ifp, 0, IFBAF_DYNAMIC);
+				return (m);
+			}
+			if (bcmp(ac->ac_enaddr, eh->ether_shost,
+			    ETHER_ADDR_LEN) == 0) {
+				m_freem(m);
+				return (NULL);
+			}
+		}
+		ifl = LIST_NEXT(ifl, next);
+	}
+	M_PREPEND(m, sizeof(*eh), M_DONTWAIT);
+	if (m == NULL)
+		return (NULL);
+	neh = mtod(m, struct ether_header *);
+	bcopy(eh, neh, sizeof(struct ether_header));
+	s = splimp();
+	if (IF_QFULL(&sc->sc_if.if_snd)) {
+		m_freem(m);
+		splx(s);
+		return (NULL);
+	}
+	IF_ENQUEUE(&sc->sc_if.if_snd, m);
+	splx(s);
+	schednetisr(NETISR_BRIDGE);
+	return (NULL);
+}
+
+/*
+ * Send a frame to all interfaces that are members of the bridge
+ * (except the one it came in on).  This code assumes that it is
+ * running at splnet or higher.
+ */
+void
+bridge_broadcast(sc, ifp, eh, m)
+	struct bridge_softc *sc;
+	struct ifnet *ifp;
+	struct ether_header *eh;
+	struct mbuf *m;
+{
+	struct bridge_iflist *p;
+	struct mbuf *mc;
+	int used = 0;
+
+	for (p = LIST_FIRST(&sc->sc_iflist); p; p = LIST_NEXT(p, next)) {
+		/*
+		 * Don't retransmit out of the same interface where
+		 * the packet was received from.
+		 */
+		if (p->ifp->if_index == ifp->if_index)
+			continue;
+
+		if ((p->bif_flags & IFBIF_DISCOVER) == 0 &&
+		    (m->m_flags & (M_BCAST | M_MCAST)) == 0)
+			continue;
+
+		if ((p->ifp->if_flags & IFF_RUNNING) == 0)
+			continue;
+
+		if (IF_QFULL(&p->ifp->if_snd)) {
+			sc->sc_if.if_oerrors++;
+			continue;
+		}
+
+		if (SIMPLEQ_FIRST(&p->bif_brlout) &&
+		    bridge_filterrule(SIMPLEQ_FIRST(&p->bif_brlout), eh) ==
+		    BRL_ACTION_BLOCK) {
+			continue;
+		}
+
+		/* If last one, reuse the passed-in mbuf */
+		if (LIST_NEXT(p, next) == NULL) {
+			mc = m;
+			used = 1;
+		}
+		else {
+			mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
+			if (mc == NULL) {
+				sc->sc_if.if_oerrors++;
+				continue;
+			}
+		}
+
+		if (p->bif_flags & IFBIF_BLOCKNONIP) {
+			mc = bridge_blocknonip(mc);
+			if (mc == NULL)
+				continue;
+		}
+
+		sc->sc_if.if_opackets++;
+		sc->sc_if.if_obytes += mc->m_pkthdr.len;
+		if ((eh->ether_shost[0] & 1) == 0)
+			ifp->if_omcasts++;
+
+		IF_ENQUEUE(&p->ifp->if_snd, mc);
+		if ((p->ifp->if_flags & IFF_OACTIVE) == 0)
+			(*p->ifp->if_start)(p->ifp);
+	}
+
+	if (!used)
+		m_freem(m);
+}
+
+struct ifnet *
+bridge_rtupdate(sc, ea, ifp, setflags, flags)
+	struct bridge_softc *sc;
+	struct ether_addr *ea;
+	struct ifnet *ifp;
+	int setflags;
+	u_int8_t flags;
+{
+	struct bridge_rtnode *p, *q;
+	u_int32_t h;
+	int s, dir;
+
+	s = splhigh();
+	if (sc->sc_rts == NULL) {
+		if (setflags && flags == IFBAF_STATIC) {
+			sc->sc_rts = (struct bridge_rthead *)malloc(
+			    BRIDGE_RTABLE_SIZE *
+			    (sizeof(struct bridge_rthead)),M_DEVBUF,M_NOWAIT);
+
+			if (sc->sc_rts == NULL)
+				goto done;
+
+			for (h = 0; h < BRIDGE_RTABLE_SIZE; h++)
+				LIST_INIT(&sc->sc_rts[h]);
+		}
+		else
+			goto done;
+	}
+
+	h = bridge_hash(ea);
+	p = LIST_FIRST(&sc->sc_rts[h]);
+	if (p == NULL) {
+		if (sc->sc_brtcnt >= sc->sc_brtmax)
+			goto done;
+		p = (struct bridge_rtnode *)malloc(
+		    sizeof(struct bridge_rtnode), M_DEVBUF, M_NOWAIT);
+		if (p == NULL)
+			goto done;
+
+		bcopy(ea, &p->brt_addr, sizeof(p->brt_addr));
+		p->brt_if = ifp;
+		p->brt_age = 1;
+
+		if (setflags)
+			p->brt_flags = flags;
+		else
+			p->brt_flags = IFBAF_DYNAMIC;
+
+		LIST_INSERT_HEAD(&sc->sc_rts[h], p, brt_next);
+		sc->sc_brtcnt++;
+		goto want;
+	}
+
+	do {
+		q = p;
+		p = LIST_NEXT(p, brt_next);
+
+		dir = bcmp(ea, &q->brt_addr, sizeof(q->brt_addr));
+		if (dir == 0) {
+			if (setflags) {
+				q->brt_if = ifp;
+				q->brt_flags = flags;
+			}
+
+			if (q->brt_if == ifp)
+				q->brt_age = 1;
+			ifp = q->brt_if;
+			goto want;
+		}
+
+		if (dir > 0) {
+			if (sc->sc_brtcnt >= sc->sc_brtmax)
+				goto done;
+			p = (struct bridge_rtnode *)malloc(
+			    sizeof(struct bridge_rtnode), M_DEVBUF, M_NOWAIT);
+			if (p == NULL)
+				goto done;
+
+			bcopy(ea, &p->brt_addr, sizeof(p->brt_addr));
+			p->brt_if = ifp;
+			p->brt_age = 1;
+
+			if (setflags)
+				p->brt_flags = flags;
+			else
+				p->brt_flags = IFBAF_DYNAMIC;
+
+			LIST_INSERT_BEFORE(q, p, brt_next);
+			sc->sc_brtcnt++;
+			goto want;
+		}
+
+		if (p == NULL) {
+			if (sc->sc_brtcnt >= sc->sc_brtmax)
+				goto done;
+			p = (struct bridge_rtnode *)malloc(
+			    sizeof(struct bridge_rtnode), M_DEVBUF, M_NOWAIT);
+			if (p == NULL)
+				goto done;
+
+			bcopy(ea, &p->brt_addr, sizeof(p->brt_addr));
+			p->brt_if = ifp;
+			p->brt_age = 1;
+
+			if (setflags)
+				p->brt_flags = flags;
+			else
+				p->brt_flags = IFBAF_DYNAMIC;
+			LIST_INSERT_AFTER(q, p, brt_next);
+			sc->sc_brtcnt++;
+			goto want;
+		}
+	} while (p != NULL);
+
+done:
+	ifp = NULL;
+want:
+	splx(s);
+	return (ifp);
+}
+
+struct ifnet *
+bridge_rtlookup(sc, ea)
+	struct bridge_softc *sc;
+	struct ether_addr *ea;
+{
+	struct bridge_rtnode *p;
+	u_int32_t h;
+	int s, dir;
+
+	/*
+	 * Lock out everything else
+	 */
+	s = splhigh();
+
+	if (sc->sc_rts == NULL)
+		goto fail;
+
+	h = bridge_hash(ea);
+	p = LIST_FIRST(&sc->sc_rts[h]);
+	while (p != NULL) {
+		dir = bcmp(ea, &p->brt_addr, sizeof(p->brt_addr));
+		if (dir == 0) {
+			splx(s);
+			return (p->brt_if);
+		}
+		if (dir > 0)
+			goto fail;
+		p = LIST_NEXT(p, brt_next);
+	}
+fail:
+	splx(s);
+	return (NULL);
+}
+
+/*
+ * The following hash function is adapted from 'Hash Functions' by Bob Jenkins
+ * ("Algorithm Alley", Dr. Dobbs Journal, September 1997).
+ * "You may use this code any way you wish, private, educational, or
+ *  commercial.  It's free."
+ */
+#define	mix(a,b,c) \
+	do {						\
+		a -= b; a -= c; a ^= (c >> 13);		\
+		b -= c; b -= a; b ^= (a << 8);		\
+		c -= a; c -= b; c ^= (b >> 13);		\
+		a -= b; a -= c; a ^= (c >> 12);		\
+		b -= c; b -= a; b ^= (a << 16);		\
+		c -= a; c -= b; c ^= (b >> 5);		\
+		a -= b; a -= c; a ^= (c >> 3);		\
+		b -= c; b -= a; b ^= (a << 10);		\
+		c -= a; c -= b; c ^= (b >> 15);		\
+	} while(0)
+
+u_int32_t
+bridge_hash(addr)
+	struct ether_addr *addr;
+{
+	u_int32_t a = 0x9e3779b9, b = 0x9e3779b9, c = 0xdeadbeef;
+
+	b += addr->ether_addr_octet[5] << 8;
+	b += addr->ether_addr_octet[4];
+	a += addr->ether_addr_octet[3] << 24;
+	a += addr->ether_addr_octet[2] << 16;
+	a += addr->ether_addr_octet[1] << 8;
+	a += addr->ether_addr_octet[0];
+
+	mix(a, b, c);
+	return (c & BRIDGE_RTABLE_MASK);
+}
+
+/*
+ * Trim the routing table so that we've got a number of routes
+ * less than or equal to the maximum.
+ */
+void
+bridge_rttrim(sc)
+	struct bridge_softc *sc;
+{
+	struct bridge_rtnode *n, *p;
+	int s, i;
+
+	s = splhigh();
+	if (sc->sc_rts == NULL)
+		goto done;
+
+	/*
+	 * Make sure we have to trim the address table
+	 */
+	if (sc->sc_brtcnt <= sc->sc_brtmax)
+		goto done;
+
+	/*
+	 * Force an aging cycle, this might trim enough addresses.
+	 */
+	splx(s);
+	bridge_rtage(sc);
+	s = splhigh();
+
+	if (sc->sc_brtcnt <= sc->sc_brtmax)
+		goto done;
+
+	for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) {
+		n = LIST_FIRST(&sc->sc_rts[i]);
+		while (n != NULL) {
+			p = LIST_NEXT(n, brt_next);
+			if ((n->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
+				LIST_REMOVE(n, brt_next);
+				sc->sc_brtcnt--;
+				free(n, M_DEVBUF);
+				n = p;
+				if (sc->sc_brtcnt <= sc->sc_brtmax)
+					goto done;
+			}
+		}
+	}
+
+done:
+	if (sc->sc_rts != NULL && sc->sc_brtcnt == 0 &&
+	    (sc->sc_if.if_flags & IFF_UP) == 0) {
+		free(sc->sc_rts, M_DEVBUF);
+		sc->sc_rts = NULL;
+	}
+
+	splx(s);
+}
+
+/*
+ * Perform an aging cycle
+ */
+void
+bridge_rtage(vsc)
+	void *vsc;
+{
+	struct bridge_softc *sc = (struct bridge_softc *)vsc;
+	struct bridge_rtnode *n, *p;
+	int s, i;
+
+	s = splhigh();
+	if (sc->sc_rts == NULL) {
+		splx(s);
+		return;
+	}
+
+	for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) {
+		n = LIST_FIRST(&sc->sc_rts[i]);
+		while (n != NULL) {
+			if ((n->brt_flags & IFBAF_TYPEMASK) == IFBAF_STATIC) {
+				n->brt_age = !n->brt_age;
+				if (n->brt_age)
+					n->brt_age = 0;
+				n = LIST_NEXT(n, brt_next);
+			}
+			else if (n->brt_age) {
+				n->brt_age = 0;
+				n = LIST_NEXT(n, brt_next);
+			}
+			else {
+				p = LIST_NEXT(n, brt_next);
+				LIST_REMOVE(n, brt_next);
+				sc->sc_brtcnt--;
+				free(n, M_DEVBUF);
+				n = p;
+			}
+		}
+	}
+	splx(s);
+
+	if (sc->sc_brttimeout != 0)
+		timeout(bridge_rtage, sc, sc->sc_brttimeout * hz);
+}
+
+/*
+ * Remove all dynamic addresses from the cache
+ */
+int
+bridge_rtflush(sc, full)
+	struct bridge_softc *sc;
+	int full;
+{
+	int s, i;
+	struct bridge_rtnode *p, *n;
+
+	s = splhigh();
+	if (sc->sc_rts == NULL)
+		goto done;
+
+	for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) {
+		n = LIST_FIRST(&sc->sc_rts[i]);
+		while (n != NULL) {
+			if (full ||
+			    (n->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
+				p = LIST_NEXT(n, brt_next);
+				LIST_REMOVE(n, brt_next);
+				sc->sc_brtcnt--;
+				free(n, M_DEVBUF);
+				n = p;
+			} else
+				n = LIST_NEXT(n, brt_next);
+		}
+	}
+
+	if (sc->sc_brtcnt == 0 && (sc->sc_if.if_flags & IFF_UP) == 0) {
+		free(sc->sc_rts, M_DEVBUF);
+		sc->sc_rts = NULL;
+	}
+
+done:
+	splx(s);
+	return (0);
+}
+
+/*
+ * Remove an address from the cache
+ */
+int
+bridge_rtdaddr(sc, ea)
+	struct bridge_softc *sc;
+	struct ether_addr *ea;
+{
+	int h, s;
+	struct bridge_rtnode *p;
+
+	s = splhigh();
+	if (sc->sc_rts == NULL)
+		goto done;
+
+	h = bridge_hash(ea);
+	p = LIST_FIRST(&sc->sc_rts[h]);
+	while (p != NULL) {
+		if (bcmp(ea, &p->brt_addr, sizeof(p->brt_addr)) == 0) {
+			LIST_REMOVE(p, brt_next);
+			sc->sc_brtcnt--;
+			free(p, M_DEVBUF);
+			if (sc->sc_brtcnt == 0 &&
+			    (sc->sc_if.if_flags & IFF_UP) == 0) {
+				free(sc->sc_rts, M_DEVBUF);
+				sc->sc_rts = NULL;
+			}
+			splx(s);
+			return (0);
+		}
+		p = LIST_NEXT(p, brt_next);
+	}
+
+done:
+	splx(s);
+	return (ENOENT);
+}
+/*
+ * Delete routes to a specific interface member.
+ */
+void
+bridge_rtdelete(sc, ifp)
+	struct bridge_softc *sc;
+	struct ifnet *ifp;
+{
+	int i, s;
+	struct bridge_rtnode *n, *p;
+
+	s = splhigh();
+	if (sc->sc_rts == NULL)
+		goto done;
+
+	/*
+	 * Loop through all of the hash buckets and traverse each
+	 * chain looking for routes to this interface.
+	 */
+	for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) {
+		n = LIST_FIRST(&sc->sc_rts[i]);
+		while (n != NULL) {
+			if (n->brt_if == ifp) {		/* found one */
+				p = LIST_NEXT(n, brt_next);
+				LIST_REMOVE(n, brt_next);
+				sc->sc_brtcnt--;
+				free(n, M_DEVBUF);
+				n = p;
+			} else
+				n = LIST_NEXT(n, brt_next);
+		}
+	}
+	if (sc->sc_brtcnt == 0 && (sc->sc_if.if_flags & IFF_UP) == 0) {
+		free(sc->sc_rts, M_DEVBUF);
+		sc->sc_rts = NULL;
+	}
+
+done:
+	splx(s);
+}
+
+/*
+ * Gather all of the routes for this interface.
+ */
+int
+bridge_rtfind(sc, baconf)
+	struct bridge_softc *sc;
+	struct ifbaconf *baconf;
+{
+	int i, s, error = 0;
+	u_int32_t cnt = 0;
+	struct bridge_rtnode *n;
+	struct ifbareq bareq;
+
+	s = splhigh();
+
+	if (sc->sc_rts == NULL || baconf->ifbac_len == 0)
+		goto done;
+
+	for (i = 0, cnt = 0; i < BRIDGE_RTABLE_SIZE; i++) {
+		n = LIST_FIRST(&sc->sc_rts[i]);
+		while (n != NULL) {
+			if (baconf->ifbac_len <
+			    (cnt + 1) * sizeof(struct ifbareq))
+				goto done;
+			bcopy(sc->sc_if.if_xname, bareq.ifba_name,
+			    sizeof(bareq.ifba_name));
+			bcopy(n->brt_if->if_xname, bareq.ifba_ifsname,
+			    sizeof(bareq.ifba_ifsname));
+			bcopy(&n->brt_addr, &bareq.ifba_dst,
+			    sizeof(bareq.ifba_dst));
+			bareq.ifba_age = n->brt_age;
+			bareq.ifba_flags = n->brt_flags;
+			error = copyout((caddr_t)&bareq,
+		    	    (caddr_t)(baconf->ifbac_req + cnt), sizeof(bareq));
+			if (error)
+				goto done;
+			n = LIST_NEXT(n, brt_next);
+			cnt++;
+		}
+	}
+done:
+	baconf->ifbac_len = cnt * sizeof(struct ifbareq);
+	splx(s);
+	return (error);
+}
+
+struct mbuf *
+bridge_blocknonip(m)
+	struct mbuf *m;
+{
+	struct ehllc *ehllc;
+	u_int16_t etype;
+
+	if (m->m_len < sizeof(struct ehllc)) {
+		m = m_pullup(m, sizeof(struct ehllc));
+		if (m == NULL)
+			return (m);
+	}
+
+	ehllc = mtod(m, struct ehllc *);
+	etype = ntohs(ehllc->eh.ether_type);
+
+	if (etype == ETHERTYPE_ARP || etype == ETHERTYPE_REVARP ||
+	    etype == ETHERTYPE_IP  || etype == ETHERTYPE_IPV6)
+		return (m);
+
+	if (etype > ETHERMTU)
+		goto notip;
+
+	if (ehllc->llc.llc_control == LLC_UI &&
+	    ehllc->llc.llc_dsap == LLC_SNAP_LSAP &&
+	    ehllc->llc.llc_ssap == LLC_SNAP_LSAP) {
+		etype = ntohs(ehllc->llc.llc_snap.ether_type);
+		if (etype == ETHERTYPE_ARP || etype == ETHERTYPE_REVARP ||
+		    etype == ETHERTYPE_IP  || etype == ETHERTYPE_IPV6)
+			return (m);
+	}
+
+notip:
+	m_freem(m);
+	return (NULL);
+}
+
+u_int8_t
+bridge_filterrule(n, eh)
+	struct brl_node *n;
+	struct ether_header *eh;
+{
+	u_int8_t flags;
+
+	for (; n != NULL; n = SIMPLEQ_NEXT(n, brl_next)) {
+		flags = n->brl_flags & (BRL_FLAG_SRCVALID|BRL_FLAG_DSTVALID);
+		if (flags == 0)
+			return (n->brl_action);
+		if (flags == (BRL_FLAG_SRCVALID|BRL_FLAG_DSTVALID)) {
+			if (bcmp(eh->ether_shost, &n->brl_src, ETHER_ADDR_LEN))
+				continue;
+			if (bcmp(eh->ether_dhost, &n->brl_src, ETHER_ADDR_LEN))
+				continue;
+			return (n->brl_action);
+		}
+		if (flags == BRL_FLAG_SRCVALID) {
+			if (bcmp(eh->ether_shost, &n->brl_src, ETHER_ADDR_LEN))
+				continue;
+			return (n->brl_action);
+		}
+		if (flags == BRL_FLAG_DSTVALID) {
+			if (bcmp(eh->ether_dhost, &n->brl_dst, ETHER_ADDR_LEN))
+				continue;
+			return (n->brl_action);
+		}
+	}
+	return (BRL_ACTION_PASS);
+}
+
+int
+bridge_addrule(bif, req, out)
+	struct bridge_iflist *bif;
+	struct ifbrlreq *req;
+	int out;
+{
+	struct brl_node *n;
+
+	n = (struct brl_node *)malloc(sizeof(struct brl_node), M_DEVBUF, M_NOWAIT);
+	if (n == NULL)
+		return (ENOMEM);
+	bcopy(&req->ifbr_src, &n->brl_src, sizeof(struct ether_addr));
+	bcopy(&req->ifbr_dst, &n->brl_dst, sizeof(struct ether_addr));
+	n->brl_action = req->ifbr_action;
+	n->brl_flags = req->ifbr_flags;
+	if (out) {
+		n->brl_flags &= ~BRL_FLAG_IN;
+		n->brl_flags |= BRL_FLAG_OUT;
+		SIMPLEQ_INSERT_TAIL(&bif->bif_brlout, n, brl_next);
+	}
+	else {
+		n->brl_flags &= ~BRL_FLAG_OUT;
+		n->brl_flags |= BRL_FLAG_IN;
+		SIMPLEQ_INSERT_TAIL(&bif->bif_brlin, n, brl_next);
+	}
+	return (0);
+}
+
+int
+bridge_flushrule(bif)
+	struct bridge_iflist *bif;
+{
+	struct brl_node *p, *q;
+
+	p = SIMPLEQ_FIRST(&bif->bif_brlin);
+	while (p != NULL) {
+		q = SIMPLEQ_NEXT(p, brl_next);
+		SIMPLEQ_REMOVE_HEAD(&bif->bif_brlin, p, brl_next);
+		free(p, M_DEVBUF);
+		p = q;
+	}
+	p = SIMPLEQ_FIRST(&bif->bif_brlout);
+	while (p != NULL) {
+		q = SIMPLEQ_NEXT(p, brl_next);
+		SIMPLEQ_REMOVE_HEAD(&bif->bif_brlout, p, brl_next);
+		free(p, M_DEVBUF);
+		p = q;
+	}
+	return (0);
+}
+
+#if defined(INET) && (defined(IPFILTER) || defined(IPFILTER_LKM))
+
+/*
+ * Filter IP packets by peeking into the ethernet frame.  This violates
+ * the ISO model, but allows us to act as a IP filter at the data link
+ * layer.  As a result, most of this code will look familiar to those
+ * who've read net/if_ethersubr.c and netinet/ip_input.c
+ */
+int
+bridge_filter(sc, ifp, eh, np)
+	struct bridge_softc *sc;
+	struct ifnet *ifp;
+	struct ether_header *eh;
+	struct mbuf **np;
+{
+	struct mbuf *m = *np;
+	struct ehllc *ehllc;
+	struct ip *ip;
+	u_int16_t etype;
+	int hlen, r, off = sizeof(struct ether_header);
+
+	if (fr_checkp == NULL)
+		return (BRIDGE_FILTER_PASS);
+
+	if (m->m_len < sizeof(struct ehllc)) {
+		m = m_pullup(m, sizeof(struct ehllc));
+		*np = m;
+		if (m == NULL)
+			return (BRIDGE_FILTER_DROP);
+	}
+
+	ehllc = mtod(m, struct ehllc *);
+	etype = ntohs(ehllc->eh.ether_type);
+	if (etype != ETHERTYPE_IP) {
+		if (etype > ETHERMTU)	/* Can't be SNAP */
+			return (BRIDGE_FILTER_PASS);
+
+		if (ehllc->llc.llc_control != LLC_UI ||
+		    ehllc->llc.llc_dsap != LLC_SNAP_LSAP ||
+		    ehllc->llc.llc_ssap != LLC_SNAP_LSAP ||
+		    ehllc->llc.llc_snap.org_code[0] != 0 ||
+		    ehllc->llc.llc_snap.org_code[1] != 0 ||
+		    ehllc->llc.llc_snap.org_code[2] != 0 ||
+		    ntohs(ehllc->llc.llc_snap.ether_type) != ETHERTYPE_IP)
+			return (BRIDGE_FILTER_PASS);
+		off += 8;
+	}
+
+	/*
+	 * We need a full copy because we're going to be destructive
+	 * to the packet before we pass it to the ip filter code.
+	 * XXX This needs to be turned into a munge -> check ->
+	 * XXX unmunge section, for now, we copy.
+	 * XXX Copy at offset 0 so that the mbuf header is copied, too.
+	 */
+	m = m_copym2(m, 0, M_COPYALL, M_NOWAIT);
+	m_adj(m, off);
+	if (m == NULL)
+		return (BRIDGE_FILTER_DROP);
+
+	/*
+	 * Pull up the IP header
+	 */
+	if (m->m_len < sizeof(struct ip)) {
+		m = m_pullup(m, sizeof(struct ip));
+		if (m == NULL)
+			return (BRIDGE_FILTER_DROP);
+	}
+
+	/*
+	 * Examine the ip header, and drop invalid packets
+	 */
+	ip = mtod(m, struct ip *);
+	if (ip->ip_v != IPVERSION) {
+		r = BRIDGE_FILTER_DROP;
+		goto out;
+	}
+
+	hlen = ip->ip_hl << 2;		/* get whole header length */
+	if (hlen < sizeof(struct ip)) {
+		r = BRIDGE_FILTER_DROP;
+		goto out;
+	}
+	if (hlen > m->m_len) {		/* pull up whole header */
+		if ((m = m_pullup(m, hlen)) == 0) {
+			r = BRIDGE_FILTER_DROP;
+			goto out;
+		}
+		ip = mtod(m, struct ip *);
+	}
+	if ((ip->ip_sum = in_cksum(m, hlen)) != 0) {
+		r = BRIDGE_FILTER_DROP;
+		goto out;
+	}
+
+	NTOHS(ip->ip_len);
+	if (ip->ip_len < hlen) {
+		r = BRIDGE_FILTER_DROP;
+		goto out;
+	}
+	NTOHS(ip->ip_id);
+	NTOHS(ip->ip_off);
+
+	if (m->m_pkthdr.len < ip->ip_len) {
+		r = BRIDGE_FILTER_DROP;
+		goto out;
+	}
+	if (m->m_pkthdr.len > ip->ip_len) {
+		if (m->m_len == m->m_pkthdr.len) {
+			m->m_len = ip->ip_len;
+			m->m_pkthdr.len = ip->ip_len;
+		} else
+			m_adj(m, ip->ip_len - m->m_pkthdr.len);
+	}
+
+	/* Finally, we get to filter the packet! */
+	if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 0, &m))
+		return (BRIDGE_FILTER_DROP);
+
+	r = BRIDGE_FILTER_PASS;
+
+out:
+	m_freem(m);
+	return (r);
+}
+#endif
+
+int
+ifpromisc(ifp, pswitch)
+	struct ifnet *ifp;
+	int pswitch;
+{
+	struct ifreq ifr;
+
+	if (pswitch) {
+		/*
+		 * If the device is not configured up, we cannot put it in
+		 * promiscuous mode.
+		 */
+		if ((ifp->if_flags & IFF_UP) == 0)
+			return (ENETDOWN);
+		if (ifp->if_pcount++ != 0)
+			return (0);
+		ifp->if_flags |= IFF_PROMISC;
+	} else {
+		if (--ifp->if_pcount > 0)
+			return (0);
+		ifp->if_flags &= ~IFF_PROMISC;
+		/*
+		 * If the device is not configured up, we should not need to
+		 * turn off promiscuous mode (device should have turned it
+		 * off when interface went down; and will look at IFF_PROMISC
+		 * again next time interface comes up).
+		 */
+		if ((ifp->if_flags & IFF_UP) == 0)
+			return (0);
+	}
+	ifr.ifr_flags = ifp->if_flags;
+	return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
+}
+
+#endif  /* NBRIDGE */
new file mode 100644
--- /dev/null
+++ b/packages/net/tcpip/current/tests/bridge.c
@@ -0,0 +1,1009 @@
+//==========================================================================
+//
+//      tests/bridge.c
+//
+//     
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//####BSDCOPYRIGHTBEGIN####
+//
+// -------------------------------------------
+//
+// Portions of this software may have been derived from OpenBSD or other sources,
+// and are covered by the appropriate copyright disclaimers included herein.
+//
+// -------------------------------------------
+//
+//####BSDCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Jason L. Wright (jason@thought.net)
+// Contributors: andrew.lunn@ascom.ch (Andrew Lunn), hmt
+// Date:         2000-01-10
+// Purpose:      
+// Description:  
+//              
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+
+/*	$OpenBSD: brconfig.c,v 1.6 2000/02/04 06:32:04 deraadt Exp $	*/
+
+/*
+ * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
+ * 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 Jason L. Wright
+ * 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.
+ */
+
+#include <stdio.h>
+#include <network.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <net/if_bridge.h>
+#include <sys/errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <assert.h>
+#include <ctype.h>
+
+void bridge_usage __P((void));
+int main __P((int, char **));
+int bridge_setflag __P((int, char *, short));
+int bridge_clrflag __P((int, char *, short));
+int bridge_ifsetflag __P((int, char *, char *, u_int32_t));
+int bridge_ifclrflag __P((int, char *, char *, u_int32_t));
+int bridge_list __P((int, char *, char *));
+int bridge_addrs __P((int, char *, char *));
+int bridge_addaddr __P((int, char *, char *, char *));
+int bridge_deladdr __P((int, char *, char *));
+int bridge_maxaddr __P((int, char *, char *));
+int bridge_timeout __P((int, char *, char *));
+int bridge_flush __P((int, char *));
+int bridge_flushall __P((int, char *));
+int bridge_add __P((int, char *, char *));
+int bridge_delete __P((int, char *, char *));
+int bridge_status __P((int, char *));
+int is_bridge __P((int, char *));
+int bridge_show_all __P((int));
+void printb __P((char *, unsigned short, char *));
+int bridge_rule __P((int, char *, int, char **, int));
+int bridge_rules __P((int, char *, char *, char *));
+int bridge_flush_rule __P((int, char *, char *));
+void bridge_badrule __P((int, char **, int));
+void bridge_showrule __P((struct ifbrlreq *, char *));
+int bridge_rulefile __P((int, char *, char *));
+
+/* if_flags bits: borrowed from ifconfig.c */
+#define	IFFBITS \
+"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\
+\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST"
+
+#define	IFBAFBITS	"\020\1STATIC"
+#define	IFBIFBITS	"\020\1LEARNING\2DISCOVER\3BLOCKNONIP\4BLOCKARP"
+
+#define warnx(x) diag_printf(x);
+#define warnx2(x,y) diag_printf(x,y) 
+#define warnx3(x,y,z) diag_printf(x,y,z) 
+#define err(x,y) assert(0);
+extern  int cyg_kmem_print_stats(void);
+
+static char * _ether_aton __P((char *, struct ether_addr *));
+
+char *
+ether_ntoa(e)
+	struct ether_addr *e;
+{
+	static char a[] = "xx:xx:xx:xx:xx:xx";
+
+	if (e->ether_addr_octet[0] > 0xFF || e->ether_addr_octet[1] > 0xFF ||
+	    e->ether_addr_octet[2] > 0xFF || e->ether_addr_octet[3] > 0xFF ||
+	    e->ether_addr_octet[4] > 0xFF || e->ether_addr_octet[5] > 0xFF) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	(void)sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x",
+	    e->ether_addr_octet[0], e->ether_addr_octet[1],
+	    e->ether_addr_octet[2], e->ether_addr_octet[3],
+	    e->ether_addr_octet[4], e->ether_addr_octet[5]);
+
+	return (a);
+}
+
+static char *
+_ether_aton(s, e)
+	char *s;
+	struct ether_addr *e;
+{
+	int i;
+	long l;
+	char *pp;
+
+	while (isspace(*s))
+		s++;
+
+	/* expect 6 hex octets separated by ':' or space/NUL if last octet */
+	for (i = 0; i < 6; i++) {
+		l = strtol(s, &pp, 16);
+		if (pp == s || l > 0xFF || l < 0)
+			return (NULL);
+		if (!(*pp == ':' || (i == 5 && (isspace(*pp) || *pp == '\0'))))
+			return (NULL);
+		e->ether_addr_octet[i] = (u_char)l;
+		s = pp + 1;
+	}
+
+	/* return character after the octets ala strtol(3) */
+	return (pp);
+}
+
+struct ether_addr *
+ether_aton(s)
+	char *s;
+{
+	static struct ether_addr n;
+
+	return (_ether_aton(s, &n) ? &n : NULL);
+}
+
+void
+bridge_usage()
+{
+	diag_printf("usage: brconfig -a\n");
+	diag_printf(
+	    "usage: brconfig interface [up] [down] [add if] [del if] ...\n");
+}
+
+
+int
+bridge_ifsetflag(s, brdg, ifsname, flag)
+	int s;
+	char *brdg, *ifsname;
+	u_int32_t flag;
+{
+	struct ifbreq req;
+
+	strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name));
+	strncpy(req.ifbr_ifsname, ifsname, sizeof(req.ifbr_ifsname));
+	if (ioctl(s, SIOCBRDGGIFFLGS, (caddr_t)&req) < 0) {
+		return (1);
+	}
+
+	req.ifbr_ifsflags |= flag;
+
+	if (ioctl(s, SIOCBRDGSIFFLGS, (caddr_t)&req) < 0) {
+		warnx3("%s: %s", brdg, ifsname);
+		return (1);
+	}
+	return (0);
+}
+
+int
+bridge_ifclrflag(s, brdg, ifsname, flag)
+	int s;
+	char *brdg, *ifsname;
+	u_int32_t flag;
+{
+	struct ifbreq req;
+
+	strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name));
+	strncpy(req.ifbr_ifsname, ifsname, sizeof(req.ifbr_ifsname));
+
+	if (ioctl(s, SIOCBRDGGIFFLGS, (caddr_t)&req) < 0) {
+		warnx3("%s: %s", brdg, ifsname);
+		return (1);
+	}
+
+	req.ifbr_ifsflags &= ~flag;
+
+	if (ioctl(s, SIOCBRDGSIFFLGS, (caddr_t)&req) < 0) {
+		warnx3("%s: %s", brdg, ifsname);
+		return (1);
+	}
+	return (0);
+}
+
+int
+bridge_show_all(s)
+	int s;
+{
+	char *inbuf = NULL;
+	struct ifconf ifc;
+	struct ifreq *ifrp, ifreq;
+	int len = 8192, i;
+
+	while (1) {
+		ifc.ifc_len = len;
+		ifc.ifc_buf = inbuf = realloc(inbuf, len);
+		if (inbuf == NULL)
+			err(1, "malloc");
+		if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
+			err(1, "ioctl(SIOCGIFCONF)");
+		if (ifc.ifc_len + sizeof(struct ifreq) < len)
+			break;
+		len *= 2;
+	}
+	ifrp = ifc.ifc_req;
+	ifreq.ifr_name[0] = '\0';
+	for (i = 0; i < ifc.ifc_len; ) {
+		ifrp = (struct ifreq *)((caddr_t)ifc.ifc_req + i);
+		i += sizeof(ifrp->ifr_name) +
+		    (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr) ?
+		    ifrp->ifr_addr.sa_len : sizeof(struct sockaddr));
+		if (ifrp->ifr_addr.sa_family != AF_LINK)
+			continue;
+		if (!is_bridge(s, ifrp->ifr_name))
+			continue;
+		bridge_status(s, ifrp->ifr_name);
+	}
+        free(ifc.ifc_buf);
+	return (0);
+}
+
+int
+bridge_setflag(s, brdg, f)
+	int s;
+	char *brdg;
+	short f;
+{
+	struct ifreq ifr;
+
+	strncpy(ifr.ifr_name, brdg, sizeof(ifr.ifr_name));
+
+	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
+		warnx2("%s", brdg);
+		if (errno == EPERM)
+			return (1);
+		return (1);
+	}
+
+	ifr.ifr_flags |= f;
+
+	if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) {
+		warnx2("%s", brdg);
+		if (errno == EPERM)
+			return (1);
+		return (1);
+	}
+
+	return (0);
+}
+
+int
+bridge_clrflag(s, brdg, f)
+	int s;
+	char *brdg;
+	short f;
+{
+	struct ifreq ifr;
+
+	strncpy(ifr.ifr_name, brdg, sizeof(ifr.ifr_name));
+
+	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
+		warnx2("%s", brdg);
+		if (errno == EPERM)
+			return (1);
+		return (1);
+	}
+
+	ifr.ifr_flags &= ~(f);
+
+	if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) {
+		warnx2("%s", brdg);
+		if (errno == EPERM)
+			return (1);
+		return (1);
+	}
+
+	return (0);
+}
+
+int
+bridge_flushall(s, brdg)
+	int s;
+	char *brdg;
+{
+	struct ifbreq req;
+
+	strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name));
+	req.ifbr_ifsflags = IFBF_FLUSHALL;
+	if (ioctl(s, SIOCBRDGFLUSH, &req) < 0) {
+		warnx2("%s", brdg);
+		return (1);
+	}
+	return (0);
+}
+
+int
+bridge_flush(s, brdg)
+	int s;
+	char *brdg;
+{
+	struct ifbreq req;
+
+	strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name));
+	req.ifbr_ifsflags = IFBF_FLUSHDYN;
+	if (ioctl(s, SIOCBRDGFLUSH, &req) < 0) {
+		warnx2("%s", brdg);
+		return (1);
+	}
+	return (0);
+}
+
+int
+bridge_list(s, brdg, delim)
+	int s;
+	char *brdg, *delim;
+{
+	struct ifbreq *reqp;
+	struct ifbifconf bifc;
+	int i, len = 8192;
+	char buf[sizeof(reqp->ifbr_ifsname) + 1], *inbuf = NULL;
+
+	while (1) {
+		strncpy(bifc.ifbic_name, brdg, sizeof(bifc.ifbic_name));
+		bifc.ifbic_len = len;
+		bifc.ifbic_buf = inbuf = realloc(inbuf, len);
+		if (inbuf == NULL)
+			err(1, "malloc");
+		if (ioctl(s, SIOCBRDGIFS, &bifc) < 0)
+			err(1, brdg);
+		if (bifc.ifbic_len + sizeof(*reqp) < len)
+			break;
+		len *= 2;
+	}
+	for (i = 0; i < bifc.ifbic_len / sizeof(*reqp); i++) {
+		reqp = bifc.ifbic_req + i;
+		strncpy(buf, reqp->ifbr_ifsname, sizeof(buf));
+		diag_printf("%s%s ", delim, buf);
+		printb("flags", reqp->ifbr_ifsflags, IFBIFBITS);
+		diag_printf("\n");
+		bridge_rules(s, brdg, buf, delim);
+	}
+	free(bifc.ifbic_buf);
+	return (0);             /* NOTREACHED */
+}
+
+int
+bridge_add(s, brdg, ifn)
+	int s;
+	char *brdg, *ifn;
+{
+	struct ifbreq req;
+
+	strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name));
+	strncpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
+	if (ioctl(s, SIOCBRDGADD, &req) < 0) {
+		warnx3("%s: %s", brdg, ifn);
+		if (errno == EPERM)
+			return (1);
+		return (1);
+	}
+	return (0);
+}
+
+int
+bridge_delete(s, brdg, ifn)
+	int s;
+	char *brdg, *ifn;
+{
+	struct ifbreq req;
+
+	strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name));
+	strncpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
+	if (ioctl(s, SIOCBRDGDEL, &req) < 0) {
+		warnx3("%s: %s", brdg, ifn);
+		if (errno == EPERM)
+			return (1);
+		return (1);
+	}
+	return (0);
+}
+
+int
+bridge_timeout(s, brdg, arg)
+	int s;
+	char *brdg, *arg;
+{
+	struct ifbcachetoreq ifbct;
+	u_int32_t newtime;
+	char *endptr;
+
+	newtime = strtoul(arg, &endptr, 0);
+	if (arg[0] == '\0' || endptr[0] != '\0') {
+		diag_printf("invalid arg for timeout: %s\n", arg);
+		return (1);
+	}
+
+	strncpy(ifbct.ifbct_name, brdg, sizeof(ifbct.ifbct_name));
+	ifbct.ifbct_time = newtime;
+	if (ioctl(s, SIOCBRDGSTO, (caddr_t)&ifbct) < 0) {
+		warnx2("%s", brdg);
+		return (1);
+	}
+	return (0);
+}
+
+int
+bridge_maxaddr(s, brdg, arg)
+	int s;
+	char *brdg, *arg;
+{
+	struct ifbcachereq ifbc;
+	u_int32_t newsize;
+	char *endptr;
+
+	newsize = strtoul(arg, &endptr, 0);
+	if (arg[0] == '\0' || endptr[0] != '\0') {
+		diag_printf("invalid arg for maxaddr: %s\n", arg);
+		return (1);
+	}
+
+	strncpy(ifbc.ifbc_name, brdg, sizeof(ifbc.ifbc_name));
+	ifbc.ifbc_size = newsize;
+	if (ioctl(s, SIOCBRDGSCACHE, (caddr_t)&ifbc) < 0) {
+		warnx2("%s", brdg);
+		return (1);
+	}
+	return (0);
+}
+
+int
+bridge_deladdr(s, brdg, addr)
+	int s;
+	char *brdg, *addr;
+{
+	struct ifbareq ifba;
+	struct ether_addr *ea;
+
+	strncpy(ifba.ifba_name, brdg, sizeof(ifba.ifba_name));
+	ea = ether_aton(addr);
+	if (ea == NULL) {
+		warnx2("Invalid address: %s", addr);
+		return (1);
+	}
+	bcopy(ea, &ifba.ifba_dst, sizeof(struct ether_addr));
+
+	if (ioctl(s, SIOCBRDGDADDR, &ifba) < 0) {
+		warnx3("%s: %s", brdg, addr);
+		return (1);
+	}
+
+	return (0);
+}
+
+int
+bridge_addaddr(s, brdg, ifname, addr)
+	int s;
+	char *brdg, *ifname, *addr;
+{
+	struct ifbareq ifba;
+	struct ether_addr *ea;
+
+	strncpy(ifba.ifba_name, brdg, sizeof(ifba.ifba_name));
+	strncpy(ifba.ifba_ifsname, ifname, sizeof(ifba.ifba_ifsname));
+
+	ea = ether_aton(addr);
+	if (ea == NULL) {
+		warnx2("Invalid address: %s", addr);
+		return (1);
+	}
+	bcopy(ea, &ifba.ifba_dst, sizeof(struct ether_addr));
+	ifba.ifba_flags = IFBAF_STATIC;
+
+	if (ioctl(s, SIOCBRDGSADDR, &ifba) < 0) {
+		warnx3("%s: %s", brdg, addr);
+		return (1);
+	}
+
+	return (0);
+}
+
+int
+bridge_addrs(s, brdg, delim)
+	int s;
+	char *brdg, *delim;
+{
+	struct ifbaconf ifbac;
+	struct ifbareq *ifba;
+	char *inbuf = NULL, buf[sizeof(ifba->ifba_ifsname) + 1];
+	int i, len = 8192;
+
+	while (1) {
+		ifbac.ifbac_len = len;
+		ifbac.ifbac_buf = inbuf = realloc(inbuf, len);
+		strncpy(ifbac.ifbac_name, brdg, sizeof(ifbac.ifbac_name));
+		if (inbuf == NULL)
+			err(1, "malloc");
+		if (ioctl(s, SIOCBRDGRTS, &ifbac) < 0) {
+			if (errno == ENETDOWN)
+				return (0);
+			err(1, brdg);
+		}
+		if (ifbac.ifbac_len + sizeof(*ifba) < len)
+			break;
+		len *= 2;
+	}
+
+	for (i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) {
+		ifba = ifbac.ifbac_req + i;
+		strncpy(buf, ifba->ifba_ifsname, sizeof(buf));
+		diag_printf("%s%s %s %d ", delim, ether_ntoa(&ifba->ifba_dst),
+		    buf, ifba->ifba_age);
+		printb("flags", ifba->ifba_flags, IFBAFBITS);
+		diag_printf("\n");
+	}
+        free(ifbac.ifbac_buf);
+	return (0);
+}
+
+/*
+ * Check to make sure 'brdg' is really a bridge interface.
+ */
+int
+is_bridge(s, brdg)
+	int s;
+	char *brdg;
+{
+	struct ifreq ifr;
+	struct ifbaconf ifbac;
+
+	strncpy(ifr.ifr_name, brdg, sizeof(ifr.ifr_name));
+
+	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0)
+		return (0);
+
+	ifbac.ifbac_len = 0;
+	strncpy(ifbac.ifbac_name, brdg, sizeof(ifbac.ifbac_name));
+	if (ioctl(s, SIOCBRDGRTS, (caddr_t)&ifbac) < 0) {
+		if (errno == ENETDOWN)
+			return (1);
+		return (0);
+	}
+	return (1);
+}
+
+int
+bridge_status(s, brdg)
+	int s;
+	char *brdg;
+{
+	struct ifreq ifr;
+	struct ifbcachereq ifbc;
+	struct ifbcachetoreq ifbct;
+	int err;
+
+	strncpy(ifr.ifr_name, brdg, sizeof(ifr.ifr_name));
+	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
+		warnx2("%s", brdg);
+		if (errno == EPERM)
+			return (1);
+		return (1);
+	}
+
+	diag_printf("%s: ", brdg);
+	printb("flags", ifr.ifr_flags, IFFBITS);
+	diag_printf("\n");
+
+	diag_printf("Interfaces:\n");
+	err = bridge_list(s, brdg, "  ");
+	if (err)
+		return (err);
+
+	strncpy(ifbc.ifbc_name, brdg, sizeof(ifbc.ifbc_name));
+	if (ioctl(s, SIOCBRDGGCACHE, (caddr_t)&ifbc) < 0) {
+		warnx2("%s", brdg);
+		return (1);
+	}
+
+	strncpy(ifbct.ifbct_name, brdg, sizeof(ifbct.ifbct_name));
+	if (ioctl(s, SIOCBRDGGTO, (caddr_t)&ifbct) < 0) {
+		warnx2("%s", brdg);
+		return (1);
+	}
+
+	diag_printf("Addresses (max cache: %d, timeout: %d):\n",
+	    ifbc.ifbc_size, ifbct.ifbct_time);
+
+	err = bridge_addrs(s, brdg, "   ");
+	return (err);
+}
+
+int
+bridge_flush_rule(s, brdg, ifname)
+	int s;
+	char *brdg, *ifname;
+{
+	struct ifbrlreq req;
+
+	strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name));
+	strncpy(req.ifbr_ifsname, ifname, sizeof(req.ifbr_ifsname));
+	if (ioctl(s, SIOCBRDGFRL, &req) < 0) {
+		warnx3("%s: %s", brdg, ifname);
+		return (1);
+	}
+	return (0);
+}
+
+int
+bridge_rules(s, brdg, ifname, delim)
+	int s;
+	char *brdg, *ifname;
+	char *delim;
+{
+	char *inbuf = NULL;
+	struct ifbrlconf ifc;
+	struct ifbrlreq *ifrp, ifreq;
+	int len = 8192, i;
+
+	while (1) {
+		ifc.ifbrl_len = len;
+		ifc.ifbrl_buf = inbuf = realloc(inbuf, len);
+		strncpy(ifc.ifbrl_name, brdg, sizeof(ifc.ifbrl_name));
+		strncpy(ifc.ifbrl_ifsname, ifname, sizeof(ifc.ifbrl_ifsname));
+		if (inbuf == NULL)
+			err(1, "malloc");
+		if (ioctl(s, SIOCBRDGGRL, &ifc) < 0)
+			err(1, "ioctl(SIOCBRDGGRL)");
+		if (ifc.ifbrl_len + sizeof(ifreq) < len)
+			break;
+		len *= 2;
+	}
+	ifrp = ifc.ifbrl_req;
+	for (i = 0; i < ifc.ifbrl_len; i += sizeof(ifreq)) {
+		ifrp = (struct ifbrlreq *)((caddr_t)ifc.ifbrl_req + i);
+		bridge_showrule(ifrp, delim);
+	}
+        free(ifc.ifbrl_buf);
+	return (0);
+}
+
+void
+bridge_showrule(r, delim)
+	struct ifbrlreq *r;
+	char *delim;
+{
+	if (delim)
+		diag_printf("%s    ", delim);
+	else
+		diag_printf("%s: ", r->ifbr_name);
+
+	if (r->ifbr_action == BRL_ACTION_BLOCK)
+		diag_printf("block ");
+	else if (r->ifbr_action == BRL_ACTION_PASS)
+		diag_printf("pass ");
+	else
+		diag_printf("[neither block nor pass?]\n");
+
+	if ((r->ifbr_flags & (BRL_FLAG_IN | BRL_FLAG_OUT)) ==
+	    (BRL_FLAG_IN | BRL_FLAG_OUT))
+		diag_printf("in/out ");
+	else if (r->ifbr_flags & BRL_FLAG_IN)
+		diag_printf("in ");
+	else if (r->ifbr_flags & BRL_FLAG_OUT)
+		diag_printf("out ");
+	else
+		diag_printf("[neither in nor out?]\n");
+
+	diag_printf("on %s", r->ifbr_ifsname);
+
+	if (r->ifbr_flags & BRL_FLAG_SRCVALID)
+		diag_printf(" src %s", ether_ntoa(&r->ifbr_src));
+	if (r->ifbr_flags & BRL_FLAG_DSTVALID)
+		diag_printf(" dst %s", ether_ntoa(&r->ifbr_dst));
+
+	diag_printf("\n");
+}
+
+/*
+ * Parse a rule definition and send it upwards.
+ *
+ * Syntax:
+ *	{block|pass} {in|out|in/out} on {ifs} [src {mac}] [dst {mac}]
+ */
+int
+bridge_rule(int s, char *brdg, int targc, char **targv, int ln)
+{
+	char **argv = targv;
+	int argc = targc;
+	struct ifbrlreq rule;
+	struct ether_addr *ea, *dea;
+
+	if (argc == 0) {
+		diag_printf( "invalid rule\n");
+		return (1);
+	}
+	rule.ifbr_flags = 0;
+	rule.ifbr_action = 0;
+	strncpy(rule.ifbr_name, brdg, sizeof(rule.ifbr_name));
+
+	if (strcmp(argv[0], "block") == 0)
+		rule.ifbr_action = BRL_ACTION_BLOCK;
+	else if (strcmp(argv[0], "pass") == 0)
+		rule.ifbr_action = BRL_ACTION_PASS;
+	else
+		goto bad_rule;
+	argc--;	argv++;
+
+	if (argc == 0) {
+		bridge_badrule(targc, targv, ln);
+		return (1);
+	}
+	if (strcmp(argv[0], "in") == 0)
+		rule.ifbr_flags |= BRL_FLAG_IN;
+	else if (strcmp(argv[0], "out") == 0)
+		rule.ifbr_flags |= BRL_FLAG_OUT;
+	else if (strcmp(argv[0], "in/out") == 0)
+		rule.ifbr_flags |= BRL_FLAG_IN | BRL_FLAG_OUT;
+	else
+		goto bad_rule;
+	argc--; argv++;
+
+	if (argc == 0 || strcmp(argv[0], "on"))
+		goto bad_rule;
+	argc--; argv++;
+
+	if (argc == 0)
+		goto bad_rule;
+	strncpy(rule.ifbr_ifsname, argv[0], sizeof(rule.ifbr_ifsname));
+	argc--; argv++;
+
+	while (argc) {
+		if (strcmp(argv[0], "dst") == 0) {
+			if (rule.ifbr_flags & BRL_FLAG_DSTVALID)
+				goto bad_rule;
+			rule.ifbr_flags |= BRL_FLAG_DSTVALID;
+			dea = &rule.ifbr_dst;
+		}
+		else if (strcmp(argv[0], "src") == 0) {
+			if (rule.ifbr_flags & BRL_FLAG_SRCVALID)
+				goto bad_rule;
+			rule.ifbr_flags |= BRL_FLAG_SRCVALID;
+			dea = &rule.ifbr_src;
+		}
+		else
+			goto bad_rule;
+
+		argc--; argv++;
+
+		if (argc == 0)
+			goto bad_rule;
+		ea = ether_aton(argv[0]);
+		if (ea == NULL) {
+			warnx2("Invalid address: %s", argv[0]);
+			return (1);
+		}
+		bcopy(ea, dea, sizeof(*dea));
+		argc--; argv++;
+	}
+
+	if (ioctl(s, SIOCBRDGARL, &rule) < 0) {
+		warnx2("%s", brdg);
+		return (1);
+	}
+	return (0);
+
+bad_rule:
+	bridge_badrule(targc, targv, ln);
+	return (1);
+}
+
+#define MAXRULEWORDS 8
+#ifdef ZAP
+int
+bridge_rulefile(s, brdg, fname)
+	int s;
+	char *brdg, *fname;
+{
+	FILE *f;
+	char *str, *argv[MAXRULEWORDS], buf[1024], xbuf[1024];
+	int ln = 1, argc = 0, err = 0, xerr;
+
+	f = fopen(fname, "r");
+	if (f == NULL) {
+		warnx2("%s", fname);
+		return (1);
+	}
+
+	while (1) {
+		fgets(buf, sizeof(buf), f);
+		if (feof(f))
+			break;
+		ln++;
+		if (buf[0] == '#')
+			continue;
+
+		argc = 0;
+		str = strtok(buf, "\n\r ");
+		strncpy(xbuf, buf, sizeof(xbuf));
+		while (str != NULL) {
+			argv[argc++] = str;
+			if (argc > MAXRULEWORDS) {
+				diag_printf( "invalid rule: %d: %s\n",
+				    ln, xbuf);
+				break;
+			}
+			str = strtok(NULL, "\n\r ");
+		}
+
+		if (argc > MAXRULEWORDS)
+			continue;
+
+		xerr = bridge_rule(s, brdg, argc, argv, ln);
+		if (xerr)
+			err = xerr;
+	}
+	fclose(f);
+	return (err);
+}
+#endif
+void
+bridge_badrule(argc, argv, ln)
+	int argc, ln;
+	char **argv;
+{
+	int i;
+
+	diag_printf( "invalid rule: ");
+	if (ln != -1)
+		diag_printf( "%d: ", ln);
+	for (i = 0; i < argc; i++) {
+		diag_printf( "%s ", argv[i]);
+	}
+	diag_printf( "\n");
+}
+
+/*
+ * Print a value ala the %b format of the kernel's printf
+ * (borrowed from ifconfig.c)
+ */
+void
+printb(s, v, bits)
+	char *s;
+	char *bits;
+	unsigned short v;
+{
+	register int i, any = 0;
+	register char c;
+
+	if (bits && *bits == 8)
+		diag_printf("%s=%o", s, v);
+	else
+		diag_printf("%s=%x", s, v);
+	bits++;
+	if (bits) {
+		diag_printf("<");
+		while ((i = *bits++)) {
+			if (v & (1 << (i-1))) {
+				if (any)
+					diag_printf(",");
+				any = 1;
+				for (; (c = *bits) > 32; bits++)
+					diag_printf("%c",c);
+			} else
+				for (; *bits > 32; bits++)
+					;
+		}
+		diag_printf(">");
+	}
+}
+
+static void 
+interface_up(const char *intf)
+{
+  struct ifreq ifr;
+  int s;
+
+  s = socket(AF_INET, SOCK_DGRAM, 0);
+  if (s < 0) {
+    perror("socket");
+    return;
+  }
+
+  strcpy(ifr.ifr_name, intf);
+  ifr.ifr_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING;
+  if (ioctl(s, SIOCSIFFLAGS, &ifr)) {
+    perror("SIOCSIFFLAGS");
+  }
+  close(s);
+}
+
+static void
+main_fn(cyg_addrword_t data) {
+
+  int sock;
+  char brdg[] = "bridge0";
+
+  sock = socket(AF_INET, SOCK_DGRAM, 0);
+  assert(sock >= 0);
+
+#ifdef CYGHWR_NET_DRIVER_ETH0
+  interface_up("eth0");
+  eth0_up = 1;
+  bridge_add(sock,brdg,"eth0");
+#endif
+#ifdef CYGHWR_NET_DRIVER_ETH1
+  interface_up("eth1");
+  eth1_up = 1;
+  bridge_add(sock,brdg,"eth1");
+#endif
+
+  bridge_status(sock,brdg);
+  bridge_setflag(sock,brdg, IFF_UP);
+
+  while(1) {
+    cyg_kmem_print_stats();
+    cyg_thread_delay(500);
+  }
+}
+
+static char main_stack[8192];
+static cyg_handle_t main_handle;
+static cyg_thread main_thread;
+
+void
+cyg_user_start(void) {
+  printf("cyg_user_start starting\n");
+  cyg_thread_create(4, &main_fn, 0, "main", &main_stack, sizeof(main_stack),
+                    &main_handle, &main_thread);
+  cyg_thread_resume(main_handle);
+  printf("cyg_user_start done\n");
+}
+
+
--- a/packages/net/tcpip/current/tests/dhcp_test.c
+++ b/packages/net/tcpip/current/tests/dhcp_test.c
@@ -223,6 +223,7 @@ ping_host(int s, struct sockaddr_in *hos
         TNR_OFF();
         if (len < 0) {
             perror("recvfrom");
+            icmp_len = MIN_PACKET - PACKET_ADD; // go back to small packet size
             seq+=4;
         } else {
             if (show_icmp(pkt2, len, &from, host)) {
@@ -270,7 +271,8 @@ void
 net_test(cyg_addrword_t p)
 {
 #ifndef CYGPKG_NET_DHCP
-    CYG_TEST_NA_FINISH( "DHCP is not enabled" );
+    CYG_TEST_NA( "DHCP is not enabled" );
+    CYG_TEST_EXIT( "DHCP is not enabled" );
 #else
     int i;
     diag_printf("Start DHCP test\n");
--- a/packages/net/tcpip/current/tests/ftp_test.c
+++ b/packages/net/tcpip/current/tests/ftp_test.c
@@ -160,6 +160,9 @@ net_test(cyg_addrword_t param)
     if (eth0_up) {
         ftp_test(&eth0_bootp_data);
     }
+    if (eth1_up) {
+        ftp_test(&eth1_bootp_data);
+    }
     cyg_test_exit();
 }
 
new file mode 100644
--- /dev/null
+++ b/packages/net/tcpip/current/tests/multi_lo_select.c
@@ -0,0 +1,453 @@
+//==========================================================================
+//
+//      tests/multi_lo_test.c
+// 
+//      Multiple selects-at-one-time test, using lo for portability.
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+// 
+// -------------------------------------------
+// The contents of this file are subject to the Red Hat eCos Public License
+// Version 1.1 (the "License"); you may not use this file except in
+// compliance with the License.  You may obtain a copy of the License at
+// http://www.redhat.com/  
+//      
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the
+// License for the specific language governing rights and limitations under
+// the License.
+// 
+// The Original Code is eCos - Embedded Configurable Operating System,
+// released September 30, 1998.
+// 
+// The Initial Developer of the Original Code is Red Hat.
+// Portions created by Red Hat are
+// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
+// All Rights Reserved.
+// -------------------------------------------
+//
+//####COPYRIGHTEND####
+//####BSDCOPYRIGHTBEGIN####
+//
+// -------------------------------------------
+//
+// Portions of this software may have been derived from OpenBSD or other sources
+// and are covered by the appropriate copyright disclaimers included herein.
+//
+// -------------------------------------------
+//
+//####BSDCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    sorin@netappi.com, hmt
+// Contributors: gthomas,sorin@netappi.com
+// Date:         2000-05-24
+// Description:
+//
+//      This test is to test that the internal producer operation to select
+//      truly has broadcast semantics; there was a bug in there whereby it
+//      doesn't, so events get lost and/or the wrong thread is awakened.
+//
+//      We need to create N threads selecting on different sockets
+//      (different ports) (including one or two selecting on several
+//      sockets) and have a further thread or threads which send data to
+//      the those sockets in an order "random" with respect to the order in
+//      which the N selectors entered the wait, and their thread
+//      priorities.
+//
+//      If this all works, then we know that select always wakes the right
+//      thread in the right order.  I think...
+//
+//      I think 10 threads 0-9 where #2,#3,#6,#7 wait for multiple threads
+//      will do it.  #0-4 will be prio HI, #5-9 will be prio LO.  Sender
+//      thread A at prio MID will send to sockets 1,3,5,7,9.  Sender thread
+//      B at prio LOWEST will send to sockets 0,2,4,6,8.
+//
+//      Each sender thread will wait for a different semaphore signal
+//      before doing their next send, thus confirming correct ordering.
+//      Two common semaphores will also be signalled, one when a send
+//      occurs, the other when a recv happens.
+//
+//      The master thread will start off VERYHIGHPRI, then drop after
+//      starting all the others, to VERYLOW... when it next runs, those
+//      common semaphores should both have value 10 == NLISTENERS.
+//
+//
+//#####DESCRIPTIONEND#####
+//
+//==========================================================================
+
+#include <network.h>
+
+#include <cyg/infra/testcase.h>
+
+#define SOURCE_PORT1 9900
+#define SOURCE_PORT2 9800 // for those who listen to multiple ports
+#define SOURCE_PORT3 9700 // for the dummy consumers of events
+
+#define PRIO_DUMMY 4 // Really high, so they're always right back there
+
+#define PRIO_LISTENER_HI 10
+#define PRIO_LISTENER_LO 15
+
+#define PRIO_SENDER_MID  12
+#define PRIO_SENDER_LOW  17
+
+#define PRIO_MASTERHIGH   3
+#define PRIO_MASTERLOW   25
+
+#if CYGPKG_IO_NFILE > 30
+#define NLISTENERS 10
+#else
+// fewer threads if not many sockets available
+#define NLISTENERS (CYGPKG_IO_NFILE/3)
+#endif
+
+#define NDUMMIES   10
+
+#define NSENDERS 2
+
+#define NUM_BUF  NLISTENERS
+#define MAX_BUF 100
+
+// buffers for receiving into:
+static unsigned char data_buf1[NUM_BUF][MAX_BUF];
+
+static unsigned char data_buf_write1[]="Client is alive";
+
+#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL)
+#define MASTER_STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000)
+
+static char stack_master[MASTER_STACK_SIZE];
+static cyg_thread master_thread_data;
+static cyg_handle_t master_thread_handle;
+
+static char stack_dummy[NDUMMIES][STACK_SIZE];
+static cyg_thread dummy_thread_data[NDUMMIES]; 
+static cyg_handle_t dummy_thread_handle[NDUMMIES];  
+
+static char stack_listener[NLISTENERS][STACK_SIZE];
+static cyg_thread listener_thread_data[NLISTENERS]; 
+static cyg_handle_t listener_thread_handle[NLISTENERS];  
+
+static char stack_sender[NSENDERS][STACK_SIZE];
+static cyg_thread sender_thread_data[NSENDERS];
+static cyg_handle_t sender_thread_handle[NSENDERS];
+
+static cyg_sem_t listen_sema[NLISTENERS];
+
+static cyg_sem_t send_sema;
+static cyg_sem_t recv_sema;
+
+static cyg_thread_entry_t master;
+static cyg_thread_entry_t listener;
+static cyg_thread_entry_t sender;
+
+// ------------------------------------------------------------------------
+
+void
+pexit(char *s)
+{
+    CYG_TEST_FAIL_FINISH( s );
+}
+
+
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+// ------------------------------------------------------------------------
+
+void dummy( cyg_addrword_t which )
+{
+    // Share the same socket... we appear to run out otherwise.
+    static int s_s1 = -1;
+    static struct sockaddr_in local;
+
+    // locals...
+    fd_set in_fds;
+    int num;
+
+    CYG_TEST_CHECK( 0 <= which, "which under" );
+    CYG_TEST_CHECK( NDUMMIES > which, "which over" );
+
+    diag_printf( "Dummy %d alive\n", which );
+
+    if ( s_s1 < 0 ) {
+        s_s1 = socket(AF_INET, SOCK_STREAM, 0);
+        if (s_s1 < 0) {
+            pexit("stream socket 1");
+        }
+        memset(&local, 0, sizeof(local));
+        local.sin_family = AF_INET;
+        local.sin_len = sizeof(local);
+        local.sin_port = ntohs(SOURCE_PORT3 + which);
+        local.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+        if(bind(s_s1, (struct sockaddr *) &local, sizeof(local)) < 0) {
+            pexit("dummy bind /source_1/ error");
+        }
+        listen(s_s1, SOMAXCONN);
+    }
+
+    while (true) {
+        FD_ZERO(&in_fds);
+        FD_SET(s_s1, &in_fds);
+        num = select( s_s1+1, &in_fds,0,0,0);
+        
+        if (FD_ISSET(s_s1,&in_fds)) {
+            CYG_TEST_FAIL( "Activity on dummy port!" );
+        }
+    }   /* while (true) */ 
+}
+
+// ------------------------------------------------------------------------
+
+void listener( cyg_addrword_t which )
+{
+    int s_s1 = -1, e_s1 = 0, s_s2 = -1, e_s2 = 0;
+    struct sockaddr_in e_s1_addr,e_s2_addr,local;
+    fd_set in_fds;
+    int len;
+    int num;
+
+    // do we select on multiple sources?
+    int dual = (3 == (which & 3)) || (2 == (which & 3));
+    // then which is 2,3,6,7 so set up a 2nd listener
+    
+    CYG_TEST_CHECK( 0 <= which, "which under" );
+    CYG_TEST_CHECK( NLISTENERS > which, "which over" );
+
+    diag_printf( "Listener %d alive [%s]\n", which, dual ? "dual" : "single" );
+
+    s_s1 = socket(AF_INET, SOCK_STREAM, 0);
+    if (s_s1 < 0) {
+        pexit("stream socket 1");
+    }   
+    memset(&local, 0, sizeof(local));
+    local.sin_family = AF_INET;
+    local.sin_len = sizeof(local);
+    local.sin_port = ntohs(SOURCE_PORT1 + which);
+    local.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+    if(bind(s_s1, (struct sockaddr *) &local, sizeof(local)) < 0) {
+        pexit("bind /source_1/ error");
+    }
+    listen(s_s1, SOMAXCONN);
+
+    if ( dual ) {
+        s_s2 = socket(AF_INET, SOCK_STREAM, 0);    
+        if (s_s2 < 0) {    
+            pexit("stream socket 2");
+        }  
+        memset(&local, 0, sizeof(local));
+        local.sin_family = AF_INET;
+        local.sin_len = sizeof(local);
+        local.sin_port = ntohs(SOURCE_PORT2 + which);
+        local.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+        if(bind(s_s2, (struct sockaddr *) &local, sizeof(local)) < 0) {    
+            pexit("bind /source_2/ error");
+        }
+        listen(s_s2, SOMAXCONN);
+    }
+
+    while (true) {
+        FD_ZERO(&in_fds);
+        FD_SET(s_s1, &in_fds);
+        if ( dual )
+            FD_SET(s_s2, &in_fds);
+        num = select ( max(s_s1,s_s2)+1, &in_fds,0,0,0);
+        
+        if (FD_ISSET(s_s1,&in_fds)) {
+            len = sizeof(e_s1_addr);
+            if ((e_s1 = accept(s_s1,(struct sockaddr *)&e_s1_addr,&len))<0) {
+                pexit("accept /source_1/");
+            }
+            diag_printf("TCP SERVER connection from %s: %d\n",
+                        inet_ntoa(e_s1_addr.sin_addr),ntohs(e_s1_addr.sin_port));
+        }
+
+        if ( dual ) {
+            if (FD_ISSET(s_s2,&in_fds)) {
+                len = sizeof(e_s2_addr);
+                if ((e_s2 = accept(s_s2,(struct sockaddr *)&e_s2_addr,&len))<0) {
+                    pexit("accept /source_2/");
+                }
+                diag_printf("TCP SERVER connection from %s: %d\n",
+                            inet_ntoa(e_s2_addr.sin_addr), ntohs(e_s2_addr.sin_port));
+            }
+        }
+        if ((e_s1 != 0) || ( e_s2 != 0)) {
+            break;
+        }
+    }   /* while (true) */ 
+
+    CYG_TEST_CHECK( 0 != e_s1, "No connection made on s1!" );
+    
+    if ((len = read(e_s1, data_buf1[which], MAX_BUF)) < 0  ) {
+        perror("I/O error s1");
+        CYG_TEST_FAIL( "Read s1 failed" );
+    }
+    diag_printf("Listener %d: %s\n", which, data_buf1[which]);
+
+    close( s_s1 );
+    if ( dual )
+        close( s_s2 );
+    if ( 0 != e_s1 )
+        close ( e_s1 );
+    if ( 0 != e_s2 )
+        close ( e_s2 );
+
+    cyg_semaphore_post( &listen_sema[which] ); // Verify that I was here
+    cyg_semaphore_post( &recv_sema );          // Count receptions
+
+    cyg_thread_exit(); // explicitly
+}
+
+// ------------------------------------------------------------------------
+static void sender( cyg_addrword_t which ) // which means which set (odd/even) here...
+{
+    int s_source;
+    struct sockaddr_in local;
+    int len;
+
+    diag_printf("client %d [%s] :started\n", which, (which & 1) ? "odd" : "even" );
+
+    for ( /* which as is */; which < NLISTENERS; which += 2 ) {
+
+        s_source = socket(AF_INET, SOCK_STREAM, 0);
+        if (s_source < 0) {
+            pexit("stream socket");
+        }
+        memset(&local, 0, sizeof(local));
+        local.sin_family = AF_INET;
+        local.sin_port = htons( SOURCE_PORT1 + which );
+        local.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+    
+        if (connect(s_source, (struct sockaddr *)&local, sizeof(local)) < 0) {
+            pexit("Can't connect to target");
+        }
+    
+        if ((len = write(s_source,data_buf_write1,sizeof(data_buf_write1) )) < 0) {
+            CYG_TEST_FAIL_FINISH("Error writing buffer");
+        } 
+        cyg_semaphore_wait( &listen_sema[which] ); // wait for the appropriate semaphore "reply"
+        cyg_semaphore_post( &send_sema ); // count up successful sends
+
+        close ( s_source );
+    }
+    cyg_thread_exit(); // explicitly
+}
+
+
+static void
+master(cyg_addrword_t param)
+{
+    int i;
+    cyg_handle_t self = cyg_thread_self();
+
+    cyg_semaphore_init( &send_sema, 0 );
+    cyg_semaphore_init( &recv_sema, 0 );
+
+    for ( i = 0 ; i < NLISTENERS; i++ )
+        cyg_semaphore_init( &listen_sema[i], 0 );
+
+    init_all_network_interfaces();
+    CYG_TEST_INFO("Start multiple loopback select test");
+#if NLOOP > 0
+    // We are currently running at high prio, so we can just go and make
+    // loads of threads:
+
+    // Some at higher prio
+    for ( i = 0; i < NLISTENERS/2; i++ )
+        cyg_thread_create(PRIO_LISTENER_HI,       // Priority
+                          listener,               // entry
+                          i,                      // entry parameter
+                          "listener",             // Name
+                          &stack_listener[i][0],  // Stack
+                          STACK_SIZE,             // Size
+                          &listener_thread_handle[i], // Handle
+                          &listener_thread_data[i] // Thread data structure
+            );
+    // the rest at lower prio
+    for (      ; i < NLISTENERS  ; i++ )
+        cyg_thread_create(PRIO_LISTENER_LO,       // Priority
+                          listener,               // entry
+                          i,                      // entry parameter
+                          "listener",             // Name
+                          &stack_listener[i][0],  // Stack
+                          STACK_SIZE,             // Size
+                          &listener_thread_handle[i], // Handle
+                          &listener_thread_data[i] // Thread data structure
+            );
+
+    // make the dummy event-grabber threads
+    for ( i = 0; i < NDUMMIES; i++ )
+        cyg_thread_create(PRIO_DUMMY,             // Priority
+                          dummy,                  // entry
+                          i,                      // entry parameter
+                          "dummy",                // Name
+                          &stack_dummy[i][0],     // Stack
+                          STACK_SIZE,             // Size
+                          &dummy_thread_handle[i], // Handle
+                          &dummy_thread_data[i]   // Thread data structure
+            );
+
+    // Start those threads
+    for ( i = 0; i < NLISTENERS; i++ )
+        cyg_thread_resume(listener_thread_handle[i]);
+    for ( i = 0; i < NDUMMIES; i++ )
+        cyg_thread_resume(   dummy_thread_handle[i]);
+
+    // and let them start up and start listening...
+    cyg_thread_set_priority( self, PRIO_MASTERLOW );
+    CYG_TEST_INFO("All listeners should be go now");
+    cyg_thread_set_priority( self, PRIO_MASTERHIGH );
+
+    for ( i = 0; i < NSENDERS; i++ ) {
+        cyg_thread_create( (0 == i)
+                           ?PRIO_SENDER_MID
+                           : PRIO_SENDER_LOW,     // Priority
+                           sender,                // entry
+                           i,                     // entry parameter
+                           "sender",              // Name
+                           &stack_sender[i][0],   // Stack
+                           STACK_SIZE,            // Size
+                           &sender_thread_handle[i], // Handle
+                           &sender_thread_data[i] // Thread data structure
+            );
+        cyg_thread_resume(sender_thread_handle[i]);
+    }
+
+    // Now we are still higher priority; so go low and let everyone else
+    // have their head.  When we next run after this, it should all be
+    // over.
+    cyg_thread_set_priority( self, PRIO_MASTERLOW );
+
+    cyg_semaphore_peek( &recv_sema, &i );
+    CYG_TEST_CHECK( NLISTENERS == i, "Not enough recvs occurred!" );
+    
+    cyg_semaphore_peek( &send_sema, &i );
+    CYG_TEST_CHECK( NLISTENERS == i, "Not enough sends occurred!" );
+
+    CYG_TEST_PASS_FINISH("Master returned OK");
+#endif
+    CYG_TEST_NA( "No loopback devs" );
+}
+
+void
+cyg_user_start(void)
+{
+    cyg_thread_create(PRIO_MASTERHIGH,            // Priority
+                      master,                     // entry
+                      0,                          // entry parameter
+                      "master",                   // Name
+                      &stack_master[0],           // Stack
+                      MASTER_STACK_SIZE,          // Size
+                      &master_thread_handle,      // Handle
+                      &master_thread_data         // Thread data structure
+            );
+    cyg_thread_resume(master_thread_handle);      // Start it
+}
+
+// EOF multi_lo_select.c
--- a/packages/net/tcpip/current/tests/ping_test.c
+++ b/packages/net/tcpip/current/tests/ping_test.c
@@ -221,6 +221,7 @@ ping_host(int s, struct sockaddr_in *hos
         TNR_OFF();
         if (len < 0) {
             perror("recvfrom");
+            icmp_len = MIN_PACKET - PACKET_ADD; // just in case - long routes
         } else {
             if (show_icmp(pkt2, len, &from, host)) {
                 ok_recv++;