Mercurial > ecos-v3_0-branch
changeset 112:02ea4320376c ecos-sw-2000-07-21
Merge from eCos master repository on 2000-07-21-21:01:39-BST
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(ð0_bootp_data); } + if (eth1_up) { + ftp_test(ð1_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++;
