Mercurial > nand-ecoscentric
changeset 110:84e4bde58b26 ecos-sw-2000-07-14
Merge from eCos master repository on 2000-07-14-22:00:02-BST
line wrap: on
line diff
--- a/host/libcdl/ChangeLog +++ b/host/libcdl/ChangeLog @@ -1,3 +1,9 @@ +2000-07-06 Bart Veer <bartv@redhat.com> + + * conflict.cxx (get_explanation): + Put quotes around "requires" in the conflict explanation. + Requested by the eCos team. + 2000-07-04 Bart Veer <bartv@redhat.com> * value.cxx (save):
--- a/host/libcdl/conflict.cxx +++ b/host/libcdl/conflict.cxx @@ -909,7 +909,7 @@ CdlConflict_RequiresBody::get_explanatio CYG_ASSERTC(0 != gexpr); std::string result = ""; - result += "Requires constraint not satisfied: " + gexpr->get_original_string(); + result += "\"requires\" constraint not satisfied: " + gexpr->get_original_string(); CYG_REPORT_RETURN(); return result;
--- a/host/tools/configtool/standalone/common/ChangeLog +++ b/host/tools/configtool/standalone/common/ChangeLog @@ -1,3 +1,8 @@ +2000-07-07 Bart Veer <bartv@redhat.com> + + * cdl_exec.cxx (transaction_callback): + Output the correct value irrespective of the option flavor. + 2000-06-28 Bart Veer <bartv@redhat.com> * cdl_exec.cxx, cdl_exec.hxx, ecosconfig.cxx:
--- a/host/tools/configtool/standalone/common/cdl_exec.cxx +++ b/host/tools/configtool/standalone/common/cdl_exec.cxx @@ -662,8 +662,11 @@ cdl_exec::transaction_callback(const Cdl for (i = 0; i < callback_data.value_changes.size(); i++) { CdlValuable valuable = callback_data.value_changes[i]; if (CdlValueSource_Inferred == valuable->get_source()) { + CdlEvalContext context(0, valuable, 0); + CdlSimpleValue simple_val; + CdlSimpleValue::eval_valuable(context, valuable, simple_val); std::string msg = std::string("U ") + valuable->get_name() + ", new inferred value "; - std::string value = valuable->get_value(); + std::string value = simple_val.get_value(); if ("" == value) { msg += "\"\""; } else {
--- a/packages/ChangeLog +++ b/packages/ChangeLog @@ -1,3 +1,8 @@ +2000-07-07 Jesper Skov <jskov@redhat.com> + + * ecos.db: Removed 'enable' statements from SH targets. Moved to + individual HAL CDL files. + 2000-06-23 Jesper Skov <jskov@redhat.com> * ecos.db: Added CqREEK serial package.
new file mode 100644 --- /dev/null +++ b/packages/cygmon/current/misc/arm/board.h @@ -0,0 +1,72 @@ +#ifndef __CYGMON_ARM_BOARD_H__ +#define __CYGMON_ARM_BOARD_H__ +//========================================================================== +// +// board.h +// +// Cygmon board/platform configuration file +// +//========================================================================== +//####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): gthomas +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= +// Hardware/platform/configuration specifics + +#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 +#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 + +#endif // __CYGMON_ARM_BOARD_H__
--- a/packages/ecos.db +++ b/packages/ecos.db @@ -289,7 +289,6 @@ package CYGPKG_DEVS_ETH_POWERPC_QUICC { script quicc_eth_drivers.cdl description "Ethernet driver for PowerPC QUICC (MPC8xx) based boards." } - package CYGPKG_IO_PCI { alias { "PCI configuration library" io_pci } directory io/pci @@ -999,7 +998,6 @@ target sh7708 { CYGPKG_IO_SERIAL_SH_EDK7708 CYGPKG_DEVICES_WATCHDOG_SH_SH3 } - enable { CYGPKG_HAL_SH_7708 } description " The sh7708 target provides the packages needed to run eCos on a Hitachi EDK/SH7708 board." @@ -1011,7 +1009,6 @@ target cq7708 { CYGPKG_HAL_SH_SH7708_CQ7708 CYGPKG_IO_SERIAL_SH_CQ7708 } - enable { CYGPKG_HAL_SH_7708 } description " The cq7708 target provides the packages needed to run eCos on a CqREEK SH7708 board."
--- a/packages/hal/arm/arch/current/ChangeLog +++ b/packages/hal/arm/arch/current/ChangeLog @@ -1,3 +1,16 @@ +2000-07-07 Jesper Skov <jskov@redhat.com> + + * src/arm_stub.c: Changes to support CygMon changes. + + * src/hal_misc.c: Fix warnings. + +2000-07-05 Jesper Skov <jskov@redhat.com> + + * src/hal_misc.c: + * src/vectors.S: + All platforms now has VECTOR_SUPPORT (or provide alternative + implementations). Removed checks for the option. + 2000-06-28 Jesper Skov <jskov@redhat.com> * src/hal_mk_defs.c:
--- a/packages/hal/arm/arch/current/src/arm_stub.c +++ b/packages/hal/arm/arch/current/src/arm_stub.c @@ -45,9 +45,6 @@ #include <stddef.h> #include <pkgconf/hal.h> -#ifdef CYGPKG_CYGMON -#include <pkgconf/cygmon.h> -#endif #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS @@ -495,7 +492,6 @@ void __clear_single_step (void) } } -#if !defined(CYGPKG_CYGMON) void __install_breakpoints (void) { // FIXME(); @@ -505,7 +501,6 @@ void __clear_breakpoints (void) { // FIXME(); } -#endif // !CYGPKG_CYGMON /* If the breakpoint we hit is in the breakpoint() instruction, return a non-zero value. */
--- a/packages/hal/arm/arch/current/src/hal_misc.c +++ b/packages/hal/arm/arch/current/src/hal_misc.c @@ -81,9 +81,10 @@ extern void *__mem_fault_handler; #define ARM_VECTORS 8 extern unsigned long vectors[]; // exception vectors as defined by the stubs + +#if !defined(CYGPKG_CYGMON) static unsigned long *hardware_vectors = (unsigned long *)0x20; static unsigned long hold_vectors[ARM_VECTORS]; - static int exception_level; static void @@ -101,6 +102,7 @@ static void hardware_vectors[CYGNUM_HAL_VECTOR_ABORT_PREFETCH] = hold_vectors[CYGNUM_HAL_VECTOR_ABORT_PREFETCH]; hardware_vectors[CYGNUM_HAL_VECTOR_ABORT_DATA] = hold_vectors[CYGNUM_HAL_VECTOR_ABORT_DATA]; } +#endif // !CYGPKG_CYGMON #endif void @@ -173,9 +175,8 @@ cyg_hal_invoke_constructors (void) } /*------------------------------------------------------------------------*/ -/* default ISR */ +/* Architecture default ISR */ -#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT externC cyg_uint32 hal_arch_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) { @@ -186,29 +187,6 @@ hal_arch_default_isr(CYG_ADDRWORD vector CYG_FAIL("Spurious Interrupt!!!"); return 0; } -#else -externC cyg_uint32 -hal_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) -{ - CYG_TRACE1(true, "Interrupt: %d", vector); - -#ifndef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS -#ifdef CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT -#ifdef CYGDBG_HAL_CTRLC_ISR - // then see if it is an incoming character interrupt and break - // into the stub ROM if the char is a ^C. - if ( CYGDBG_HAL_CTRLC_ISR( vector, data ) ) - return 1; // interrupt handled -#endif -#endif -#endif - - diag_printf("Spurious Interrupt!!! - vector: %d, data: %x\n", vector, - data); - CYG_FAIL("Spurious Interrupt!!!"); - return 0; -} -#endif // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT /*------------------------------------------------------------------------*/ /* Idle thread action */
--- a/packages/hal/arm/arch/current/src/vectors.S +++ b/packages/hal/arm/arch/current/src/vectors.S @@ -189,8 +189,8 @@ hal_dram_size: .long 0 .balign 16 -#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this _check_ should go away - // Vectors used to communicate between eCos and ROM environments +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT + // Vectors used to communicate between eCos and ROM environments .globl hal_virtual_vector_table hal_virtual_vector_table: .rept CYGNUM_CALL_IF_TABLE_SIZE @@ -388,13 +388,11 @@ 2: str r2,[r0,#0x24] #endif -#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this _check_ should go away #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 @@ -716,7 +714,6 @@ 10: mov r0,v1 // vector # -#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this _check_ should go away #if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \ || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) // If we are supporting Ctrl-C interrupts from GDB, we must squirrel @@ -727,7 +724,6 @@ 10: ldr r2,=hal_saved_interrupt_state str v6,[r2] #endif -#endif #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS cmp r0,#0 // ignore spurious interrupts
--- a/packages/hal/arm/cma230/current/ChangeLog +++ b/packages/hal/arm/cma230/current/ChangeLog @@ -1,3 +1,13 @@ +2000-07-05 Jesper Skov <jskov@redhat.com> + + * cdl/hal_arm_cma230.cdl: + * include/hal_diag.h: + * include/plf_stub.h: + * src/cma230_misc.c: + * src/hal_diag.c: + * src/plf_stub.c: [deleted] + Changed to support virtual vectors. + 2000-06-18 Gary Thomas <gthomas@redhat.com> * include/pkgconf/mlt_arm_cma222_ram.ldi:
--- a/packages/hal/arm/cma230/current/cdl/hal_arm_cma230.cdl +++ b/packages/hal/arm/cma230/current/cdl/hal_arm_cma230.cdl @@ -50,10 +50,11 @@ cdl_package CYGPKG_HAL_ARM_CMA230 { The cma230 HAL package provides the support needed to run eCos on Cogent Computer Systems CMA2xx (CMA230, CMA222) boards." - compile hal_diag.c plf_stub.c cma230_misc.c + compile hal_diag.c cma230_misc.c implements CYGINT_HAL_DEBUG_GDB_STUBS implements CYGINT_HAL_DEBUG_GDB_STUBS_BREAK + implements CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT define_proc { puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H <pkgconf/hal_arm.h>" @@ -85,17 +86,7 @@ cdl_package CYGPKG_HAL_ARM_CMA230 { into ROM." } - cdl_option CYGHWR_HAL_ARM_CMA230_DIAG_PORT { - display "Diagnostic serial port" - flavor data - legal_values 0 1 - default_value 0 - description " - The CMA230 board has two separate serial ports. This option - chooses which of these ports will be used." - } - - cdl_option CYGHWR_HAL_ARM_CMA230_DIAG_BAUD { + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD { display "Diagnostic serial port baud rate" flavor data legal_values 9600 19200 38400 115200 @@ -106,18 +97,7 @@ cdl_package CYGPKG_HAL_ARM_CMA230 { diagnostic and GDB port are the same." } - cdl_option CYGHWR_HAL_ARM_CMA230_GDB_PORT { - display "GDB serial port" - flavor data - legal_values 0 1 - default_value 0 - description " - The CMA230 board has two separate serial ports. This option - chooses which of these ports will be used to connect to a host - running GDB." - } - - cdl_option CYGHWR_HAL_ARM_CMA230_GDB_BAUD { + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD { display "GDB serial port baud rate" flavor data legal_values 9600 19200 38400 115200 @@ -126,6 +106,33 @@ cdl_package CYGPKG_HAL_ARM_CMA230 { This option controls the baud rate used for the GDB connection." } + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS { + display "Number of communication channels on the board" + flavor data + calculated 2 + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL { + display "Debug serial port" + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + The CMA230 board has two serial ports. This option + chooses which port will be used to connect to a host + running GDB." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL { + display "Diagnostic serial port" + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + The CMA230 board has two serial ports. This option + chooses which port will be used for diagnostic output." + } + # Real-time clock/counter specifics cdl_component CYGNUM_HAL_RTC_CONSTANTS { display "Real-time clock constants" @@ -219,8 +226,8 @@ cdl_package CYGPKG_HAL_ARM_CMA230 { requires { CYG_HAL_STARTUP == "ROM" } requires CYGSEM_HAL_ROM_MONITOR requires CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS - requires ! CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT - requires ! CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT + requires CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + requires CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT requires ! CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT requires ! CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM no_define @@ -285,4 +292,25 @@ cdl_package CYGPKG_HAL_ARM_CMA230 { application. This enables features such as utilizing a separate interrupt stack when exceptions are generated." } + + cdl_option CYGSEM_HAL_USE_ROM_MONITOR { + display "Work with a ROM monitor" + flavor booldata + legal_values { "Generic" "GDB_stubs" } + default_value { CYG_HAL_STARTUP == "RAM" ? "GDB_stubs" : 0 } + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "RAM" } + description " + Support can be enabled for different varieties of ROM monitor. + This support changes various eCos semantics such as the encoding + of diagnostic output, or the overriding of hardware interrupt + vectors. + Firstly there is \"Generic\" support which prevents the HAL + from overriding the hardware vectors that it does not use, to + instead allow an installed ROM monitor to handle them. This is + the most basic support which is likely to be common to most + implementations of ROM monitor. + \"GDB_stubs\" provides support when GDB stubs are included in + the ROM monitor or boot ROM." + } }
--- a/packages/hal/arm/cma230/current/include/hal_diag.h +++ b/packages/hal/arm/cma230/current/include/hal_diag.h @@ -49,6 +49,16 @@ #include <cyg/infra/cyg_type.h> +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) + +#include <cyg/hal/hal_if.h> + +#define HAL_DIAG_INIT() hal_if_diag_init() +#define HAL_DIAG_WRITE_CHAR(_c_) hal_if_diag_write_char(_c_) +#define HAL_DIAG_READ_CHAR(_c_) hal_if_diag_read_char(&_c_) + +#else // everything by steam + /*---------------------------------------------------------------------------*/ /* functions implemented in hal_diag.c */ @@ -64,6 +74,8 @@ externC void hal_diag_read_char(char *c) #define HAL_DIAG_READ_CHAR(_c_) hal_diag_read_char(&_c_) +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG + /*---------------------------------------------------------------------------*/ /* end of hal_diag.h */ #endif /* CYGONCE_HAL_DIAG_H */
--- a/packages/hal/arm/cma230/current/include/plf_stub.h +++ b/packages/hal/arm/cma230/current/include/plf_stub.h @@ -54,29 +54,29 @@ #include <cyg/hal/arm_stub.h> // architecture stub support //---------------------------------------------------------------------------- -// Define serial stuff. +// Define some platform specific communication details. This is mostly +// handled by hal_if now, but we need to make sure the comms tables are +// properly initialized. -extern void hal_cma230_init_serial(void); -extern int hal_cma230_get_char(void); -extern void hal_cma230_put_char(int c); -extern int hal_cma230_interruptible(int); +externC void cyg_hal_plf_comms_init(void); -#define HAL_STUB_PLATFORM_INIT_SERIAL() hal_cma230_init_serial() -#define HAL_STUB_PLATFORM_GET_CHAR() hal_cma230_get_char() -#define HAL_STUB_PLATFORM_PUT_CHAR(c) hal_cma230_put_char((c)) +#define HAL_STUB_PLATFORM_INIT_SERIAL() cyg_hal_plf_comms_init() + #define HAL_STUB_PLATFORM_SET_BAUD_RATE(baud) CYG_UNUSED_PARAM(int, (baud)) -#define HAL_STUB_PLATFORM_INTERRUPTIBLE (&hal_cma230_interruptible) +#define HAL_STUB_PLATFORM_INTERRUPTIBLE 0 #define HAL_STUB_PLATFORM_INIT_BREAK_IRQ() CYG_EMPTY_STATEMENT //---------------------------------------------------------------------------- // Stub initializer. #define HAL_STUB_PLATFORM_INIT() CYG_EMPTY_STATEMENT +#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + //---------------------------------------------------------------------------- // Reset. #define HAL_STUB_PLATFORM_RESET() CYG_EMPTY_STATEMENT -#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +#define HAL_STUB_PLATFORM_RESET_ENTRY 0xe000000 //----------------------------------------------------------------------------- #endif // CYGONCE_HAL_PLF_STUB_H
--- a/packages/hal/arm/cma230/current/src/cma230_misc.c +++ b/packages/hal/arm/cma230/current/src/cma230_misc.c @@ -47,6 +47,7 @@ #include <cyg/infra/cyg_trac.h> // tracing macros #include <cyg/infra/cyg_ass.h> // assertion macros +#include <cyg/hal/hal_if.h> // calling interface API #include <cyg/hal/hal_io.h> // IO macros #include <cyg/hal/hal_arch.h> // Register state info #include <cyg/hal/hal_diag.h> @@ -110,6 +111,9 @@ void hal_hardware_init(void) // Reset all interrupt masks (disable all interrupt sources) *(volatile cyg_uint8 *)CMA230_IMRw = 0; *(volatile cyg_uint8 *)CMA230_CLR = 0xFF; // Clear all current interrupts + + // Set up eCos/ROM interfaces + hal_if_init(); } //
--- a/packages/hal/arm/cma230/current/src/hal_diag.c +++ b/packages/hal/arm/cma230/current/src/hal_diag.c @@ -53,85 +53,96 @@ #include <cyg/hal/hal_io.h> // IO macros #include <cyg/hal/hal_diag.h> #include <cyg/hal/hal_cma230.h> // Hardware definitions -#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS -#include <cyg/hal/drv_api.h> -#include <cyg/hal/hal_stub.h> // cyg_hal_gdb_interrupt -#endif +#include <cyg/hal/hal_if.h> // Calling-if API +#include <cyg/hal/drv_api.h> // driver API +#include <cyg/hal/hal_misc.h> // Helper functions + +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) \ + || defined(CYGPRI_HAL_IMPLEMENTS_IF_SERVICES) + +static void cyg_hal_plf_serial_init(void); + +// FIXME: Copy LCD driver from powerpc/cogent +//static void cyg_hal_plf_lcd_init(void); + +void +cyg_hal_plf_comms_init(void) +{ + static int initialized = 0; + + if (initialized) + return; + + initialized = 1; + + cyg_hal_plf_serial_init(); +// cyg_hal_plf_lcd_init(); +} +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG || CYGPRI_HAL_IMPLEMENTS_IF_SERVICES -// Assumption: all diagnostic output must be GDB packetized unless this is a ROM (i.e. -// totally stand-alone) system. +//============================================================================= +// Serial driver +//============================================================================= + +//----------------------------------------------------------------------------- +// There are two serial ports. +#define CYG_DEV_SERIAL_BASE_A 0xe900047 // port A +#define CYG_DEV_SERIAL_BASE_B 0xe900007 // port B -#if defined(CYG_HAL_STARTUP_ROM) || defined(CYGDBG_HAL_DIAG_DISABLE_GDB_PROTOCOL) -#define HAL_DIAG_USES_HARDWARE +//----------------------------------------------------------------------------- +// Default baud rate is 38400 +// Based on 3.6864 MHz xtal +#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==9600 +#define CYG_DEV_SERIAL_BAUD_MSB 0x00 +#define CYG_DEV_SERIAL_BAUD_LSB 0x18 +#endif +#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==19200 +#define CYG_DEV_SERIAL_BAUD_MSB 0x00 +#define CYG_DEV_SERIAL_BAUD_LSB 0x0C +#endif +#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==38400 +#define CYG_DEV_SERIAL_BAUD_MSB 0x00 +#define CYG_DEV_SERIAL_BAUD_LSB 0x06 +#endif +#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==115200 +#define CYG_DEV_SERIAL_BAUD_MSB 0x00 +#define CYG_DEV_SERIAL_BAUD_LSB 0x02 #endif -/*---------------------------------------------------------------------------*/ -#if CYGHWR_HAL_ARM_CMA230_DIAG_PORT==0 -// This is the base address of the A-channel -#define CYG_DEVICE_SERIAL_RS232_16550_BASE CMA101_DUARTA -#define CYG_DEVICE_SERIAL_INT CYGNUM_HAL_INTERRUPT_SERIAL_A -#else -// This is the base address of the B-channel -#define CYG_DEVICE_SERIAL_RS232_16550_BASE CMA101_DUARTB -#define CYG_DEVICE_SERIAL_INT CYGNUM_HAL_INTERRUPT_SERIAL_B -#endif - -// Based on 3.6864 MHz xtal -#if CYGHWR_HAL_ARM_CMA230_DIAG_BAUD==9600 -#define CYG_DEVICE_SERIAL_RS232_BAUD_MSB 0x00 -#define CYG_DEVICE_SERIAL_RS232_BAUD_LSB 0x18 -#endif -#if CYGHWR_HAL_ARM_CMA230_DIAG_BAUD==19200 -#define CYG_DEVICE_SERIAL_RS232_BAUD_MSB 0x00 -#define CYG_DEVICE_SERIAL_RS232_BAUD_LSB 0x0C -#endif -#if CYGHWR_HAL_ARM_CMA230_DIAG_BAUD==38400 -#define CYG_DEVICE_SERIAL_RS232_BAUD_MSB 0x00 -#define CYG_DEVICE_SERIAL_RS232_BAUD_LSB 0x06 -#endif -#if CYGHWR_HAL_ARM_CMA230_DIAG_BAUD==115200 -#define CYG_DEVICE_SERIAL_RS232_BAUD_MSB 0x00 -#define CYG_DEVICE_SERIAL_RS232_BAUD_LSB 0x02 -#endif - -#ifndef CYG_DEVICE_SERIAL_RS232_BAUD_MSB +#ifndef CYG_DEV_SERIAL_BAUD_MSB #error Missing/incorrect serial baud rate defined - CDL error? #endif -// Define the serial registers. -#define CYG_DEVICE_SERIAL_RS232_16550_RBR \ - ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x00) - // receiver buffer register, read, dlab = 0 -#define CYG_DEVICE_SERIAL_RS232_16550_THR \ - ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x00) - // transmitter holding register, write, dlab = 0 -#define CYG_DEVICE_SERIAL_RS232_16550_DLL \ - ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x00) - // divisor latch (LS), read/write, dlab = 1 -#define CYG_DEVICE_SERIAL_RS232_16550_IER \ - ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x08) - // interrupt enable register, read/write, dlab = 0 -#define CYG_DEVICE_SERIAL_RS232_16550_DLM \ - ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x08) - // divisor latch (MS), read/write, dlab = 1 -#define CYG_DEVICE_SERIAL_RS232_16550_IIR \ - ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x10) - // interrupt identification register, read, dlab = 0 -#define CYG_DEVICE_SERIAL_RS232_16550_FCR \ - ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x10) - // fifo control register, write, dlab = 0 -#define CYG_DEVICE_SERIAL_RS232_16550_LCR \ - ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x18) - // line control register, read/write -#define CYG_DEVICE_SERIAL_RS232_16550_MCR \ - ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x20) - // modem control register, read/write -#define CYG_DEVICE_SERIAL_RS232_16550_LSR \ - ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x28) - // line status register, read -#define CYG_DEVICE_SERIAL_RS232_16550_MSR \ - ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x30) - // modem status register, read +//----------------------------------------------------------------------------- +// Define the serial registers. The Cogent board is equipped with a 16552 +// serial chip. +#define CYG_DEV_SERIAL_RBR 0x00 // receiver buffer register, read, dlab = 0 +#define CYG_DEV_SERIAL_THR 0x00 // transmitter holding register, write, dlab = 0 +#define CYG_DEV_SERIAL_DLL 0x00 // divisor latch (LS), read/write, dlab = 1 +#define CYG_DEV_SERIAL_IER 0x08 // interrupt enable register, read/write, dlab = 0 +#define CYG_DEV_SERIAL_DLM 0x08 // divisor latch (MS), read/write, dlab = 1 +#define CYG_DEV_SERIAL_IIR 0x10 // interrupt identification register, read, dlab = 0 +#define CYG_DEV_SERIAL_FCR 0x10 // fifo control register, write, dlab = 0 +#define CYG_DEV_SERIAL_AFR 0x10 // alternate function register, read/write, dlab = 1 +#define CYG_DEV_SERIAL_LCR 0x18 // line control register, read/write +#define CYG_DEV_SERIAL_MCR 0x20 +#define CYG_DEV_SERIAL_MCR_A 0x20 +#define CYG_DEV_SERIAL_MCR_B 0x20 +#define CYG_DEV_SERIAL_LSR 0x28 // line status register, read +#define CYG_DEV_SERIAL_MSR 0x30 // modem status register, read +#define CYG_DEV_SERIAL_SCR 0x38 // scratch pad register + +// The interrupt enable register bits. +#define SIO_IER_ERDAI 0x01 // enable received data available irq +#define SIO_IER_ETHREI 0x02 // enable THR empty interrupt +#define SIO_IER_ELSI 0x04 // enable receiver line status irq +#define SIO_IER_EMSI 0x08 // enable modem status interrupt + +// The interrupt identification register bits. +#define SIO_IIR_IP 0x01 // 0 if interrupt pending +#define SIO_IIR_ID_MASK 0x0e // mask for interrupt ID bits +#define ISR_Tx 0x02 +#define ISR_Rx 0x04 // The line status register bits. #define SIO_LSR_DR 0x01 // data ready @@ -163,6 +174,299 @@ #define SIO_LCR_SB 0x40 // set break #define SIO_LCR_DLAB 0x80 // divisor latch access bit +// The FIFO control register +#define SIO_FCR_FCR0 0x01 // enable xmit and rcvr fifos +#define SIO_FCR_FCR1 0x02 // clear RCVR FIFO +#define SIO_FCR_FCR2 0x04 // clear XMIT FIFO + + +//----------------------------------------------------------------------------- +typedef struct { + cyg_uint8* base; + cyg_int32 msec_timeout; + int isr_vector; +} channel_data_t; + +//----------------------------------------------------------------------------- +static void +init_serial_channel(const channel_data_t* __ch_data) +{ + cyg_uint8* base = __ch_data->base; + cyg_uint8 lcr; + + // 8-1-no parity. + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_LCR, + SIO_LCR_WLS0 | SIO_LCR_WLS1); + + HAL_READ_UINT8(base+CYG_DEV_SERIAL_LCR, lcr); + lcr |= SIO_LCR_DLAB; + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_LCR, lcr); + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_DLL, CYG_DEV_SERIAL_BAUD_LSB); + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_DLM, CYG_DEV_SERIAL_BAUD_MSB); + lcr &= ~SIO_LCR_DLAB; + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_LCR, lcr); + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_FCR, 0x07); // Enable & clear FIFO +} + +static cyg_bool +cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch) +{ + cyg_uint8* base = ((channel_data_t*)__ch_data)->base; + cyg_uint8 lsr; + + HAL_READ_UINT8(base+CYG_DEV_SERIAL_LSR, lsr); + if ((lsr & SIO_LSR_DR) == 0) + return false; + + HAL_READ_UINT8(base+CYG_DEV_SERIAL_RBR, *ch); + + return true; +} + + +cyg_uint8 +cyg_hal_plf_serial_getc(void* __ch_data) +{ + cyg_uint8 ch; + CYGARC_HAL_SAVE_GP(); + + while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch)); + + CYGARC_HAL_RESTORE_GP(); + return ch; +} + +void +cyg_hal_plf_serial_putc(void* __ch_data, cyg_uint8 c) +{ + cyg_uint8* base = ((channel_data_t*)__ch_data)->base; + cyg_uint8 lsr; + CYGARC_HAL_SAVE_GP(); + + do { + HAL_READ_UINT8(base+CYG_DEV_SERIAL_LSR, lsr); + } while ((lsr & SIO_LSR_THRE) == 0); + + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_THR, c); + + // Hang around until the character has been safely sent. + do { + HAL_READ_UINT8(base+CYG_DEV_SERIAL_LSR, lsr); + } while ((lsr & SIO_LSR_THRE) == 0); + + CYGARC_HAL_RESTORE_GP(); +} + +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) \ + || defined(CYGPRI_HAL_IMPLEMENTS_IF_SERVICES) + +static const channel_data_t channels[2] = { + { (cyg_uint8*)CMA101_DUARTA, 1000, CYGNUM_HAL_INTERRUPT_SERIAL_A}, + { (cyg_uint8*)CMA101_DUARTB, 1000, CYGNUM_HAL_INTERRUPT_SERIAL_B} +}; + +static void +cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, + cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + cyg_hal_plf_serial_putc(__ch_data, *__buf++); + + CYGARC_HAL_RESTORE_GP(); +} + +static void +cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + *__buf++ = cyg_hal_plf_serial_getc(__ch_data); + + CYGARC_HAL_RESTORE_GP(); +} + +cyg_bool +cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch) +{ + int delay_count; + channel_data_t* chan = (channel_data_t*)__ch_data; + cyg_bool res; + CYGARC_HAL_SAVE_GP(); + + delay_count = chan->msec_timeout * 10; // delay in .1 ms steps + for(;;) { + res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch); + if (res || 0 == delay_count--) + break; + + CYGACC_CALL_IF_DELAY_US(100); + } + + CYGARC_HAL_RESTORE_GP(); + return res; +} + +static int +cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...) +{ + static int irq_state = 0; + channel_data_t* chan = (channel_data_t*)__ch_data; + cyg_uint8 ier; + int ret = 0; + CYGARC_HAL_SAVE_GP(); + + switch (__func) { + case __COMMCTL_IRQ_ENABLE: + HAL_INTERRUPT_UNMASK(chan->isr_vector); + HAL_INTERRUPT_SET_LEVEL(chan->isr_vector, 1); + HAL_READ_UINT8(chan->base+CYG_DEV_SERIAL_IER, ier); + ier |= SIO_IER_ERDAI; + HAL_WRITE_UINT8(chan->base+CYG_DEV_SERIAL_IER, ier); + irq_state = 1; + break; + case __COMMCTL_IRQ_DISABLE: + ret = irq_state; + irq_state = 0; + HAL_INTERRUPT_MASK(chan->isr_vector); + HAL_READ_UINT8(chan->base+CYG_DEV_SERIAL_IER, ier); + ier &= ~SIO_IER_ERDAI; + HAL_WRITE_UINT8(chan->base+CYG_DEV_SERIAL_IER, ier); + break; + case __COMMCTL_DBG_ISR_VECTOR: + ret = chan->isr_vector; + break; + case __COMMCTL_SET_TIMEOUT: + { + va_list ap; + + va_start(ap, __func); + + ret = chan->msec_timeout; + chan->msec_timeout = va_arg(ap, cyg_uint32); + + va_end(ap); + } + default: + break; + } + CYGARC_HAL_RESTORE_GP(); + return ret; +} + +static int +cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, + CYG_ADDRWORD __vector, CYG_ADDRWORD __data) +{ + channel_data_t* chan = (channel_data_t*)__ch_data; + cyg_uint8 _iir; + int res = 0; + CYGARC_HAL_SAVE_GP(); + + HAL_READ_UINT8(chan->base+CYG_DEV_SERIAL_IIR, _iir); + _iir &= SIO_IIR_ID_MASK; + + *__ctrlc = 0; + if ( ISR_Rx == _iir ) { + cyg_uint8 c, lsr; + HAL_READ_UINT8(chan->base+CYG_DEV_SERIAL_LSR, lsr); + if (lsr & SIO_LSR_DR) { + + HAL_READ_UINT8(chan->base+CYG_DEV_SERIAL_RBR, c); + + if( cyg_hal_is_break( &c , 1 ) ) + *__ctrlc = 1; + } + + // Acknowledge the interrupt + HAL_INTERRUPT_ACKNOWLEDGE(chan->isr_vector); + res = CYG_ISR_HANDLED; + } + + CYGARC_HAL_RESTORE_GP(); + return res; +} + +static void +cyg_hal_plf_serial_init(void) +{ + hal_virtual_comm_table_t* comm; + int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + + // Disable interrupts. + HAL_INTERRUPT_MASK(channels[0].isr_vector); + HAL_INTERRUPT_MASK(channels[1].isr_vector); + + // Init channels + init_serial_channel(&channels[0]); + init_serial_channel(&channels[1]); + + // Setup procs in the vector table + + // Set channel 0 + CYGACC_CALL_IF_SET_CONSOLE_COMM(0); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, &channels[0]); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout); + + // Set channel 1 + CYGACC_CALL_IF_SET_CONSOLE_COMM(1); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, &channels[1]); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout); + + // Restore original console + CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); +} + +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG || CYGPRI_HAL_IMPLEMENTS_IF_SERVICES + + +//============================================================================= +// Compatibility with older stubs +//============================================================================= + +#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG + + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +#include <cyg/hal/drv_api.h> +#include <cyg/hal/hal_stub.h> // cyg_hal_gdb_interrupt +#endif + +// Assumption: all diagnostic output must be GDB packetized unless this is a ROM (i.e. +// totally stand-alone) system. + +#if defined(CYG_HAL_STARTUP_ROM) || defined(CYGDBG_HAL_DIAG_DISABLE_GDB_PROTOCOL) +#define HAL_DIAG_USES_HARDWARE +#endif + +/*---------------------------------------------------------------------------*/ +#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL==0 +// This is the base address of the A-channel +#define CYG_DEV_SERIAL_BASE CMA101_DUARTA +#define CYG_DEV_SERIAL_INT CYGNUM_HAL_INTERRUPT_SERIAL_A +#else +// This is the base address of the B-channel +#define CYG_DEV_SERIAL_BASE CMA101_DUARTB +#define CYG_DEV_SERIAL_INT CYGNUM_HAL_INTERRUPT_SERIAL_B +#endif + +static channel_data_t ser_channel = { (cyg_uint8*)CYG_DEV_SERIAL_BASE, 0, 0}; #ifdef HAL_DIAG_USES_HARDWARE @@ -173,20 +477,9 @@ void hal_diag_init(void) cyg_uint8 lcr; if (init++) return; - // 8-1-no parity. - HAL_WRITE_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_LCR, - SIO_LCR_WLS0 | SIO_LCR_WLS1); - HAL_READ_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_LCR, lcr); - lcr |= SIO_LCR_DLAB; - HAL_WRITE_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_LCR, lcr); - HAL_WRITE_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_DLL, - CYG_DEVICE_SERIAL_RS232_BAUD_LSB); - HAL_WRITE_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_DLM, - CYG_DEVICE_SERIAL_RS232_BAUD_MSB); - lcr &= ~SIO_LCR_DLAB; - HAL_WRITE_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_LCR, lcr); - HAL_WRITE_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_FCR, 0x07); // Enable & clear FIFO + init_serial_channel(&ser_channel); + while (*msg) hal_diag_write_char(*msg++); } @@ -205,11 +498,9 @@ void hal_diag_write_char(char c) cyg_uint8 lsr; hal_diag_init(); - do { - HAL_READ_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_LSR, lsr); - } while ((lsr & SIO_LSR_THRE) == 0); - HAL_WRITE_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_THR, c); + cyg_hal_plf_serial_putc(&ser_channel, c) + #ifdef DEBUG_DIAG diag_buffer[diag_bp++] = c; if (diag_bp == DIAG_BUFSIZE) { @@ -221,13 +512,7 @@ void hal_diag_write_char(char c) void hal_diag_read_char(char *c) { - cyg_uint8 lsr; - - do { - HAL_READ_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_LSR, lsr); - } while ((lsr & SIO_LSR_DR) == 0); - - HAL_READ_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_RBR, *c); + *c = cyg_hal_plf_serial_getc(&ser_channel); } #else // HAL_DIAG relies on GDB @@ -235,37 +520,23 @@ void hal_diag_read_char(char *c) // Initialize diag port - assume GDB channel is already set up void hal_diag_init(void) { + if (0) init_serial_channel(&ser_channel); // avoid warning } // Actually send character down the wire static void hal_diag_write_char_serial(char c) { - cyg_uint8 lsr; - - hal_diag_init(); - do { - HAL_READ_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_LSR, lsr); - } while ((lsr & SIO_LSR_THRE) == 0); - - HAL_WRITE_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_THR, c); - HAL_IO_BARRIER (); + cyg_hal_plf_serial_putc(&ser_channel, c); } static bool hal_diag_read_serial(char *c) { long timeout = 1000000000; // A long time... - cyg_uint8 lsr; + while (!cyg_hal_plf_serial_getc_nonblock(&ser_channel, c)) + if (0 == --timeout) return false; - do { - HAL_READ_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_LSR, lsr); - if (--timeout == 0) return false; - } while ((lsr & SIO_LSR_DR) == 0); - HAL_IO_BARRIER (); // Prevent RBR preload. - - HAL_READ_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_RBR, *c); - HAL_IO_BARRIER (); return true; } @@ -335,7 +606,7 @@ hal_diag_write_char(char c) break; // a good acknowledge #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT - cyg_drv_interrupt_acknowledge(CYG_DEVICE_SERIAL_INT); + cyg_drv_interrupt_acknowledge(CYG_DEV_SERIAL_INT); if( c1 == 3 ) { // Ctrl-C: breakpoint. cyg_hal_gdb_interrupt (__builtin_return_address(0)); @@ -358,5 +629,7 @@ hal_diag_write_char(char c) } #endif +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG + /*---------------------------------------------------------------------------*/ /* End of hal_diag.c */
--- a/packages/hal/arm/ebsa285/current/ChangeLog +++ b/packages/hal/arm/ebsa285/current/ChangeLog @@ -1,3 +1,14 @@ +2000-07-04 Jesper Skov <jskov@redhat.com> + + * src/plf_stub.c: [deleted] + * src/hal_diag.c: + * src/ebsa285_misc.c: + * include/plf_stub.h: + * include/hal_platform_ints.h: + * include/hal_diag.h: + * cdl/hal_arm_ebsa285.cdl: + Changed to use virtual vector table. + 2000-06-19 Gary Thomas <gthomas@redhat.com> * include/hal_platform_setup.h:
--- a/packages/hal/arm/ebsa285/current/cdl/hal_arm_ebsa285.cdl +++ b/packages/hal/arm/ebsa285/current/cdl/hal_arm_ebsa285.cdl @@ -49,10 +49,11 @@ cdl_package CYGPKG_HAL_ARM_EBSA285 { The EBSA285 HAL package provides the support needed to run eCos on a Intel EBSA285 StrongARM eval board." - compile hal_diag.c plf_stub.c ebsa285_misc.c mem285.S + compile hal_diag.c ebsa285_misc.c mem285.S implements CYGINT_HAL_DEBUG_GDB_STUBS implements CYGINT_HAL_DEBUG_GDB_STUBS_BREAK + implements CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT define_proc { puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H <pkgconf/hal_arm.h>" @@ -102,6 +103,33 @@ cdl_package CYGPKG_HAL_ARM_EBSA285 { increments." } + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS { + display "Number of communication channels on the board" + flavor data + calculated 1 + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL { + display "Debug serial port" + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + The EBSA285 board has only one serial port. This option + chooses which port will be used to connect to a host + running GDB." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL { + display "Diagnostic serial port" + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + The EBSA285 board has only one serial port. This option + chooses which port will be used for diagnostic output." + } + # Real-time clock/counter specifics cdl_component CYGNUM_HAL_RTC_CONSTANTS { display "Real-time clock constants" @@ -172,8 +200,8 @@ cdl_package CYGPKG_HAL_ARM_EBSA285 { requires CYGSEM_HAL_ROM_MONITOR requires CYGBLD_BUILD_COMMON_GDB_STUBS requires CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS - requires ! CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT - requires ! CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT + requires CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + requires CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT requires ! CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT requires ! CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM no_define @@ -271,4 +299,25 @@ cdl_package CYGPKG_HAL_ARM_EBSA285 { application. This enables features such as utilizing a separate interrupt stack when exceptions are generated." } + + cdl_option CYGSEM_HAL_USE_ROM_MONITOR { + display "Work with a ROM monitor" + flavor booldata + legal_values { "Generic" "GDB_stubs" } + default_value { CYG_HAL_STARTUP == "RAM" ? "GDB_stubs" : 0 } + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "RAM" } + description " + Support can be enabled for different varieties of ROM monitor. + This support changes various eCos semantics such as the encoding + of diagnostic output, or the overriding of hardware interrupt + vectors. + Firstly there is \"Generic\" support which prevents the HAL + from overriding the hardware vectors that it does not use, to + instead allow an installed ROM monitor to handle them. This is + the most basic support which is likely to be common to most + implementations of ROM monitor. + \"GDB_stubs\" provides support when GDB stubs are included in + the ROM monitor or boot ROM." + } }
--- a/packages/hal/arm/ebsa285/current/include/hal_diag.h +++ b/packages/hal/arm/ebsa285/current/include/hal_diag.h @@ -49,6 +49,16 @@ #include <cyg/infra/cyg_type.h> +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) + +#include <cyg/hal/hal_if.h> + +#define HAL_DIAG_INIT() hal_if_diag_init() +#define HAL_DIAG_WRITE_CHAR(_c_) hal_if_diag_write_char(_c_) +#define HAL_DIAG_READ_CHAR(_c_) hal_if_diag_read_char(&_c_) + +#else // everything by steam + /*---------------------------------------------------------------------------*/ /* functions implemented in hal_diag.c */ @@ -64,6 +74,8 @@ externC void hal_diag_read_char(char *c) #define HAL_DIAG_READ_CHAR(_c_) hal_diag_read_char(&_c_) +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG + /*---------------------------------------------------------------------------*/ /* end of hal_diag.h */ #endif /* CYGONCE_HAL_DIAG_H */
--- a/packages/hal/arm/ebsa285/current/include/hal_platform_ints.h +++ b/packages/hal/arm/ebsa285/current/include/hal_platform_ints.h @@ -88,15 +88,4 @@ // The vector used by the Real time clock #define CYGNUM_HAL_INTERRUPT_RTC CYGNUM_HAL_INTERRUPT_TIMER_3 -// The vector used by hal_diag (for reception) -#define CYG_DIAG_DEV_INT CYGNUM_HAL_INTERRUPT_SERIAL_RX -// The vector used by gdb stubs (for reception) -#define CYG_GDB_DEV_INT CYGNUM_HAL_INTERRUPT_SERIAL_RX - -// Do we want to poll in the default ISR for ^C interrupt chars? -#ifdef CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT -extern int hal_ctrlc_isr( CYG_ADDRWORD vector, CYG_ADDRWORD data); -#define CYGDBG_HAL_CTRLC_ISR( _V_, _D_ ) hal_ctrlc_isr( _V_, _D_ ) -#endif - #endif // CYGONCE_HAL_PLATFORM_INTS_H
--- a/packages/hal/arm/ebsa285/current/include/plf_stub.h +++ b/packages/hal/arm/ebsa285/current/include/plf_stub.h @@ -51,29 +51,32 @@ #include <cyg/infra/cyg_type.h> // CYG_UNUSED_PARAM -#include <cyg/hal/hal_ebsa285.h> // registers -#include <cyg/hal/hal_io.h> // IO macros #include <cyg/hal/arm_stub.h> // architecture stub support //---------------------------------------------------------------------------- -// Define serial stuff. +// Define some platform specific communication details. This is mostly +// handled by hal_if now, but we need to make sure the comms tables are +// properly initialized. + +externC void cyg_hal_plf_comms_init(void); -extern void hal_ebsa285_init_serial(void); -extern int hal_ebsa285_get_char(void); -extern void hal_ebsa285_put_char(int c); -extern int hal_ebsa285_interruptible(int); +#define HAL_STUB_PLATFORM_INIT_SERIAL() cyg_hal_plf_comms_init() -#define HAL_STUB_PLATFORM_INIT_SERIAL() hal_ebsa285_init_serial() -#define HAL_STUB_PLATFORM_GET_CHAR() hal_ebsa285_get_char() -#define HAL_STUB_PLATFORM_PUT_CHAR(c) hal_ebsa285_put_char((c)) #define HAL_STUB_PLATFORM_SET_BAUD_RATE(baud) CYG_UNUSED_PARAM(int, (baud)) +#define HAL_STUB_PLATFORM_INTERRUPTIBLE 0 +#define HAL_STUB_PLATFORM_INIT_BREAK_IRQ() CYG_EMPTY_STATEMENT //---------------------------------------------------------------------------- // Stub initializer. #define HAL_STUB_PLATFORM_INIT() CYG_EMPTY_STATEMENT +#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + //---------------------------------------------------------------------------- // Reset. +#include <cyg/hal/hal_ebsa285.h> // registers +#include <cyg/hal/hal_io.h> // IO macros + #define HAL_STUB_PLATFORM_RESET() \ CYG_MACRO_START \ cyg_uint32 ctrl; \ @@ -95,14 +98,7 @@ extern int hal_ebsa285_interruptible(in for(;;); /* wait for it */ \ CYG_MACRO_END -#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT -#define HAL_STUB_PLATFORM_INIT_BREAK_IRQ() CYG_EMPTY_STATEMENT -#define HAL_STUB_PLATFORM_INTERRUPTIBLE (&hal_ebsa285_interruptible) -#else -#define HAL_STUB_PLATFORM_INTERRUPTIBLE 0 -#endif - -#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +#define HAL_STUB_PLATFORM_RESET_ENTRY 0x41000000 //----------------------------------------------------------------------------- #endif // CYGONCE_HAL_PLF_STUB_H
--- a/packages/hal/arm/ebsa285/current/src/ebsa285_misc.c +++ b/packages/hal/arm/ebsa285/current/src/ebsa285_misc.c @@ -50,6 +50,7 @@ #include <cyg/infra/cyg_ass.h> // assertion macros #include <cyg/hal/hal_io.h> // IO macros +#include <cyg/hal/hal_if.h> // calling interface API #include <cyg/hal/hal_arch.h> // Register state info #include <cyg/hal/hal_diag.h> #include <cyg/hal/hal_intr.h> // Interrupt names @@ -112,15 +113,8 @@ void hal_hardware_init(void) HAL_DCACHE_ENABLE(); HAL_ICACHE_ENABLE(); -#ifndef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS -#ifdef CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT - // then enable the interrupt for incoming characters and break - // into the stub ROM if the char is a ^C. - HAL_INTERRUPT_UNMASK( CYG_DIAG_DEV_INT ); - // hal_diag.c: hal_ctrlc_isr( CYG_ADDRWORD vector, CYG_ADDRWORD data) - // is polled from the default ISR so it's OK just to enable this. -#endif -#endif + // Set up eCos/ROM interfaces + hal_if_init(); } // -------------------------------------------------------------------------
--- a/packages/hal/arm/ebsa285/current/src/hal_diag.c +++ b/packages/hal/arm/ebsa285/current/src/hal_diag.c @@ -52,12 +52,273 @@ #include <cyg/hal/hal_arch.h> // basic machine info #include <cyg/hal/hal_intr.h> // interrupt macros #include <cyg/hal/hal_io.h> // IO macros +#include <cyg/hal/hal_if.h> // calling interface API +#include <cyg/hal/hal_misc.h> // helper functions #include <cyg/hal/hal_diag.h> +#include <cyg/hal/hal_ebsa285.h> // Hardware definitions +#include <cyg/hal/drv_api.h> // cyg_drv_interrupt_acknowledge + +/*---------------------------------------------------------------------------*/ + +struct ebsa_serial { + volatile cyg_uint32 data_register; + volatile cyg_uint32 rxstat; + volatile cyg_uint32 h_baud_control; + volatile cyg_uint32 m_baud_control; + volatile cyg_uint32 l_baud_control; + volatile cyg_uint32 control_register; + volatile cyg_uint32 flag_register; +}; + +/*---------------------------------------------------------------------------*/ + +static void +init_channel(void* __ch_data) +{ + volatile struct ebsa_serial* base = (struct ebsa_serial*)__ch_data; + + int dummy; + /* + * Make sure everything is off + */ + base->control_register = SA110_UART_DISABLED | SA110_SIR_DISABLED; + + /* + * Read the RXStat to drain the fifo + */ + dummy = base->rxstat; + + /* + * Set the baud rate - this also turns the uart on. + * + * Note that the ordering of these writes is critical, + * and the writes to the H_BAUD_CONTROL and CONTROL_REGISTER + * are necessary to force the UART to update its register + * contents. + */ + base->l_baud_control = 0x13; // bp->divisor_low; + base->m_baud_control = 0x00; // bp->divisor_high; + base->h_baud_control = SA110_UART_BREAK_DISABLED | + SA110_UART_PARITY_DISABLED | + SA110_UART_STOP_BITS_ONE | + SA110_UART_FIFO_ENABLED | + SA110_UART_DATA_LENGTH_8_BITS; + base->control_register = SA110_UART_ENABLED | SA110_SIR_DISABLED; + // All done +} + +void +cyg_hal_plf_serial_putc(void *__ch_data, char c) +{ + volatile struct ebsa_serial* base = (struct ebsa_serial*)__ch_data; + CYGARC_HAL_SAVE_GP(); + + // Wait for Tx FIFO not full + while ((base->flag_register & SA110_TX_FIFO_STATUS_MASK) == SA110_TX_FIFO_BUSY) + ; + base->data_register = c; + + CYGARC_HAL_RESTORE_GP(); +} + + +static cyg_bool +cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch) +{ + volatile struct ebsa_serial* base = (struct ebsa_serial*)__ch_data; + + + if ((base->flag_register & SA110_RX_FIFO_STATUS_MASK) == SA110_RX_FIFO_EMPTY) + return false; + + *ch = (char)(base->data_register & 0xFF); + + return true; +} + + +cyg_uint8 +cyg_hal_plf_serial_getc(void* __ch_data) +{ + cyg_uint8 ch; + CYGARC_HAL_SAVE_GP(); + + while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch)); + + CYGARC_HAL_RESTORE_GP(); + return ch; +} + +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) \ + || defined(CYGPRI_HAL_IMPLEMENTS_IF_SERVICES) + +static cyg_int32 msec_timeout; + +static void +cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, + cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + cyg_hal_plf_serial_putc(__ch_data, *__buf++); + + CYGARC_HAL_RESTORE_GP(); +} + +static void +cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + *__buf++ = cyg_hal_plf_serial_getc(__ch_data); + + CYGARC_HAL_RESTORE_GP(); +} + +cyg_bool +cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch) +{ + int delay_count; + cyg_bool res; + CYGARC_HAL_SAVE_GP(); + + delay_count = msec_timeout * 10; // delay in .1 ms steps + + for(;;) { + res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch); + if (res || 0 == delay_count--) + break; + + CYGACC_CALL_IF_DELAY_US(100); + } + + CYGARC_HAL_RESTORE_GP(); + return res; +} + +static int +cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...) +{ + static int irq_state = 0; + int ret = 0; + CYGARC_HAL_SAVE_GP(); + + switch (__func) { + case __COMMCTL_IRQ_ENABLE: + irq_state = 1; + + HAL_INTERRUPT_UNMASK(CYGNUM_HAL_INTERRUPT_SERIAL_RX); + break; + case __COMMCTL_IRQ_DISABLE: + ret = irq_state; + irq_state = 0; + + HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SERIAL_RX); + break; + case __COMMCTL_DBG_ISR_VECTOR: + ret = CYGNUM_HAL_INTERRUPT_SERIAL_RX; + break; + case __COMMCTL_SET_TIMEOUT: + { + va_list ap; + + va_start(ap, __func); + + ret = msec_timeout; + msec_timeout = va_arg(ap, cyg_uint32); + + va_end(ap); + } + default: + break; + } + CYGARC_HAL_RESTORE_GP(); + return ret; +} + +static int +cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, + CYG_ADDRWORD __vector, CYG_ADDRWORD __data) +{ + int reg, res = 0; + volatile struct ebsa_serial* base = (struct ebsa_serial*)__ch_data; + char c; + 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); + + 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(); + return res; +} + +static void +cyg_hal_plf_serial_init(void) +{ + hal_virtual_comm_table_t* comm; + int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + + // Init channels + init_channel((void*)UART_BASE_0); + + // Setup procs in the vector table + + // Set channel 0 + CYGACC_CALL_IF_SET_CONSOLE_COMM(0); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, UART_BASE_0); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout); + + // Restore original console + CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); +} + +void +cyg_hal_plf_comms_init(void) +{ + static int initialized = 0; + + if (initialized) + return; + + initialized = 1; + + cyg_hal_plf_serial_init(); +} +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG || CYGPRI_HAL_IMPLEMENTS_IF_SERVICES + + + +//============================================================================= +// Compatibility with older stubs +//============================================================================= + +#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG + #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS -#include <cyg/hal/drv_api.h> // cyg_drv_interrupt_acknowledge #include <cyg/hal/hal_stub.h> // cyg_hal_gdb_interrupt #endif -#include <cyg/hal/hal_ebsa285.h> // Hardware definitions #ifdef CYGSEM_HAL_ROM_MONITOR #define CYG_HAL_STARTUP_ROM @@ -71,24 +332,26 @@ /*---------------------------------------------------------------------------*/ // EBSA285 Serial Port (UARTx) for Debug +void hal_diag_init(void) +{ + init_channel((void*)UART_BASE_0); +} + + // Actually send character down the wire static void hal_diag_write_char_serial(char c) { - // Wait for Tx FIFO not full - while ((*SA110_UART_FLAG_REGISTER & SA110_TX_FIFO_STATUS_MASK) == SA110_TX_FIFO_BUSY) - ; - *SA110_UART_DATA_REGISTER = c; + cyg_hal_plf_serial_putc((void*)UART_BASE_0, c); } static bool hal_diag_read_serial(char *c) { long timeout = 1000000000; // A long time... - while ((*SA110_UART_FLAG_REGISTER & SA110_RX_FIFO_STATUS_MASK) == SA110_RX_FIFO_EMPTY) - if ( --timeout == 0 ) - return false; - *c = (char)(*SA110_UART_DATA_REGISTER & 0xFF); + while (! cyg_hal_plf_serial_getc_nonblock((void*)UART_BASE_0, c) ) + if ( --timeout == 0 ) return false; + return true; } @@ -124,39 +387,6 @@ const static struct _baud bauds[] = { }; #endif -void hal_diag_init(void) -{ - int dummy; - /* - * Make sure everything is off - */ - *SA110_UART_CONTROL_REGISTER = SA110_UART_DISABLED | SA110_SIR_DISABLED; - - /* - * Read the RXStat to drain the fifo - */ - dummy = *SA110_UART_RXSTAT; - - /* - * Set the baud rate - this also turns the uart on. - * - * Note that the ordering of these writes is critical, - * and the writes to the H_BAUD_CONTROL and CONTROL_REGISTER - * are necessary to force the UART to update its register - * contents. - */ - *SA110_UART_L_BAUD_CONTROL = 0x13; // bp->divisor_low; - *SA110_UART_M_BAUD_CONTROL = 0x00; // bp->divisor_high; - *SA110_UART_H_BAUD_CONTROL = SA110_UART_BREAK_DISABLED | - SA110_UART_PARITY_DISABLED | - SA110_UART_STOP_BITS_ONE | - SA110_UART_FIFO_ENABLED | - SA110_UART_DATA_LENGTH_8_BITS; - *SA110_UART_CONTROL_REGISTER = SA110_UART_ENABLED | - SA110_SIR_DISABLED; - // All done -} - #ifdef HAL_DIAG_USES_HARDWARE #ifdef DEBUG_DIAG @@ -270,7 +500,7 @@ hal_diag_write_char(char c) break; // a good acknowledge #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT - cyg_drv_interrupt_acknowledge(CYG_DIAG_DEV_INT); + cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_SERIAL_RX); if( c1 == 3 ) { // Ctrl-C: breakpoint. cyg_hal_gdb_interrupt( @@ -297,31 +527,7 @@ hal_diag_write_char(char c) } #endif -/*---------------------------------------------------------------------------*/ -#ifndef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS -#ifdef CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT -// This routine is polled from the default ISR - the assumption is that any -// other ISR installed knows what it's going and can handle a ^C correctly. -int hal_ctrlc_isr( CYG_ADDRWORD vector, CYG_ADDRWORD data) -{ - char c; - int reg; - if ( CYG_DIAG_DEV_INT != vector ) - return 0; // not for us - - reg = *SA110_UART_FLAG_REGISTER; - // read it anyway just in case - no harm done and we might prevent an - // interrup loop - c = (char)(*SA110_UART_DATA_REGISTER & 0xFF); - if ( (reg & SA110_RX_FIFO_STATUS_MASK) != SA110_RX_FIFO_EMPTY ) { - if ( 3 == c ) { - HAL_BREAKPOINT( hal_ctrlc_isr_breakinst ); - } - } - return 1; -} -#endif -#endif +#endif // !CYGSEM_HAL_VIRTUAL_VECTOR_DIAG /*---------------------------------------------------------------------------*/ /* End of hal_diag.c */
--- a/packages/hal/arm/edb7xxx/current/ChangeLog +++ b/packages/hal/arm/edb7xxx/current/ChangeLog @@ -1,3 +1,27 @@ +2000-07-07 Jesper Skov <jskov@redhat.com> + + * src/edb7xxx_misc.c (dram_delay_loop): + * src/hal_diag.c (cyg_hal_plf_serial_getc, + (cyg_hal_plf_serial_putc): Added delay loop. + +2000-07-05 Jesper Skov <jskov@redhat.com> + + * include/plf_stub.h (HAL_STUB_PLATFORM_RESET_ENTRY): Not comitted. + + * src/hal_diag.c: + * cdl/hal_arm_edb7xxx.cdl: + Clean up channel options. + + * src/plf_stub.c: [deleted] + * src/hal_diag.c: + * src/edb7xxx_misc.c: + * include/plf_stub.h: + * include/hal_diag.h: + * cdl/hal_arm_edb7xxx.cdl: + Changed to use virtual vectors. + + * include/hal_platform_setup.h: #error instead of #err. + 2000-06-18 Gary Thomas <gthomas@redhat.com> * include/pkgconf/mlt_arm_cl7111_ram.ldi:
--- a/packages/hal/arm/edb7xxx/current/cdl/hal_arm_edb7xxx.cdl +++ b/packages/hal/arm/edb7xxx/current/cdl/hal_arm_edb7xxx.cdl @@ -50,10 +50,11 @@ cdl_package CYGPKG_HAL_ARM_EDB7XXX { The EDB7XXX HAL package provides the support needed to run eCos on a Cirrus Logic development board." - compile hal_diag.c plf_stub.c edb7xxx_misc.c + compile hal_diag.c edb7xxx_misc.c implements CYGINT_HAL_DEBUG_GDB_STUBS implements CYGINT_HAL_DEBUG_GDB_STUBS_BREAK + implements CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT define_proc { puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H <pkgconf/hal_arm.h>" @@ -115,17 +116,7 @@ cdl_package CYGPKG_HAL_ARM_EDB7XXX { into ROM." } - cdl_option CYGHWR_HAL_ARM_EDB7XXX_DIAG_PORT { - display "Diagnostic serial port" - flavor data - legal_values 0 1 - default_value 0 - description " - The Cirrus Logic evaluation boards have two separate serial ports. This option - chooses which of these ports will be used." - } - - cdl_option CYGHWR_HAL_ARM_EDB7XXX_DIAG_BAUD { + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD { display "Diagnostic serial port baud rate" flavor data legal_values 9600 19200 38400 115200 @@ -136,18 +127,7 @@ cdl_package CYGPKG_HAL_ARM_EDB7XXX { diagnostic and GDB port are the same." } - cdl_option CYGHWR_HAL_ARM_EDB7XXX_GDB_PORT { - display "GDB serial port" - flavor data - legal_values 0 1 - default_value 0 - description " - The Cirrus Logic evlauation boards have two separate serial ports. This option - chooses which of these ports will be used to connect to a host - running GDB." - } - - cdl_option CYGHWR_HAL_ARM_EDB7XXX_GDB_BAUD { + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD { display "GDB serial port baud rate" flavor data legal_values 9600 19200 38400 115200 @@ -156,6 +136,33 @@ cdl_package CYGPKG_HAL_ARM_EDB7XXX { This option controls the baud rate used for the GDB connection." } + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS { + display "Number of communication channels on the board" + flavor data + calculated 2 + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL { + display "Debug serial port" + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + The EDB7xxx boards have two serial ports. This option + chooses which port will be used to connect to a host + running GDB." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL { + display "Diagnostic serial port" + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + The EDB7xxx boards have two serial ports. This option + chooses which port will be used for diagnostic output." + } + cdl_option CYGHWR_HAL_ARM_EDB7XXX_PROCESSOR_CLOCK { display "Processor clock rate" flavor data @@ -268,8 +275,8 @@ cdl_package CYGPKG_HAL_ARM_EDB7XXX { requires CYGSEM_HAL_ROM_MONITOR requires CYGBLD_BUILD_COMMON_GDB_STUBS requires CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS - requires ! CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT - requires ! CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT + requires CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + requires CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT requires ! CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT requires ! CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM no_define @@ -531,4 +538,25 @@ cdl_package CYGPKG_HAL_ARM_EDB7XXX { } } } + + cdl_option CYGSEM_HAL_USE_ROM_MONITOR { + display "Work with a ROM monitor" + flavor booldata + legal_values { "Generic" "GDB_stubs" } + default_value { CYG_HAL_STARTUP == "RAM" ? "GDB_stubs" : 0 } + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "RAM" } + description " + Support can be enabled for different varieties of ROM monitor. + This support changes various eCos semantics such as the encoding + of diagnostic output, or the overriding of hardware interrupt + vectors. + Firstly there is \"Generic\" support which prevents the HAL + from overriding the hardware vectors that it does not use, to + instead allow an installed ROM monitor to handle them. This is + the most basic support which is likely to be common to most + implementations of ROM monitor. + \"GDB_stubs\" provides support when GDB stubs are included in + the ROM monitor or boot ROM." + } }
--- a/packages/hal/arm/edb7xxx/current/include/hal_diag.h +++ b/packages/hal/arm/edb7xxx/current/include/hal_diag.h @@ -49,6 +49,16 @@ #include <cyg/infra/cyg_type.h> +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) + +#include <cyg/hal/hal_if.h> + +#define HAL_DIAG_INIT() hal_if_diag_init() +#define HAL_DIAG_WRITE_CHAR(_c_) hal_if_diag_write_char(_c_) +#define HAL_DIAG_READ_CHAR(_c_) hal_if_diag_read_char(&_c_) + +#else // everything by steam + /*---------------------------------------------------------------------------*/ /* functions implemented in hal_diag.c */ @@ -64,6 +74,8 @@ externC void hal_diag_read_char(char *c) #define HAL_DIAG_READ_CHAR(_c_) hal_diag_read_char(&_c_) +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG + /*---------------------------------------------------------------------------*/ /* end of hal_diag.h */ #endif /* CYGONCE_HAL_DIAG_H */
--- a/packages/hal/arm/edb7xxx/current/include/hal_platform_setup.h +++ b/packages/hal/arm/edb7xxx/current/include/hal_platform_setup.h @@ -113,7 +113,7 @@ // Define startup code [macros] #if defined(CYGSEM_HAL_INSTALL_MMU_TABLES) && !defined(CYG_HAL_STARTUP_RAM) -#ifdef CYGPKG_HAL_ARM_CL7111 // CL7111, 710 processor +#ifdef CYGHWR_HAL_ARM_EDB7XXX_VARIANT_CL_PS7111 // CL7111, 710 processor #define MMU_INITIALIZE \ ldr r2,=MMU_Control_Init ;\ mcr MMU_CP,0,r2,MMU_Control,c0 /* MMU off */ ;\ @@ -315,7 +315,7 @@ 15: mov r6,r5 /* Build page table entry b 10b /* Next section */ ;\ 20: #else -#err Invalid DRAM size select +#error Invalid DRAM size select #endif #define PLATFORM_SETUP1 \
--- a/packages/hal/arm/edb7xxx/current/include/plf_stub.h +++ b/packages/hal/arm/edb7xxx/current/include/plf_stub.h @@ -54,24 +54,24 @@ #include <cyg/hal/arm_stub.h> // architecture stub support //---------------------------------------------------------------------------- -// Define serial stuff. +// Define some platform specific communication details. This is mostly +// handled by hal_if now, but we need to make sure the comms tables are +// properly initialized. -extern void hal_edb7xxx_init_serial(void); -extern int hal_edb7xxx_get_char(void); -extern void hal_edb7xxx_put_char(int c); -extern int hal_edb7xxx_interruptible(int); +externC void cyg_hal_plf_comms_init(void); -#define HAL_STUB_PLATFORM_INIT_SERIAL() hal_edb7xxx_init_serial() -#define HAL_STUB_PLATFORM_GET_CHAR() hal_edb7xxx_get_char() -#define HAL_STUB_PLATFORM_PUT_CHAR(c) hal_edb7xxx_put_char((c)) +#define HAL_STUB_PLATFORM_INIT_SERIAL() cyg_hal_plf_comms_init() + #define HAL_STUB_PLATFORM_SET_BAUD_RATE(baud) CYG_UNUSED_PARAM(int, (baud)) -#define HAL_STUB_PLATFORM_INTERRUPTIBLE (&hal_edb7xxx_interruptible) +#define HAL_STUB_PLATFORM_INTERRUPTIBLE 0 #define HAL_STUB_PLATFORM_INIT_BREAK_IRQ() CYG_EMPTY_STATEMENT //---------------------------------------------------------------------------- // Stub initializer. #define HAL_STUB_PLATFORM_INIT() CYG_EMPTY_STATEMENT +#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + //---------------------------------------------------------------------------- // Reset. @@ -80,7 +80,7 @@ extern int hal_edb7xxx_interruptible(in externC void reset_platform(void); #define HAL_STUB_PLATFORM_RESET() reset_platform() -#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +#define HAL_STUB_PLATFORM_RESET_ENTRY 0xe0000000 //----------------------------------------------------------------------------- #endif // CYGONCE_HAL_PLF_STUB_H
--- a/packages/hal/arm/edb7xxx/current/src/edb7xxx_misc.c +++ b/packages/hal/arm/edb7xxx/current/src/edb7xxx_misc.c @@ -55,6 +55,7 @@ #include <cyg/hal/hal_intr.h> // Interrupt names #include <cyg/hal/hal_cache.h> #include <cyg/hal/hal_edb7xxx.h> // Hardware definitions +#include <cyg/hal/hal_if.h> // calling interface API // #define CYGHWR_HAL_ARM_EDB7XXX_BATLOW #ifdef CYGHWR_HAL_ARM_EDB7XXX_BATLOW @@ -155,6 +156,16 @@ void hal_clock_read(cyg_uint32 *pvalue) *pvalue = (cyg_uint32)(_period - clock_val); // 'clock_val' counts down and wraps } +void +dram_delay_loop(void) +{ + // Temporary fix for DRAM starvation problem + if (CYGHWR_HAL_ARM_EDB7XXX_PROCESSOR_CLOCK > 37000) { + int i; + for (i = 0; i < (CYGHWR_HAL_ARM_EDB7XXX_PROCESSOR_CLOCK*2)/24; i++) ; // approx 300 us + } +} + // These tables map the various [soft] interrupt numbers onto the hardware static cyg_uint32 hal_interrupt_bitmap[] = { @@ -382,6 +393,9 @@ void hal_hardware_init(void) cyg_drv_interrupt_attach(batlow_interrupt_handle); cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_BLINT); #endif + + // Set up eCos/ROM interfaces + hal_if_init(); } //
--- a/packages/hal/arm/edb7xxx/current/src/hal_diag.c +++ b/packages/hal/arm/edb7xxx/current/src/hal_diag.c @@ -52,25 +52,277 @@ #include <cyg/hal/hal_arch.h> // basic machine info #include <cyg/hal/hal_intr.h> // interrupt macros #include <cyg/hal/hal_io.h> // IO macros +#include <cyg/hal/hal_if.h> // calling interface API +#include <cyg/hal/hal_misc.h> // helper functions #include <cyg/hal/hal_diag.h> -#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS #include <cyg/hal/drv_api.h> -#include <cyg/hal/hal_stub.h> // cyg_hal_gdb_interrupt -#endif #include <cyg/hal/hal_edb7xxx.h> // Hardware definitions -#if CYGHWR_HAL_ARM_EDB7XXX_DIAG_PORT == 0 -#define CYG_DIAG_DEV_DATA UARTDR1 -#define CYG_DIAG_DEV_BLCR UBLCR1 -#define CYG_DIAG_DEV_STAT SYSFLG1 -#define CYG_DIAG_DEV_CTRL SYSCON1 -#define CYG_DIAG_DEV_INT CYGNUM_HAL_INTERRUPT_URXINT1 -#else -#define CYG_DIAG_DEV_DATA UARTDR2 -#define CYG_DIAG_DEV_STAT SYSFLG2 -#define CYG_DIAG_DEV_CTRL SYSCON2 -#define CYG_DIAG_DEV_BLCR UBLCR2 -#define CYG_DIAG_DEV_INT CYGNUM_HAL_INTERRUPT_URXINT2 +//----------------------------------------------------------------------------- + +struct edb_serial { + volatile cyg_uint32 ctrl; + cyg_uint32 pad004_040[16-1]; + volatile cyg_uint32 stat; + cyg_uint32 pad044_37c[208-1]; + union { + volatile cyg_uint8 write; + volatile cyg_uint32 read; // Need to read 32 bits + } data; + cyg_uint32 pad384_3BC[16-1]; + volatile cyg_uint32 blcr; +}; + +//----------------------------------------------------------------------------- +typedef struct { + volatile struct edb_serial* base; + cyg_int32 msec_timeout; + int isr_vector; +} channel_data_t; + +//----------------------------------------------------------------------------- + +static void +cyg_hal_plf_serial_init_channel(channel_data_t* __ch_data) +{ + channel_data_t* chan = (channel_data_t*)__ch_data; + + // Enable port + chan->base->ctrl |= SYSCON1_UART1EN; + // Configure + chan->base->blcr = UART_BITRATE(CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD) | + UBLCR_FIFOEN | UBLCR_WRDLEN8; +} + + +// Call this delay function when polling for serial access - otherwise +// the CPU will keep the memory bus busy and thus prevent DRAM refresh +// (and the resulting memory corruption). +externC void dram_delay_loop(void); + +void +cyg_hal_plf_serial_putc(void *__ch_data, char c) +{ + channel_data_t* chan = (channel_data_t*)__ch_data; + CYGARC_HAL_SAVE_GP(); + + // Wait for Tx FIFO not full + while ((chan->base->stat & SYSFLG1_UTXFF1) != 0) + dram_delay_loop(); + + chan->base->data.write = c; + + CYGARC_HAL_RESTORE_GP(); +} + +static cyg_bool +cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch) +{ + channel_data_t* chan = (channel_data_t*)__ch_data; + + if ((chan->base->stat & SYSFLG1_URXFE1) != 0) + return false; + + *ch = (cyg_uint8)(chan->base->data.read & 0xFF); + + return true; +} + +cyg_uint8 +cyg_hal_plf_serial_getc(void* __ch_data) +{ + cyg_uint8 ch; + CYGARC_HAL_SAVE_GP(); + + while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch)) + dram_delay_loop(); + + CYGARC_HAL_RESTORE_GP(); + return ch; +} + +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) \ + || defined(CYGPRI_HAL_IMPLEMENTS_IF_SERVICES) + +static channel_data_t edb_ser_channels[2] = { + {(volatile struct edb_serial*)SYSCON1, 1000, CYGNUM_HAL_INTERRUPT_URXINT1}, + {(volatile struct edb_serial*)SYSCON2, 1000, CYGNUM_HAL_INTERRUPT_URXINT2} +}; + +static void +cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, + cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + cyg_hal_plf_serial_putc(__ch_data, *__buf++); + + CYGARC_HAL_RESTORE_GP(); +} + +static void +cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + *__buf++ = cyg_hal_plf_serial_getc(__ch_data); + + CYGARC_HAL_RESTORE_GP(); +} + +cyg_bool +cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch) +{ + int delay_count; + channel_data_t* chan = (channel_data_t*)__ch_data; + cyg_bool res; + CYGARC_HAL_SAVE_GP(); + + delay_count = chan->msec_timeout * 10; // delay in .1 ms steps + + for(;;) { + res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch); + if (res || 0 == delay_count--) + break; + + CYGACC_CALL_IF_DELAY_US(100); + } + + CYGARC_HAL_RESTORE_GP(); + return res; +} + +static int +cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...) +{ + static int irq_state = 0; + channel_data_t* chan = (channel_data_t*)__ch_data; + int ret = 0; + CYGARC_HAL_SAVE_GP(); + + switch (__func) { + case __COMMCTL_IRQ_ENABLE: + irq_state = 1; + HAL_INTERRUPT_UNMASK(chan->isr_vector); + break; + case __COMMCTL_IRQ_DISABLE: + ret = irq_state; + irq_state = 0; + HAL_INTERRUPT_MASK(chan->isr_vector); + break; + case __COMMCTL_DBG_ISR_VECTOR: + ret = chan->isr_vector; + break; + case __COMMCTL_SET_TIMEOUT: + { + va_list ap; + + va_start(ap, __func); + + ret = chan->msec_timeout; + chan->msec_timeout = va_arg(ap, cyg_uint32); + + va_end(ap); + } + default: + break; + } + CYGARC_HAL_RESTORE_GP(); + return ret; +} + +static int +cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, + CYG_ADDRWORD __vector, CYG_ADDRWORD __data) +{ + int res = 0; + channel_data_t* chan = (channel_data_t*)__ch_data; + char c; + CYGARC_HAL_SAVE_GP(); + + cyg_drv_interrupt_acknowledge(chan->isr_vector); + + *__ctrlc = 0; + if ((chan->base->stat & SYSFLG1_URXFE1) == 0) { + c = (cyg_uint8)(chan->base->data.read & 0xFF); + if( cyg_hal_is_break( &c , 1 ) ) + *__ctrlc = 1; + + res = CYG_ISR_HANDLED; + } + + CYGARC_HAL_RESTORE_GP(); + return res; +} + +static void +cyg_hal_plf_serial_init(void) +{ + hal_virtual_comm_table_t* comm; + int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + + // Disable interrupts. + HAL_INTERRUPT_MASK(edb_ser_channels[0].isr_vector); + HAL_INTERRUPT_MASK(edb_ser_channels[1].isr_vector); + + // Init channels + cyg_hal_plf_serial_init_channel(&edb_ser_channels[0]); + cyg_hal_plf_serial_init_channel(&edb_ser_channels[1]); + + // Setup procs in the vector table + + // Set channel 0 + CYGACC_CALL_IF_SET_CONSOLE_COMM(0); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, &edb_ser_channels[0]); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout); + + // Set channel 1 + CYGACC_CALL_IF_SET_CONSOLE_COMM(1); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, &edb_ser_channels[1]); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout); + + // Restore original console + CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); +} + +void +cyg_hal_plf_comms_init(void) +{ + static int initialized = 0; + + if (initialized) + return; + + initialized = 1; + + cyg_hal_plf_serial_init(); +} +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG || CYGPRI_HAL_IMPLEMENTS_IF_SERVICES + +//============================================================================= +// Compatibility with older stubs +//============================================================================= + +#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +#include <cyg/hal/hal_stub.h> // cyg_hal_gdb_interrupt #endif // Assumption: all diagnostic output must be GDB packetized unless this is a ROM (i.e. @@ -86,11 +338,23 @@ #else #if defined(CYGDBG_HAL_DIAG_DISABLE_GDB_PROTOCOL) #define HAL_DIAG_USES_HARDWARE -#elif CYGHWR_HAL_ARM_EDB7XXX_DIAG_PORT != CYGHWR_HAL_ARM_EDB7XXX_GDB_PORT +#elif CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL != CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL #define HAL_DIAG_USES_HARDWARE #endif #endif +#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == 0 +# define __BASE ((volatile struct edb_serial*)SYSCON1) +# define __IRQ CYGNUM_HAL_INTERRUPT_URXINT1 +#else +# define __BASE ((volatile struct edb_serial*)SYSCON2) +# define __IRQ CYGNUM_HAL_INTERRUPT_URXINT2 +#endif + +static channel_data_t edb_ser_channel = { + __BASE, 0, 0 +}; + /*---------------------------------------------------------------------------*/ // EDB7XXX Serial Port (UARTx) for Debug @@ -98,27 +362,17 @@ static void hal_diag_write_char_serial(char c) { - cyg_uint32 stat; - // Wait for Tx FIFO not full - do { - stat = *(volatile cyg_uint32 *)CYG_DIAG_DEV_STAT; - } while ((stat & SYSFLG1_UTXFF1) != 0) ; - *(volatile cyg_uint8 *)CYG_DIAG_DEV_DATA = c; + cyg_hal_plf_serial_putc(&edb_ser_channel, c); } static bool hal_diag_read_serial(char *c) { long timeout = 1000000000; // A long time... - cyg_uint32 stat, val; - do { - stat = *(volatile cyg_uint32 *)CYG_DIAG_DEV_STAT; + while (! cyg_hal_plf_serial_getc_nonblock(&edb_ser_channel, c) ) if (--timeout == 0) return false; - } while ((stat & SYSFLG1_URXFE1) != 0); - // Need to read 32 bits - val = *(volatile cyg_uint32 *)CYG_DIAG_DEV_DATA & 0xFF; - *c = val; + return true; } @@ -132,12 +386,8 @@ void hal_diag_init(void) #endif if (init++) return; - // Enable port - *(volatile cyg_uint32 *)CYG_DIAG_DEV_CTRL |= SYSCON1_UART1EN; - // Configure - *(volatile cyg_uint32 *)CYG_DIAG_DEV_BLCR = - UART_BITRATE(CYGHWR_HAL_ARM_EDB7XXX_DIAG_BAUD) | - UBLCR_FIFOEN | UBLCR_WRDLEN8; + cyg_hal_plf_serial_init_channel(&edb_ser_channel); + #ifndef CYG_HAL_STARTUP_ROM while (*msg) hal_diag_write_char(*msg++); #endif @@ -173,14 +423,8 @@ void hal_diag_read_char(char *c) // Initialize diag port void hal_diag_init(void) { -#if 0 // Assume port is already setup - // Enable port - *(volatile cyg_uint32 *)CYG_DIAG_DEV_CTRL |= SYSCON1_UART1EN; - // Configure - *(volatile cyg_uint32 *)CYG_DIAG_DEV_BLCR = - UART_BITRATE(CYGHWR_HAL_ARM_EDB7XXX_DIAG_BAUD) | - UBLCR_FIFOEN | UBLCR_WRDLEN8; -#endif + // Assume port is already setup + if (0) cyg_hal_plf_serial_init_channel(&edb_ser_channel); } void @@ -250,7 +494,7 @@ hal_diag_write_char(char c) break; // a good acknowledge #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT - cyg_drv_interrupt_acknowledge(CYG_DIAG_DEV_INT); + cyg_drv_interrupt_acknowledge(__IRQ); if( c1 == 3 ) { // Ctrl-C: breakpoint. cyg_hal_gdb_interrupt (__builtin_return_address(0)); @@ -274,5 +518,7 @@ hal_diag_write_char(char c) } #endif +#endif // !CYGSEM_HAL_VIRTUAL_VECTOR_DIAG + /*---------------------------------------------------------------------------*/ /* End of hal_diag.c */
--- a/packages/hal/arm/pid/current/ChangeLog +++ b/packages/hal/arm/pid/current/ChangeLog @@ -1,3 +1,13 @@ +2000-07-07 Jesper Skov <jskov@redhat.com> + + * cdl/hal_arm_pid.cdl: CygMon changed to use virtual vectors. + +2000-07-05 Jesper Skov <jskov@redhat.com> + + * src/hal_diag.c: + * cdl/hal_arm_pid.cdl: + Clean up channel options. + 2000-07-04 Jesper Skov <jskov@redhat.com> * cdl/hal_arm_pid.cdl:
--- a/packages/hal/arm/pid/current/cdl/hal_arm_pid.cdl +++ b/packages/hal/arm/pid/current/cdl/hal_arm_pid.cdl @@ -84,17 +84,7 @@ cdl_package CYGPKG_HAL_ARM_PID { } - cdl_option CYGHWR_HAL_ARM_PID_DIAG_PORT { - display "Diagnostic serial port" - flavor data - legal_values 0 1 - default_value 0 - description " - The PID board has two separate serial ports. This option - chooses which of these ports will be used." - } - - cdl_option CYGHWR_HAL_ARM_PID_DIAG_BAUD { + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD { display "Diagnostic serial port baud rate" flavor data legal_values 9600 19200 38400 115200 @@ -105,18 +95,7 @@ cdl_package CYGPKG_HAL_ARM_PID { diagnostic and GDB port are the same." } - cdl_option CYGHWR_HAL_ARM_PID_GDB_PORT { - display "GDB serial port" - flavor data - legal_values 0 1 - default_value 0 - description " - The PID board has two separate serial ports. This option - chooses which of these ports will be used to connect to a host - running GDB." - } - - cdl_option CYGHWR_HAL_ARM_PID_GDB_BAUD { + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD { display "GDB serial port baud rate" flavor data legal_values 9600 19200 38400 115200 @@ -153,7 +132,7 @@ cdl_package CYGPKG_HAL_ARM_PID { display "Debug serial port" flavor data legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 - default_value CYGHWR_HAL_ARM_PID_GDB_PORT + default_value 0 description " The PID board has only one serial port. This option chooses which port will be used to connect to a host @@ -164,7 +143,7 @@ cdl_package CYGPKG_HAL_ARM_PID { display "Diagnostic serial port" flavor data legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 - default_value CYGHWR_HAL_ARM_PID_DIAG_PORT + default_value 0 description " The PID board has only one serial port. This option chooses which port will be used for diagnostic output." @@ -272,7 +251,7 @@ cdl_package CYGPKG_HAL_ARM_PID { display "Build flash programming tool" default_value 0 requires { CYG_HAL_STARTUP == "RAM" } - requires CYGHWR_HAL_ARM_PID_DIAG_PORT == 1 + requires CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == 1 requires CYGPKG_LIBC requires CYGPKG_KERNEL no_define @@ -294,7 +273,7 @@ cdl_package CYGPKG_HAL_ARM_PID { display "Build flash programming tool for BE images on LE boards" default_value 0 requires { CYG_HAL_STARTUP == "RAM" } - requires CYGHWR_HAL_ARM_PID_DIAG_PORT == 1 + requires CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == 1 requires CYGPKG_LIBC requires CYGPKG_KERNEL no_define @@ -364,28 +343,11 @@ cdl_package CYGPKG_HAL_ARM_PID { no_define parent CYGPKG_CYGMON active_if CYGPKG_CYGMON - requires CYGPKG_IO_SERIAL_ARM_PID - requires {(CYGDAT_CYGMON_CONSOLE_DEV != "\"/dev/ser0\"") || \ - (CYGPKG_IO_SERIAL_ARM_PID_SERIAL0 && \ - (CYGNUM_IO_SERIAL_ARM_PID_SERIAL0_BUFSIZE == 512))} - requires {(CYGDAT_CYGMON_CONSOLE_DEV != "\"/dev/ser1\"") || \ - (CYGPKG_IO_SERIAL_ARM_PID_SERIAL1 && \ - (CYGNUM_IO_SERIAL_ARM_PID_SERIAL1_BUFSIZE == 512))} description " This option also lists the target's requirements for a valid CygMon configuration." - cdl_option CYGDAT_CYGMON_CONSOLE_DEV { - display "Serial port for default console" - flavor data - default_value { "\"/dev/ser0\"" } - description " - This option selects the physical device to use as the default - console device for CygMon." - - } - cdl_option CYGBLD_BUILD_CYGMON_BIN { display "Build CygMon ROM binary image" active_if CYGBLD_BUILD_CYGMON
--- a/packages/hal/arm/pid/current/src/hal_diag.c +++ b/packages/hal/arm/pid/current/src/hal_diag.c @@ -58,19 +58,19 @@ /*---------------------------------------------------------------------------*/ /* From serial_16550.h */ -#if CYGHWR_HAL_ARM_PID_DIAG_BAUD==9600 +#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==9600 #define CYG_DEVICE_SERIAL_BAUD_MSB 0x00 #define CYG_DEVICE_SERIAL_BAUD_LSB 0x0C #endif -#if CYGHWR_HAL_ARM_PID_DIAG_BAUD==19200 +#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==19200 #define CYG_DEVICE_SERIAL_BAUD_MSB 0x00 #define CYG_DEVICE_SERIAL_BAUD_LSB 0x06 #endif -#if CYGHWR_HAL_ARM_PID_DIAG_BAUD==38400 +#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==38400 #define CYG_DEVICE_SERIAL_BAUD_MSB 0x00 #define CYG_DEVICE_SERIAL_BAUD_LSB 0x03 #endif -#if CYGHWR_HAL_ARM_PID_DIAG_BAUD==115200 +#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==115200 #define CYG_DEVICE_SERIAL_BAUD_MSB 0x00 #define CYG_DEVICE_SERIAL_BAUD_LSB 0x01 #endif @@ -414,7 +414,7 @@ hal_diag_led(int n) #include <cyg/hal/hal_stub.h> // cyg_hal_gdb_interrupt #endif -#if CYGHWR_HAL_ARM_PID_DIAG_PORT==0 +#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL==0 // This is the base address of the A-channel #define CYG_DEV_SERIAL_BASE 0x0D800000 #define CYG_DEVICE_SERIAL_INT CYGNUM_HAL_INTERRUPT_SERIALA @@ -436,7 +436,7 @@ static channel_data_t pid_ser_channel = #endif #ifndef HAL_DIAG_USES_HARDWARE -#if (CYGHWR_HAL_ARM_PID_DIAG_PORT != CYGHWR_HAL_ARM_PID_GDB_PORT) +#if (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL != CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL) #define HAL_DIAG_USES_HARDWARE #endif #endif
--- a/packages/hal/arm/sa11x0/assabet/current/ChangeLog +++ b/packages/hal/arm/sa11x0/assabet/current/ChangeLog @@ -1,3 +1,7 @@ +2000-07-05 Jesper Skov <jskov@redhat.com> + + * cdl/hal_arm_sa11x0_assabet.cdl: Cleanup channel options. + 2000-06-27 Jesper Skov <jskov@redhat.com> * cdl/hal_arm_sa11x0_assabet.cdl: Changed PORT values.
--- a/packages/hal/arm/sa11x0/assabet/current/cdl/hal_arm_sa11x0_assabet.cdl +++ b/packages/hal/arm/sa11x0/assabet/current/cdl/hal_arm_sa11x0_assabet.cdl @@ -79,19 +79,7 @@ cdl_package CYGPKG_HAL_ARM_SA11X0_ASSABE building the eCos GDB stubs themselves." } - # Assabet board has only 1 serial port useable for diagnostic/GDB -## define CYGHWR_HAL_ARM_SA11X0_DIAG_PORT 1 -# FIXME - make this fixed. - cdl_option CYGHWR_HAL_ARM_SA11X0_DIAG_PORT { - display "Diagnostic serial port" - flavor data - legal_values 0 0 - default_value 0 - description " - The Assabet evaluation boards has only one serial port." - } - - cdl_option CYGHWR_HAL_ARM_SA11X0_DIAG_BAUD { + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD { display "Diagnostic serial port baud rate" flavor data legal_values 9600 19200 38400 115200 @@ -102,16 +90,7 @@ cdl_package CYGPKG_HAL_ARM_SA11X0_ASSABE diagnostic and GDB port are the same." } - cdl_option CYGHWR_HAL_ARM_SA11X0_GDB_PORT { - display "GDB serial port" - flavor data - legal_values 0 0 - default_value 0 - description " - The Assabet evaluation boards has only one serial port." - } - - cdl_option CYGHWR_HAL_ARM_SA11X0_GDB_BAUD { + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD { display "GDB serial port baud rate" flavor data legal_values 9600 19200 38400 115200
--- a/packages/hal/arm/sa11x0/brutus/current/ChangeLog +++ b/packages/hal/arm/sa11x0/brutus/current/ChangeLog @@ -1,3 +1,7 @@ +2000-07-05 Jesper Skov <jskov@redhat.com> + + * cdl/hal_arm_sa11x0_brutus.cdl: Cleanup channel options. + 2000-06-26 Jesper Skov <jskov@redhat.com> * include/hal_platform_ints.h: Removed Ctrl-c handling.
--- a/packages/hal/arm/sa11x0/brutus/current/cdl/hal_arm_sa11x0_brutus.cdl +++ b/packages/hal/arm/sa11x0/brutus/current/cdl/hal_arm_sa11x0_brutus.cdl @@ -79,17 +79,7 @@ cdl_package CYGPKG_HAL_ARM_SA11X0_BRUTUS building the eCos GDB stubs themselves." } - cdl_option CYGHWR_HAL_ARM_SA11X0_DIAG_PORT { - display "Diagnostic serial port" - flavor data - legal_values 0 1 - default_value 1 - description " - The Brutus evaluation boards have two separate serial ports. This option - chooses which of these ports will be used." - } - - cdl_option CYGHWR_HAL_ARM_SA11X0_DIAG_BAUD { + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD { display "Diagnostic serial port baud rate" flavor data legal_values 9600 19200 38400 115200 @@ -100,17 +90,7 @@ cdl_package CYGPKG_HAL_ARM_SA11X0_BRUTUS diagnostic and GDB port are the same." } - cdl_option CYGHWR_HAL_ARM_SA11X0_GDB_PORT { - display "GDB serial port" - flavor data - legal_values 0 1 - default_value 1 - description " - The Brutus evaluation boards have two separate serial ports. This option - chooses which of these ports will be used." - } - - cdl_option CYGHWR_HAL_ARM_SA11X0_GDB_BAUD { + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD { display "GDB serial port baud rate" flavor data legal_values 9600 19200 38400 115200 @@ -131,7 +111,7 @@ cdl_package CYGPKG_HAL_ARM_SA11X0_BRUTUS display "Debug serial port" flavor data legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 - default_value CYGHWR_HAL_ARM_SA11X0_GDB_PORT + default_value 1 description " The brutus board has two serial ports. This option chooses which port will be used to connect to a host @@ -142,7 +122,7 @@ cdl_package CYGPKG_HAL_ARM_SA11X0_BRUTUS display "Diagnostic serial port" flavor data legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 - default_value CYGHWR_HAL_ARM_SA11X0_DIAG_PORT + default_value 1 description " The brutus board has two serial ports. This option chooses which port will be used for diagnostic output."
--- a/packages/hal/arm/sa11x0/var/current/ChangeLog +++ b/packages/hal/arm/sa11x0/var/current/ChangeLog @@ -1,3 +1,18 @@ +2000-07-14 Gary Thomas <gthomas@redhat.com> + + * include/hal_diag.h (HAL_DELAY_US): Define. + + * src/sa11x0_misc.c (hal_delay_us): New function. Used to + provide timers/delays in non-kernel systems. + +2000-07-05 Jesper Skov <jskov@redhat.com> + + * cdl/hal_arm_sa11x0.cdl: + * src/hal_diag.c: + Cleaned up channel options. + + * src/hal_diag.c: Use per-channel structure instead of code cruft. + 2000-06-30 Jesper Skov <jskov@redhat.com> * src/hal_diag.c: calling i/f macro changes.
--- a/packages/hal/arm/sa11x0/var/current/include/hal_diag.h +++ b/packages/hal/arm/sa11x0/var/current/include/hal_diag.h @@ -60,6 +60,11 @@ #define HAL_DIAG_WRITE_CHAR(_c_) hal_if_diag_write_char(_c_) #define HAL_DIAG_READ_CHAR(_c_) hal_if_diag_read_char(&_c_) +// Not the best place for this, but ... +extern void hal_delay_us(cyg_int32 usecs); + +#define HAL_DELAY_US(n) hal_delay_us(n); + #else /*---------------------------------------------------------------------------*/
--- a/packages/hal/arm/sa11x0/var/current/src/hal_diag.c +++ b/packages/hal/arm/sa11x0/var/current/src/hal_diag.c @@ -71,13 +71,20 @@ struct sa11x0_serial { volatile cyg_uint32 utsr1; }; +//----------------------------------------------------------------------------- +typedef struct { + volatile struct sa11x0_serial* base; + cyg_int32 msec_timeout; + int isr_vector; +} channel_data_t; + /*---------------------------------------------------------------------------*/ // SA11x0 Serial Port (UARTx) for Debug static void -init_channel(void* __ch_data) +init_channel(channel_data_t* __ch_data) { - volatile struct sa11x0_serial* base = (struct sa11x0_serial*)__ch_data; + volatile struct sa11x0_serial* base = __ch_data->base; cyg_uint32 brd; // Disable Receiver and Transmitter (clears FIFOs) @@ -106,7 +113,7 @@ init_channel(void* __ch_data) SA11X0_UART_DATA_BITS_8; // Set the desired baud rate. - brd = SA11X0_UART_BAUD_RATE_DIVISOR(CYGHWR_HAL_ARM_SA11X0_DIAG_BAUD); + brd = SA11X0_UART_BAUD_RATE_DIVISOR(CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD); base->utcr1 = (brd >> 8) & SA11X0_UART_H_BAUD_RATE_DIVISOR_MASK; base->utcr2 = brd & SA11X0_UART_L_BAUD_RATE_DIVISOR_MASK; @@ -119,7 +126,7 @@ init_channel(void* __ch_data) void cyg_hal_plf_serial_putc(void *__ch_data, char c) { - volatile struct sa11x0_serial* base = (struct sa11x0_serial*)__ch_data; + volatile struct sa11x0_serial* base = ((channel_data_t*)__ch_data)->base; CYGARC_HAL_SAVE_GP(); // Wait for Tx FIFO not full @@ -137,7 +144,7 @@ cyg_hal_plf_serial_putc(void *__ch_data, static cyg_bool cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch) { - volatile struct sa11x0_serial* base = (struct sa11x0_serial*)__ch_data; + volatile struct sa11x0_serial* base = ((channel_data_t*)__ch_data)->base; // If receive fifo is empty, return false if ((base->utsr1 & SA11X0_UART_RX_FIFO_NOT_EMPTY) == 0) @@ -167,6 +174,11 @@ cyg_hal_plf_serial_getc(void* __ch_data) #if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) \ || defined(CYGPRI_HAL_IMPLEMENTS_IF_SERVICES) +static channel_data_t ser_channels[2] = { + { (volatile struct sa11x0_serial*)SA11X0_UART1_BASE, 1000, CYGNUM_HAL_INTERRUPT_UART1 }, + { (volatile struct sa11x0_serial*)SA11X0_UART3_BASE, 1000, CYGNUM_HAL_INTERRUPT_UART3 } +}; + static void cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len) @@ -190,22 +202,15 @@ cyg_hal_plf_serial_read(void* __ch_data, CYGARC_HAL_RESTORE_GP(); } -cyg_int32 msec_timeout[2] = { 1000, 1000 }; - cyg_bool cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch) { int delay_count; - int index; + channel_data_t* chan = (channel_data_t*)__ch_data; cyg_bool res; CYGARC_HAL_SAVE_GP(); - if (SA11X0_UART1_BASE == __ch_data) - index = 0; - else - index = 1; - - delay_count = msec_timeout[index] * 10; // delay in .1 ms steps + delay_count = chan->msec_timeout * 10; // delay in .1 ms steps for(;;) { res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch); @@ -219,41 +224,32 @@ cyg_hal_plf_serial_getc_timeout(void* __ return res; } -static int isr_vectors[2] = {CYGNUM_HAL_INTERRUPT_UART1, - CYGNUM_HAL_INTERRUPT_UART3}; - static int cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...) { static int irq_state = 0; - volatile struct sa11x0_serial* base = (struct sa11x0_serial*)__ch_data; + channel_data_t* chan = (channel_data_t*)__ch_data; int ret = 0; - int index; CYGARC_HAL_SAVE_GP(); - if (SA11X0_UART1_BASE == __ch_data) - index = 0; - else - index = 1; - switch (__func) { case __COMMCTL_IRQ_ENABLE: irq_state = 1; - base->utcr3 |= SA11X0_UART_RX_FIFO_INT_ENABLED; + chan->base->utcr3 |= SA11X0_UART_RX_FIFO_INT_ENABLED; - HAL_INTERRUPT_UNMASK(isr_vectors[index]); + HAL_INTERRUPT_UNMASK(chan->isr_vector); break; case __COMMCTL_IRQ_DISABLE: ret = irq_state; irq_state = 0; - base->utcr3 &= ~SA11X0_UART_RX_FIFO_INT_ENABLED; + chan->base->utcr3 &= ~SA11X0_UART_RX_FIFO_INT_ENABLED; - HAL_INTERRUPT_MASK(isr_vectors[index]); + HAL_INTERRUPT_MASK(chan->isr_vector); break; case __COMMCTL_DBG_ISR_VECTOR: - ret = isr_vectors[index]; + ret = chan->isr_vector; break; case __COMMCTL_SET_TIMEOUT: { @@ -261,8 +257,8 @@ cyg_hal_plf_serial_control(void *__ch_da va_start(ap, __func); - ret = msec_timeout[index]; - msec_timeout[index] = va_arg(ap, cyg_uint32); + ret = chan->msec_timeout; + chan->msec_timeout = va_arg(ap, cyg_uint32); va_end(ap); } @@ -277,28 +273,23 @@ static int cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, CYG_ADDRWORD __vector, CYG_ADDRWORD __data) { - int index, res = 0; - volatile struct sa11x0_serial* base = (struct sa11x0_serial*)__ch_data; + int res = 0; + channel_data_t* chan = (channel_data_t*)__ch_data; char c; int reg; CYGARC_HAL_SAVE_GP(); - if (SA11X0_UART1_BASE == __ch_data) - index = 0; - else - index = 1; - - reg = base->utsr1; + reg = chan->base->utsr1; // read it anyway just in case - no harm done and we might prevent an // interrupt loop - c = (char)base->utdr; + c = (char)chan->base->utdr; //Clear receiver idle status bit, to allow another interrupt to //occur in the case where the receive fifo is almost empty. - base->utsr0 = SA11X0_UART_RX_IDLE; + chan->base->utsr0 = SA11X0_UART_RX_IDLE; - cyg_drv_interrupt_acknowledge(isr_vectors[index]); + cyg_drv_interrupt_acknowledge(chan->isr_vector); *__ctrlc = 0; if ( (reg & SA11X0_UART_RX_FIFO_NOT_EMPTY) != 0 ) { @@ -319,9 +310,9 @@ cyg_hal_plf_serial_init(void) int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); // Init channels - init_channel((void*)SA11X0_UART1_BASE); + init_channel(&ser_channels[0]); #if (CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS == 2) - init_channel((void*)SA11X0_UART3_BASE); + init_channel(&ser_channels[1]); #endif // Setup procs in the vector table @@ -329,7 +320,7 @@ cyg_hal_plf_serial_init(void) // Set channel 0 CYGACC_CALL_IF_SET_CONSOLE_COMM(0); comm = CYGACC_CALL_IF_CONSOLE_PROCS(); - CYGACC_COMM_IF_CH_DATA_SET(*comm, SA11X0_UART1_BASE); + CYGACC_COMM_IF_CH_DATA_SET(*comm, &ser_channels[0]); CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); @@ -342,7 +333,7 @@ cyg_hal_plf_serial_init(void) // Set channel 1 CYGACC_CALL_IF_SET_CONSOLE_COMM(1); comm = CYGACC_CALL_IF_CONSOLE_PROCS(); - CYGACC_COMM_IF_CH_DATA_SET(*comm, SA11X0_UART3_BASE); + CYGACC_COMM_IF_CH_DATA_SET(*comm, &ser_channels[1]); CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); @@ -379,10 +370,12 @@ cyg_hal_plf_comms_init(void) #include <cyg/hal/hal_stub.h> // cyg_hal_gdb_interrupt -#if (CYGHWR_HAL_ARM_SA11X0_DIAG_PORT == 0) +#if (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == 0) # define __BASE ((void*)SA11X0_UART1_BASE) +# define CYGHWR_HAL_GDB_PORT_VECTOR CYGNUM_HAL_INTERRUPT_UART1 #else # define __BASE ((void*)SA11X0_UART3_BASE) +# define CYGHWR_HAL_GDB_PORT_VECTOR CYGNUM_HAL_INTERRUPT_UART3 #endif #ifdef CYGSEM_HAL_ROM_MONITOR @@ -394,15 +387,19 @@ cyg_hal_plf_comms_init(void) #define HAL_DIAG_USES_HARDWARE #elif defined(CYGDBG_HAL_DIAG_DISABLE_GDB_PROTOCOL) #define HAL_DIAG_USES_HARDWARE -#elif CYGHWR_HAL_ARM_SA11X0_DIAG_PORT != CYGHWR_HAL_ARM_SA11X0_GDB_PORT +#elif CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL != CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL #define HAL_DIAG_USES_HARDWARE #endif +static channel_data_t ser_channel = { + (volatile struct sa11x0_serial*)__BASE, 0, CYGHWR_HAL_GDB_PORT_VECTOR +}; + void hal_diag_init(void) { // Init serial device - init_channel(__BASE); + init_channel(&ser_channel); } #ifdef HAL_DIAG_USES_HARDWARE @@ -417,7 +414,7 @@ static int diag_bp = 0; void hal_diag_read_char(char *c) { - *c = cyg_hal_plf_serial_getc(__BASE); + *c = cyg_hal_plf_serial_getc(&ser_channel); } void hal_diag_write_char(char c) @@ -428,7 +425,7 @@ void hal_diag_write_char(char c) if (diag_bp == sizeof(diag_buffer)) diag_bp = 0; #endif #endif - cyg_hal_plf_serial_putc(__BASE, c); + cyg_hal_plf_serial_putc(&ser_channel, c); } #else // not HAL_DIAG_USES_HARDWARE - it uses GDB protocol @@ -436,7 +433,7 @@ void hal_diag_write_char(char c) void hal_diag_read_char(char *c) { - *c = cyg_hal_plf_serial_getc(__BASE); + *c = cyg_hal_plf_serial_getc(&ser_channel); } void @@ -476,22 +473,22 @@ hal_diag_write_char(char c) #ifndef CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT char c1; #endif - cyg_hal_plf_serial_putc(__BASE, '$'); - cyg_hal_plf_serial_putc(__BASE, 'O'); + cyg_hal_plf_serial_putc(&ser_channel, '$'); + cyg_hal_plf_serial_putc(&ser_channel, 'O'); csum += 'O'; for( i = 0; i < pos; i++ ) { char ch = line[i]; char h = hex[(ch>>4)&0xF]; char l = hex[ch&0xF]; - cyg_hal_plf_serial_putc(__BASE, h); - cyg_hal_plf_serial_putc(__BASE, l); + cyg_hal_plf_serial_putc(&ser_channel, h); + cyg_hal_plf_serial_putc(&ser_channel, l); csum += h; csum += l; } - cyg_hal_plf_serial_putc(__BASE, '#'); - cyg_hal_plf_serial_putc(__BASE, hex[(csum>>4)&0xF]); - cyg_hal_plf_serial_putc(__BASE, hex[csum&0xF]); + cyg_hal_plf_serial_putc(&ser_channel, '#'); + cyg_hal_plf_serial_putc(&ser_channel, hex[(csum>>4)&0xF]); + cyg_hal_plf_serial_putc(&ser_channel, hex[csum&0xF]); #ifdef CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT @@ -502,7 +499,7 @@ hal_diag_write_char(char c) // Wait for the ACK character '+' from GDB here and handle // receiving a ^C instead. This is the reason for this clause // being a loop. - c1 = cyg_hal_plf_serial_getc(__BASE); + c1 = cyg_hal_plf_serial_getc(&ser_channel); if( c1 == '+' ) break; // a good acknowledge
--- a/packages/hal/arm/sa11x0/var/current/src/sa11x0_misc.c +++ b/packages/hal/arm/sa11x0/var/current/src/sa11x0_misc.c @@ -85,6 +85,10 @@ void hal_hardware_init(void) // Perform any platform specific initializations plf_hardware_init(); + // Let the "OS" counter run + *SA11X0_OSCR = 0; + *SA11X0_OSMR0 = 0; + // Set up eCos/ROM interfaces hal_if_init(); @@ -159,6 +163,30 @@ void hal_clock_read(cyg_uint32 *pvalue) *pvalue = ctr; } +// +// Delay for some number of micro-seconds +// +void hal_delay_us(cyg_int32 usecs) +{ + int diff, diff2; + cyg_uint32 val1, val2; + while (usecs-- > 0) { + diff = 0; + while (diff < 3) { + val1 = *SA11X0_OSCR; + while ((val2 = *SA11X0_OSCR) == val1) ; + if (*SA11X0_OSMR0) { + // A kernel is running, the counter may get reset as we watch + diff2 = val2 - val1; + if (diff2 < 0) diff2 += *SA11X0_OSMR0; + diff += diff2; + } else { + diff += val2 - val1; + } + } + } +} + // ------------------------------------------------------------------------- // This routine is called to respond to a hardware interrupt (IRQ). It
--- a/packages/hal/common/current/ChangeLog +++ b/packages/hal/common/current/ChangeLog @@ -1,3 +1,25 @@ +2000-07-14 Gary Thomas <gthomas@redhat.com> + + * src/hal_if.c (delay_us): Use HAL_DELAY_US() if defined. + +2000-07-07 Jesper Skov <jskov@redhat.com> + + * src/hal_stub.c (initHardware): Fix #endif location. + + * src/hal_if.c (hal_ctrlc_isr_init): Added hack to work around a + silly but critical problem. + + * src/hal_stub.c: Removed some CygMon conditional exclusions. + + * src/hal_if.c (hal_ctrlc_isr_init): Don't enable interrupts when + configured as ROM monitor. + +2000-07-05 Jesper Skov <jskov@redhat.com> + + * cdl/debugging.cdl: Only allow CTRLC support if there's stubs or + a ROM monitor to handle it. (Haruki Kashiwaya (kashiwaya at redhat + dot com)). + 2000-06-30 Jesper Skov <jskov@redhat.com> * include/hal_if.h: Make CYGACC macros call functions. May have to @@ -826,7 +848,6 @@ 1999-01-29 Jesper Skov <jskov@cygnus.c * include/pkgconf/hal.h: Added simple MPC8xx configuration. - 1999-01-26 Hugo Tyson <hmt@cygnus.co.uk> * tests/cache.c (time0): Waste much less time if running in a @@ -865,7 +886,6 @@ 1999-01-21 Jesper Skov <jskov@cygnus.c * include/pkgconf/hal.h: Add CYG_KERNEL_USE_INIT_PRIORITY for SPARCLITE. - 1999-01-18 Jesper Skov <jskov@cygnus.co.uk> PR 18823 * include/pkgconf/hal.h: Don't allow GDB stubs to be configured @@ -912,7 +932,6 @@ Wed Dec 9 14:07:30 GMT 1998 Chris Prov * include/pkgconf/hal.h: Compile the i386 linux target with CYG_KERNEL_USE_INIT_PRIORITY defined. - 1999-01-04 Jesper Skov <jskov@cygnus.co.uk> * src/generic-stub.c (interruptible): Cleaned up a bit.
--- a/packages/hal/common/current/cdl/debugging.cdl +++ b/packages/hal/common/current/cdl/debugging.cdl @@ -91,6 +91,7 @@ cdl_interface CYGINT_HAL_DEBUG_GDB_CTRLC cdl_option CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT { display "Include GDB external break support when no stubs" requires !CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + active_if { CYGSEM_HAL_USE_ROM_MONITOR || CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS } active_if { CYGINT_HAL_DEBUG_GDB_CTRLC_UNSUPPORTED == 0 } default_value 1 description "
--- a/packages/hal/common/current/src/hal_if.c +++ b/packages/hal/common/current/src/hal_if.c @@ -104,6 +104,11 @@ delay_us(cyg_int32 usecs) } while (usec_ticks > 0); CYGARC_HAL_RESTORE_GP(); +#else + // Use a HAL feature if defined +#ifdef HAL_DELAY_US + HAL_DELAY_US(usecs); +#endif #endif } @@ -364,14 +369,26 @@ struct Hal_SavedRegisters *hal_saved_int void hal_ctrlc_isr_init(void) { + // A ROM monitor never enables the interrupt itself. This is left + // to the (RAM) application. +#ifndef CYGSEM_HAL_ROM_MONITOR hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); #if 1 // Prevents crash on older stubs if (CYGNUM_CALL_IF_TABLE_VERSION != CYGACC_CALL_IF_VERSION()) return; + + // Now trash that value - otherwise downloading an image with + // builtin stubs on a board with older stubs may cause all + // subsequent runs to (wrongly) fall through to the below code. + // If there is a new stub on the board, it will reinitialize the + // version field on reset. + // Yes, this is a gross hack! + CYGACC_CALL_IF_VERSION_SET(CYGNUM_CALL_IF_TABLE_VERSION+1); #endif CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE); +#endif } cyg_uint32
--- a/packages/hal/common/current/src/hal_stub.c +++ b/packages/hal/common/current/src/hal_stub.c @@ -501,7 +501,6 @@ initHardware (void) return; initialized = 1; -#if !defined(CYGPKG_CYGMON) // Get serial port initialized. HAL_STUB_PLATFORM_INIT_SERIAL(); @@ -530,28 +529,25 @@ initHardware (void) // Set the debug channel. CYGACC_CALL_IF_SET_DEBUG_COMM(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL); } +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT #ifdef HAL_STUB_PLATFORM_INIT // If the platform defines any initialization code, call it here. HAL_STUB_PLATFORM_INIT(); #endif -#endif -#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT +#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this should go away #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT // Get interrupt handler initialized. HAL_STUB_PLATFORM_INIT_BREAK_IRQ(); #endif -#endif // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT -#endif // CYGPKG_CYGMON - +#endif // !CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT } // Reset the board. void __reset (void) { -#if !defined(CYGPKG_CYGMON) #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT __call_if_reset_t __rom_reset = CYGACC_CALL_IF_RESET_GET(); if (__rom_reset) @@ -559,7 +555,6 @@ void #else HAL_STUB_PLATFORM_RESET(); #endif -#endif } //-----------------------------------------------------------------------------
--- a/packages/hal/sh/arch/current/ChangeLog +++ b/packages/hal/sh/arch/current/ChangeLog @@ -58,13 +58,6 @@ 2000-06-08 Jesper Skov <jskov@redhat.c * src/vectors.S: Minor config change to get rid of growing list of variant checks. -2000-06-08 Jesper Skov <jskov@redhat.com> - - * include/mod_7707a.h: - * src/vectors.S: - * cdl/hal_sh.cdl: - Added first level of support for 7707A variant. - 2000-06-06 Jesper Skov <jskov@redhat.com> * src/vectors.S: INTEVT2 is not defined on all variants. Protect
--- a/packages/hal/sh/arch/current/cdl/hal_sh.cdl +++ b/packages/hal/sh/arch/current/cdl/hal_sh.cdl @@ -91,21 +91,6 @@ cdl_package CYGPKG_HAL_SH { @rm target.tmp } - cdl_option CYGPKG_HAL_SH_7707A { - display "SH 7707A microprocessor" - implements CYGINT_HAL_SH_VARIANT - default_value 0 - no_define - define -file=system.h CYGPKG_HAL_SH_7707A - description " - The SH3 7707A microprocessor. This is an embedded part that in - addition to the SH3 processor core has built in peripherals - such as memory controllers, serial ports, LCD controller and - timers/counters." - define_proc { - puts $cdl_system_header "#define CYGBLD_HAL_CPU_MODULES_H <cyg/hal/mod_7707a.h>" - } - } cdl_option CYGPKG_HAL_SH_7708 { display "SH 7708 microprocessor"
--- a/packages/hal/sh/arch/current/include/hal_intr.h +++ b/packages/hal/sh/arch/current/include/hal_intr.h @@ -130,6 +130,9 @@ #define CYGNUM_HAL_ISR_MAX CYGNUM_HAL_INTERRUPT_REF_ROVI +//---------------------------------------------------------------------------- +// Additional vectors provided by INTC V2 + //#ifdef CYGARC_SH_MOD_INTC_V2 // FIXME #define CYGNUM_HAL_INTERRUPT_RESERVED_5C0 32 #define CYGNUM_HAL_INTERRUPT_HUDI_HUDI 33 @@ -170,6 +173,7 @@ #endif // CYGARC_SH_MOD_INTC_V2 + // CYGNUM_HAL_ISR_COUNT must match CYG_ISR_TABLE_SIZE defined in vectors.S. #define CYGNUM_HAL_ISR_MIN CYGNUM_HAL_INTERRUPT_NMI #define CYGNUM_HAL_ISR_COUNT ( CYGNUM_HAL_ISR_MAX + 1 )
--- a/packages/hal/sh/arch/current/include/sh_regs.h +++ b/packages/hal/sh/arch/current/include/sh_regs.h @@ -341,6 +341,7 @@ # define CYGARC_REG_IPRE 0xa400001a //#endif + #define CYGARC_REG_IPRA_TMU0_MASK 0xf000 #define CYGARC_REG_IPRA_TMU0_PRI1 0x1000 #define CYGARC_REG_IPRA_TMU1_MASK 0x0f00
--- a/packages/hal/sh/cq7708/current/ChangeLog +++ b/packages/hal/sh/cq7708/current/ChangeLog @@ -1,3 +1,11 @@ +2000-07-07 Jesper Skov <jskov@redhat.com> + + * cdl/hal_sh_sh7708_cq7708.cdl: Require sub-variant package. + +2000-07-05 Jesper Skov <jskov@redhat.com> + + * src/hal_diag.c: Include hal_if.c + 2000-06-29 Jesper Skov <jskov@redhat.com> * src/hal_diag.c: serial driver API changes.
--- a/packages/hal/sh/cq7708/current/cdl/hal_sh_sh7708_cq7708.cdl +++ b/packages/hal/sh/cq7708/current/cdl/hal_sh_sh7708_cq7708.cdl @@ -43,6 +43,7 @@ cdl_package CYGPKG_HAL_SH_SH7708_CQ7708 { display "CqREEK SH7708 board" parent CYGPKG_HAL_SH + requires CYGPKG_HAL_SH_7708 define_header hal_sh_sh7708_cq7708.h include_dir cyg/hal description "
--- a/packages/hal/sh/cq7708/current/src/hal_diag.c +++ b/packages/hal/sh/cq7708/current/src/hal_diag.c @@ -47,6 +47,7 @@ #include <cyg/infra/cyg_type.h> // base types, externC #include <cyg/hal/hal_io.h> // IO macros +#include <cyg/hal/hal_if.h> // calling interface API #include <cyg/hal/hal_intr.h> // Interrupt macros #include <cyg/hal/sh3_sci.h> // driver API #include <cyg/hal/hal_misc.h> // Helper functions
--- a/packages/hal/sh/edk/current/ChangeLog +++ b/packages/hal/sh/edk/current/ChangeLog @@ -1,3 +1,7 @@ +2000-07-07 Jesper Skov <jskov@redhat.com> + + * cdl/hal_sh_edk7708.cdl: Require sub-variant package. + 2000-06-29 Jesper Skov <jskov@redhat.com> * src/hal_diag.c: serial driver API changes.
--- a/packages/hal/sh/edk/current/cdl/hal_sh_edk7708.cdl +++ b/packages/hal/sh/edk/current/cdl/hal_sh_edk7708.cdl @@ -43,6 +43,7 @@ cdl_package CYGPKG_HAL_SH_EDK7708 { display "Hitachi EDK/SH7708 board" parent CYGPKG_HAL_SH + requires CYGPKG_HAL_SH_7708 define_header hal_sh_edk7708.h include_dir cyg/hal description "
--- a/packages/net/drivers/eth/common/current/src/eth_drv.c +++ b/packages/net/drivers/eth/common/current/src/eth_drv.c @@ -440,4 +440,5 @@ eth_drv_recv(struct eth_drv_sc *sc, int ether_input(ifp, eh, m); } + // EOF eth_drv.c
--- a/packages/net/snmp/agent/current/ChangeLog +++ b/packages/net/snmp/agent/current/ChangeLog @@ -1,3 +1,8 @@ +2000-07-13 Hugo Tyson <hmt@cygnus.co.uk> + + * tests/snmpping.c: Up the stack size to cope with full DHCP + initialization in init_all_network_interfaces(). + 2000-06-27 Hugo Tyson <hmt@cygnus.co.uk> * src/mibgroup/mibII/dot3.c (var_dot3StatsTable): Forgot the
--- a/packages/net/snmp/agent/current/tests/snmpping.c +++ b/packages/net/snmp/agent/current/tests/snmpping.c @@ -138,7 +138,7 @@ CONNECTION WITH THE USE OR PERFORMANCE O #include <network.h> -#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000) static char stack[STACK_SIZE]; static cyg_thread thread_data; static cyg_handle_t thread_handle; @@ -354,3 +354,5 @@ cyg_start(void) cyg_thread_resume(thread_handle); // Start it cyg_scheduler_start(); } + +// EOF snmpping.c
--- a/packages/net/tcpip/current/ChangeLog +++ b/packages/net/tcpip/current/ChangeLog @@ -1,3 +1,102 @@ +2000-07-14 Hugo Tyson <hmt@cygnus.co.uk> + + * include/bootp.h: export init_loopback_interface(); + +2000-07-14 Hugo Tyson <hmt@cygnus.co.uk> + + * cdl/net.cdl: Add option controlling whether to have a separate + DHCP lease management thread, and what its parameter is to be - + which controls whether it loops or quits if a lease fails. + + * src/lib/dhcp_support.c (dhcp_start_dhcp_mgt_thread): Provide the + DHCP management thread function and code to instantiate and start + the thread if so configured. + + * src/lib/network_support.c (init_all_network_interfaces): Call + the function that starts the DHCP management thread function. + + * include/dhcp.h: Declare the DHCP management thread function &c + if so configured. + + * tests/dhcp_test.c (net_test): Only poll for need to rebind DHCP + leases if there is no service thread to do the same. + +2000-07-14 Hugo Tyson <hmt@cygnus.co.uk> + + * include/bootp.h (build_bootp_record): Export this, no harm in + it, and some folk want to use this rather than configured + initialization or bootp/dhcp. + Also commented the other APIs somewhat better. + + * src/lib/network_support.c (build_bootp_record): Unconditionally + provide this; selective linking will look after it if unused. + +2000-07-14 Hugo Tyson <hmt@cygnus.co.uk> + + * src/lib/network_support.c (build_bootp_record): [Static + configuration of interface parameters] Add the gateway into the + options section with TAG_GATEWAY so that init_net() will pick it + up and set up a route accordingly. + +2000-07-13 Hugo Tyson <hmt@cygnus.co.uk> + + * tests/dhcp_test.c: + * tests/flood.c: + * tests/ftp_test.c: + * tests/nc_test_master.c: + * tests/nc_test_slave.c: + * tests/ping_lo_test.c: + * tests/ping_test.c: + * tests/server_test.c: + * tests/set_mac_address.c: + * tests/tcp_echo.c: + * tests/tftp_client_test.c: + * tests/tftp_server_test.c: + Up the stack size to cope with full DHCP initialization in + init_all_network_interfaces(). + +2000-07-13 Hugo Tyson <hmt@cygnus.co.uk> + + * cdl/net.cdl: Add DHCP enable and interface-specific controls. + + * include/dhcp.h: New file: describe the DHCP APIs and behaviour, + as well as some internal APIs that are also available. + + * src/lib/dhcp_support.c: New file: the surrounding management + routines, a bit like network_support.c, which know about multiple + interfaces and so on. + + * src/lib/dhcp_prot.c: New file: the interface-independent DHCP + protocol machine, which is called from dhcp_support.c routines and + init_all_network_interfaces() in network_support.c + + * include/bootp.h (struct bootp): Make the packet bigger if DHCP + so that a mininal DHCP packet will fit. + + * src/lib/bootp_support.c (do_bootp): If no reply, fail gracefully + and tidy up so that other interfaces can be upbrung. + (show_bootp): Tell us a lot more about DHCP-specific info in the + packet structure. + (get_bootp_option): be aware of DHCP extensions to re-use file and + sname fields for options. + + * src/lib/network_support.c (init_all_network_interfaces): Call + do_dhcp() rather than do_bootp() if so configured, and initialize + the per-interface DHCP state variables accordingly. + + * tests/dhcp_test.c (net_test): New test file that diddles the + DHCP machine while doing a ping test. + +2000-07-11 Gary Thomas <gthomas@redhat.com> + + * include/netdev.h: Add single-inclusion fences. + + * include/sys/param.h: Add traced versions of splx() routines, + selectable by a configuration option. + + * src/ecos/support.c: Rework splx() emulation routines to + be more robust and realtime friendly. + 2000-07-04 Hugo Tyson <hmt@cygnus.co.uk> * include/bootp.h: Fix namespace pollution from "#define int32
--- a/packages/net/tcpip/current/cdl/net.cdl +++ b/packages/net/tcpip/current/cdl/net.cdl @@ -88,6 +88,8 @@ cdl_package CYGPKG_NET { sys/netinet/tcp_timer.c \ lib/inet_addr.c \ lib/bootp_support.c \ + lib/dhcp_support.c \ + lib/dhcp_prot.c \ lib/network_support.c \ lib/getproto.c \ lib/getserv.c \ @@ -178,6 +180,52 @@ cdl_package CYGPKG_NET { } } + cdl_component CYGPKG_NET_DHCP { + display "Use full DHCP instead of BOOTP" + active_if (CYGHWR_NET_DRIVERS > 0) + flavor bool + default_value 1 + description " + Provide DHCP for initializing the IP address + of network interfaces. The DHCP client is capable of falling + back to BOOTP usage if the server does not support DHCP, so it + should never be necessary to disable this option. However, + depending on other configuration the DHCP client may provide or + require a kernel thread of its own; this consumes quite a lot + of resource which a BOOTP solution does not require." + + cdl_option CYGOPT_NET_DHCP_DHCP_THREAD { + display "DHCP management thread" + flavor bool + default_value 1 + description " + Provide a separate thread to renew DHCP leases; otherwise + the application MUST periodically examine the semaphore + dhcp_needs_attention and call dhcp_bind() if it is + signalled. If enabled, this thread does all that for you. + Independent of this option, initialization of the + interfaces still occurs in init_all_network_interfaces() + and your startup code must call that. It will start the + DHCP management thread if necessary. If a lease fails to + be renewed, the management thread will shut down all + interfaces and attempt to initialize all the interfaces + again from scratch. This may cause application problems, + in which case managing the DHCP state in an application + aware thread is recommended. See comments in dhcp.h" + } + + cdl_option CYGOPT_NET_DHCP_DHCP_THREAD_PARAM { + display "DHCP management thread loops forever" + flavor data + default_value 0 + active_if CYGOPT_NET_DHCP_DHCP_THREAD + description " + If the parameter is nonzero, it loops forever; if zero, + the thread exits if a lease expires, and the application + must detect this and tidy up or reboot the whole machine." + } + } + cdl_option CYGPKG_NET_SYSCTL { display "Support BSD 'sysctl()' function" flavor bool @@ -316,6 +364,7 @@ cdl_package CYGPKG_NET { tests/set_mac_address \ tests/flood \ tests/ping_test \ + tests/dhcp_test \ tests/ping_lo_test \ tests/tcp_lo_test \ tests/udp_lo_test \ @@ -381,6 +430,13 @@ cdl_package CYGPKG_NET { default_value 1 implements CYGHWR_NET_DRIVER_ETH0_SETUP + cdl_option CYGHWR_NET_DRIVER_ETH0_DHCP { + display "Use DHCP rather than BOOTP for 'eth0'?" + flavor bool + default_value 1 + active_if CYGPKG_NET_DHCP + } + cdl_option CYGHWR_NET_DRIVER_ETH0_BOOTP_SHOW { display "Show BOOTP/DHCP initialization values?" flavor bool @@ -452,6 +508,13 @@ cdl_package CYGPKG_NET { default_value 1 implements CYGHWR_NET_DRIVER_ETH1_SETUP + cdl_option CYGHWR_NET_DRIVER_ETH1_DHCP { + display "Use DHCP rather than BOOTP for 'eth1'?" + flavor bool + default_value 1 + active_if CYGPKG_NET_DHCP + } + cdl_option CYGHWR_NET_DRIVER_ETH1_BOOTP_SHOW { display "Show BOOTP/DHCP initialization values?" flavor bool
--- a/packages/net/tcpip/current/include/bootp.h +++ b/packages/net/tcpip/current/include/bootp.h @@ -86,6 +86,10 @@ SOFTWARE. */ #ifdef __ECOS + +#include <pkgconf/system.h> +#include <pkgconf/net.h> + #include <machine/types.h> #else #include "bptypes.h" /* for int32, u_int32 */ @@ -94,8 +98,15 @@ SOFTWARE. #define BP_CHADDR_LEN 16 #define BP_SNAME_LEN 64 #define BP_FILE_LEN 128 + +#ifdef CYGPKG_NET_DHCP +// The standard requires only 312 bytes here +#define BP_VEND_LEN (312 + 32) +#define BP_MINPKTSZ 576 +#else #define BP_VEND_LEN 64 #define BP_MINPKTSZ 300 /* to check sizeof(struct bootp) */ +#endif struct bootp { unsigned char bp_op; /* packet opcode type */ @@ -331,11 +342,45 @@ extern struct bootp eth1_bootp_data; extern cyg_bool_t eth1_up; extern const char *eth1_name; #endif -cyg_bool_t do_bootp(const char *interface, struct bootp *res); -cyg_bool_t init_net(const char *interface, struct bootp *res); -void show_bootp(const char *interface, struct bootp *res); -cyg_bool_t get_bootp_option(struct bootp *bp, unsigned char tag, void *res); -void init_all_network_interfaces(void); + +// ------------------------------------------------------------------------ +// Initialize your own bootp record however you like, as far as is needed +// to bring up an interface. +extern void +build_bootp_record(struct bootp *bp, + const char *addrs_ip, + const char *addrs_netmask, + const char *addrs_broadcast, + const char *addrs_gateway, + const char *addrs_server); + +// Do bootp to fill in the bootp record from the net (other interfaces must +// be down for this to work, because of the "half-up" state of the +// interface in use) +extern cyg_bool_t do_bootp(const char *interface, struct bootp *res); + +// Initialize an interface (which is down) according to a bootp structure +extern cyg_bool_t init_net(const char *interface, struct bootp *res); + +// Dump contents to diag_printf +extern void show_bootp(const char *interface, struct bootp *res); + +// Interrogate a bootp record for a particular option +extern cyg_bool_t get_bootp_option(struct bootp *bp, unsigned char tag, void *res); + +// ------------------------------------------------------------------------ +// This isn't exactly the right place for this since bootp is not involved +// BUT you will only be using this API if you are using bootp-style +// initialization of the other interfaces; it fits here in a documentation +// sense. +extern cyg_bool_t init_loopback_interface(int lo); + +// ------------------------------------------------------------------------ +// Do all the above automatically according to the configuration. Do not +// mix using this and making the above calls yourself. +// (this is also declared in the much simpler API in network.h) +extern void init_all_network_interfaces(void); + #endif #endif // _BOOTP_H_
new file mode 100644 --- /dev/null +++ b/packages/net/tcpip/current/include/dhcp.h @@ -0,0 +1,254 @@ +#ifndef CYGONCE_NET_TCPIP_DHCP_H +#define CYGONCE_NET_TCPIP_DHCP_H + +//========================================================================== +// +// include/dhcp.h +// +// DHCP protocol support +// +//========================================================================== +//####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): hmt +// Contributors: gthomas +// Date: 2000-07-01 +// Purpose: Support DHCP initialization in eCos TCPIP stack +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +// +// DHCP. RFC2131, RFC1533, RFC1534 +// See also bootp.h +// + +#include <pkgconf/system.h> +#include <pkgconf/net.h> + +#ifdef CYGPKG_NET_DHCP + +#include <machine/types.h> + +#include <cyg/kernel/kapi.h> + +#include <bootp.h> + +// DHCP messages; these are sent in the tag TAG_DHCP_MESS_TYPE already +// defined in bootp.h + +#define DHCPDISCOVER 1 +#define DHCPOFFER 2 +#define DHCPREQUEST 3 +#define DHCPDECLINE 4 +#define DHCPACK 5 +#define DHCPNAK 6 +#define DHCPRELEASE 7 + +// DHCP interface state machine states; these are published so that app +// code can know what to do... (see page 35 of RFC2131) + +// These we will use in the normal course of events +#define DHCPSTATE_INIT 1 +#define DHCPSTATE_SELECTING 2 // wait for replies to b/c DISCOVER +#define DHCPSTATE_REQUESTING 3 +#define DHCPSTATE_REQUEST_RECV 4 // wait for replies to b/c REQUEST +#define DHCPSTATE_BOUND 5 +#define DHCPSTATE_RENEWING 6 // wait for replies to u/c REQUEST +#define DHCPSTATE_RENEW_RECV 7 +#define DHCPSTATE_REBINDING 8 // wait for replies to b/c REQUEST +#define DHCPSTATE_REBIND_RECV 9 +#define DHCPSTATE_BOOTP_FALLBACK 10 // fall back to plain bootp +#define DHCPSTATE_NOTBOUND 11 // To let app tidy up +#define DHCPSTATE_FAILED 12 // Net is down +#define DHCPSTATE_DO_RELEASE 13 // Force release of the current lease +// These we don't use +//#define DHCPSTATE_INITREBOOT +//#define DHCPSTATE_REBOOTING + +// These are to let the app inspect the state of the interfaces when +// managing them itself, by analogy with eth0_up &c; eth0_bootp_data and so +// on will still be used with DHCP. +#ifdef CYGHWR_NET_DRIVER_ETH0 +extern cyg_uint8 eth0_dhcpstate; +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 +extern cyg_uint8 eth1_dhcpstate; +#endif + +// This is public so the app wait on it or poll it when managing DHCP +// itself. It will be zero while the app should wait, and posted when a +// call to do_dhcp() is needed. +extern cyg_sem_t dhcp_needs_attention; + +// This routine is used at startup time, and after relinquishing leases or +// after a lease timeout: it does DHCP or bootp or static setup according +// to configuration. +extern void init_all_network_interfaces(void); + +// This routine does the work of renewing leases &c. +// return value: 1 => everything OK, no change. +// 0 => close your connections, then call do_dhcp_halt() to halt the +// interface(s) in question (it knows because the state will be NOTBOUND). +// After that you can return to the start and use +// init_all_network_interfaces() as usual. +extern int dhcp_bind( void ); + +// Shutdown any interface which is not already shut down - whether +// initialized by DHCP or not. Reason: because of the broadcast-while-not- +// -fully-initialized nature of the DHCP conversation, all other interfaces +// must be shut down during that. So one down, all down, is required. +extern int dhcp_halt( void ); + +// Release (and set state to DHCPSTATE_NOTBOUND) all interfaces - we are +// closing down. (unlikely but useful for testing) +// Interfaces are left up; use dhcp_halt() to bring them right down, then +// call init_all_network_interfaces() as usual to restart all. +extern int dhcp_release( void ); + +// The intent with this API is that a simple DHCP client thread, which +// maintains the state of the interfaces, can go as follows: +// (after init_all_networks is called from elsewhere) +// +// while ( 1 ) { +// while ( 1 ) { +// cyg_semaphore_wait( &dhcp_needs_attention ); +// if ( ! dhcp_bind() ) // a lease expired +// break; // If we need to re-bind +// } +// dhcp_halt(); // tear everything down +// init_all_network_interfaces(); // re-initialize +// } +// +// and if the application does not want to suffer the overhead of a +// separate thread and its stack for this, this functionality can be placed +// in the app's server loop in an obvious fashion. That is the goal of +// breaking out these internal elements. For example, some server might +// be arranged to poll DHCP from time to time like this: +// +// while ( 1 ) { +// init_all_network_interfaces(); +// open-my-listen-sockets(); +// while ( 1 ) { +// serve-one-request(); +// // sleeps if no connections, but not forever; so this loop is +// // polled a few times a minute... +// if ( cyg_semaphore_trywait( &dhcp_needs_attention )) { +// if ( ! dhcp_bind() ) { +// close-my-listen-sockets(); +// dhcp_halt(); +// break; +// } +// } +// } +// } +// +// ------------------------------------------------------------------------ + +#ifdef CYGOPT_NET_DHCP_DHCP_THREAD +// Then we provide such a thread... + +// Provide a separate thread to renew DHCP leases; otherwise the +// application MUST periodically examine the semaphore dhcp_needs_attention +// and call dhcp_bind() if it is signalled. If enabled, this thread does +// all that for you. Independent of this option, initialization of the +// interfaces still occurs in init_all_network_interfaces() and your +// startup code must call that. It will start the DHCP management thread +// if necessary. If a lease fails to be renewed, the management thread +// will shut down all interfaces and attempt to initialize all the +// interfaces again from scratch. This may cause chaos in the app, which +// is why managing the DHCP state in an application aware thread is +// actually better, just far less convenient for testing. + +extern cyg_handle_t dhcp_mgt_thread_h; // To allow its external manipulation. +extern cyg_thread dhcp_mgt_thread; // The object itself + +extern void dhcp_start_dhcp_mgt_thread( void ); + +#endif + +// The function is provided unconditionally so that the app can put it in a +// thread of its own. If the parameter is true, it loops forever; if +// false, the call returns if a lease expires, and the caller must tidy up +// or reboot the whole machine. +extern cyg_thread_entry_t dhcp_mgt_entry; +extern void dhcp_mgt_entry( cyg_addrword_t loop_on_failure ); // the function + +// --------------------------------------------------------------------------- +// These are rather more internal routines, internal to the protocol engine +// in dhcp_prot.c - those above are in dhcp_support.c + +#define DHCP_LEASE_T1 1 +#define DHCP_LEASE_T2 2 +#define DHCP_LEASE_EX 4 + +struct dhcp_lease { + cyg_tick_count_t t1, t2, expiry; + volatile cyg_uint8 next; + volatile cyg_uint8 which; + cyg_handle_t alarm; + cyg_alarm alarm_obj; +}; + +#ifdef CYGHWR_NET_DRIVER_ETH0 +extern struct dhcp_lease eth0_lease; +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 +extern struct dhcp_lease eth1_lease; +#endif + +extern int +do_dhcp(const char *interface, struct bootp *res, + cyg_uint8 *pstate, struct dhcp_lease *lease); +// NB *res and *pstate and *lease are all INOUT; *res must point to a valid +// record from "last time". + +extern int +do_dhcp_down_net(const char *intf, struct bootp *res, + cyg_uint8 *pstate, struct dhcp_lease *lease); + +extern int +do_dhcp_release(const char *intf, struct bootp *res, + cyg_uint8 *pstate, struct dhcp_lease *lease); + +#endif // CYGPKG_NET_DHCP + +#endif // CYGONCE_NET_TCPIP_DHCP_H +// EOF dhcp.h
--- a/packages/net/tcpip/current/include/netdev.h +++ b/packages/net/tcpip/current/include/netdev.h @@ -1,3 +1,5 @@ +#ifndef _NETDEV_H_ +#define _NETDEV_H_ //========================================================================== // // include/netdev.h @@ -72,3 +74,5 @@ cyg_netdevtab_entry_t _l __attribute__ ( _init, \ _instance \ }; + +#endif // _NETDEV_H_
--- a/packages/net/tcpip/current/include/sys/param.h +++ b/packages/net/tcpip/current/include/sys/param.h @@ -330,6 +330,21 @@ extern void cyg_wakeup(void *); #define tsleep(e,p,w,t) cyg_tsleep(e,0,w,t) #define wakeup(e) cyg_wakeup(e) +#ifdef CYGIMPL_TRACE_SPLX +extern cyg_uint32 cyg_splimp(const char *file, const int line); +extern cyg_uint32 cyg_splnet(const char *file, const int line); +extern cyg_uint32 cyg_splclock(const char *file, const int line); +extern cyg_uint32 cyg_splsoftnet(const char *file, const int line); +extern void cyg_splx(cyg_uint32, const char *file, const int line); +#define splimp() cyg_splimp(__FUNCTION__, __LINE__) +#define splnet() cyg_splnet(__FUNCTION__, __LINE__) +#define splclock() cyg_splclock(__FUNCTION__, __LINE__) +#define splsoftnet() cyg_splsoftnet(__FUNCTION__, __LINE__) +#define splx(x) cyg_splx(x, __FUNCTION__, __LINE__) +#define cyg_scheduler_lock() _cyg_scheduler_lock(__FUNCTION__, __LINE__) +#define cyg_scheduler_safe_lock() _cyg_scheduler_safe_lock(__FUNCTION__, __LINE__) +#define cyg_scheduler_unlock() _cyg_scheduler_unlock(__FUNCTION__, __LINE__) +#else extern cyg_uint32 cyg_splimp(void); extern cyg_uint32 cyg_splnet(void); extern cyg_uint32 cyg_splclock(void); @@ -340,6 +355,7 @@ extern void cyg_splx(cyg_uint32); #define splclock cyg_splclock #define splsoftnet cyg_splsoftnet #define splx cyg_splx +#endif extern void cyg_panic(const char *msg, ...); #define panic cyg_panic
--- a/packages/net/tcpip/current/src/ecos/support.c +++ b/packages/net/tcpip/current/src/ecos/support.c @@ -102,143 +102,177 @@ cyg_panic(const char *msg, ...) cyg_test_exit(); // FIXME } - -// ------------------------------------------------------------------------ -#define SPLSOFTNET_IS_A_MUTEX 1 -// ------------------------------------------------------------------------ -#ifdef SPLSOFTNET_IS_A_MUTEX +//---------------------------- splx() emulation ------------------------------ +// +// This variable (and the associated bit patterns) is used to keep track +// of the "splx()" level. This is an artifact of the original stack, based +// on the BSD interrupt world (interrupts and processing could be masked +// based on a level value, supported by hardware). This is not very real-time, +// so the emulation uses proper eCos tools and techniques to accomplish the +// same result. The key here is in the analysis of the various "levels", why +// they are used, etc. +// +static cyg_uint32 spl_state; +#define SPL_STATE_IMP 0x01 +#define SPL_STATE_NET 0x02 +#define SPL_STATE_CLOCK 0x04 +#define SPL_STATE_SOFTNET 0x08 -#define MUTEX 0x50F750F7 -#define HOLD MUTEX+1 - -static cyg_mutex_t mutex; -static volatile cyg_handle_t owner; +static cyg_mutex_t softnet_mutex; +static volatile cyg_handle_t softnet_thread; #define SPLINIT() CYG_MACRO_START \ - cyg_mutex_init( &mutex ); \ - owner = 0; \ + cyg_mutex_init( &softnet_mutex ); \ + softnet_thread = 0; \ CYG_MACRO_END -// use the scheduler lock for SPLX() and a mutex for softnet - -static inline cyg_uint32 -cyg_splin_softnet(void) +// +// This function is called in order to protect internal data structures +// short-term, primarily so that interrupt processing does not interfere +// with them. +// +// Simply protecting against interrupts (DSRs) should suffice. +// +cyg_uint32 +#ifdef CYGIMPL_TRACE_SPLX +cyg_splimp(const char *file, const int line) +#else +cyg_splimp(void) +#endif { - if ( 0 == cyg_scheduler_read_lock() ) { - cyg_handle_t self = cyg_thread_self(); - if ( self != owner ) { - cyg_mutex_lock( &mutex ); // Perfectly OK for this to wait - owner = self; - return MUTEX; // release when restoring here - } - return HOLD; // do not release when restoring to this value + cyg_uint32 old_ints; + cyg_scheduler_lock(); +#ifdef CYGIMPL_TRACE_SPLX + do_sched_event(__FUNCTION__, file, line, cyg_scheduler_read_lock()); +#endif + old_ints = spl_state; + spl_state |= SPL_STATE_IMP; + if (old_ints & SPL_STATE_IMP) { + // Already at this state/level, no need to retake scheduler lock + cyg_scheduler_unlock(); } - cyg_scheduler_lock(); - return cyg_scheduler_read_lock() - 1; -} - -static inline cyg_uint32 -cyg_splin(void) -{ - cyg_scheduler_lock(); - return cyg_scheduler_read_lock() - 1; + return old_ints; } -static inline void -cyg_splout(cyg_uint32 orig) -{ - if ( MUTEX == orig ) { - CYG_ASSERT( cyg_thread_self() == owner, "Not owner release!" ); - cyg_scheduler_lock(); - owner = 0; - cyg_mutex_unlock( &mutex ); - cyg_scheduler_unlock(); - return; - } - if ( HOLD == orig ) { - CYG_ASSERT( cyg_thread_self() == owner, "Not owner hold!" ); - return; - } - CYG_ASSERT( 0 == (0xffff0000 & orig), "Scary splx value" ); - while ( cyg_scheduler_read_lock() > orig ) - cyg_scheduler_unlock(); -} - -#define SPL_ENTER(x) (x) = cyg_splin() -#define SPL_SOFTNET(x) (x) = cyg_splin_softnet() -#define SPL_EXIT(x) cyg_splout((x)) - +// +// This function is called in order to ensure that a timestamp is valid +// i.e. no time passes while the stamp is being taken (since it is a +// potentially non-idempotent data structure). +// +// Simply protecting against interrupts (DSRs) should suffice. +// +cyg_uint32 +#ifdef CYGIMPL_TRACE_SPLX +cyg_splclock(const char *file, const int line) #else -#if 1 - -// use the scheduler lock for SPLX() -static inline cyg_uint32 -cyg_splin(void) -{ - cyg_scheduler_lock(); - return cyg_scheduler_read_lock() - 1; -} - -static inline void -cyg_splout(cyg_uint32 orig) -{ - CYG_ASSERT( 0 == (0xffff0000 & orig), "Scary splx value" ); - while ( cyg_scheduler_read_lock() > orig ) - cyg_scheduler_unlock(); -} - -#define SPL_ENTER(x) (x) = cyg_splin() -#define SPL_SOFTNET(x) (x) = cyg_splin() -#define SPL_EXIT(x) cyg_splout((x)) - -#else - -// Old interrupt based version -#define SPL_ENTER(x) HAL_DISABLE_INTERRUPTS((x)) -#define SPL_SOFTNET(x) HAL_DISABLE_INTERRUPTS((x)) -#define SPL_EXIT(x) HAL_RESTORE_INTERRUPTS((x)) - +cyg_splclock(void) #endif -#endif -// ------------------------------------------------------------------------ - -cyg_uint32 -cyg_splimp(void) { cyg_uint32 old_ints; - SPL_ENTER(old_ints); + cyg_scheduler_lock(); +#ifdef CYGIMPL_TRACE_SPLX + do_sched_event(__FUNCTION__, file, line, cyg_scheduler_read_lock()); +#endif + old_ints = spl_state; + spl_state |= SPL_STATE_CLOCK; + if (old_ints & SPL_STATE_CLOCK) { + // Already at this state/level, no need to retake scheduler lock + cyg_scheduler_unlock(); + } return old_ints; } cyg_uint32 +#ifdef CYGIMPL_TRACE_SPLX +cyg_splnet(const char *file, const int line) +#else cyg_splnet(void) +#endif { cyg_uint32 old_ints; - SPL_ENTER(old_ints); + cyg_scheduler_lock(); +#ifdef CYGIMPL_TRACE_SPLX + do_sched_event(__FUNCTION__, file, line, cyg_scheduler_read_lock()); +#endif + old_ints = spl_state; + spl_state |= SPL_STATE_NET; + if (old_ints & SPL_STATE_NET) { + // Already at this state/level, no need to retake scheduler lock + cyg_scheduler_unlock(); + } return old_ints; } +// +// Prevent all other stack processing, including interrupts (DSRs), etc. +// cyg_uint32 -cyg_splclock(void) +#ifdef CYGIMPL_TRACE_SPLX +cyg_splsoftnet(const char *file, const int line) +#else +cyg_splsoftnet(void) +#endif { cyg_uint32 old_ints; - SPL_ENTER(old_ints); + cyg_scheduler_lock(); +#ifdef CYGIMPL_TRACE_SPLX + do_sched_event(__FUNCTION__, file, line, cyg_scheduler_read_lock()); +#endif + if (spl_state & SPL_STATE_SOFTNET) { + if (softnet_thread == cyg_thread_self()) { + // Do nothing + old_ints = spl_state; + spl_state |= SPL_STATE_SOFTNET; + cyg_scheduler_unlock(); + return old_ints; + } + } + cyg_scheduler_unlock(); + cyg_mutex_lock(&softnet_mutex); + cyg_scheduler_lock(); + softnet_thread = cyg_thread_self(); + old_ints = spl_state; + spl_state |= SPL_STATE_SOFTNET; return old_ints; } -cyg_uint32 -cyg_splsoftnet(void) +// +// Return to a previous interrupt state/level. +// +void +#ifdef CYGIMPL_TRACE_SPLX +cyg_splx(cyg_uint32 old_state, const char *file, const int line) +#else +cyg_splx(cyg_uint32 old_state) +#endif { - cyg_uint32 old_ints; - SPL_SOFTNET(old_ints); - return old_ints; + cyg_uint32 new_state = spl_state; + cyg_scheduler_lock(); // Extra security while messing about +#ifdef CYGIMPL_TRACE_SPLX + do_sched_event(__FUNCTION__, file, line, cyg_scheduler_read_lock()); +#endif + if ((spl_state & SPL_STATE_SOFTNET) && !(old_state & SPL_STATE_SOFTNET)) { + new_state &= ~SPL_STATE_SOFTNET; + softnet_thread = 0; + cyg_mutex_unlock(&softnet_mutex); + cyg_scheduler_unlock(); + } + if ((spl_state & SPL_STATE_NET) && !(old_state & SPL_STATE_NET)) { + new_state &= ~SPL_STATE_NET; + cyg_scheduler_unlock(); + } + if ((spl_state & SPL_STATE_CLOCK) && !(old_state & SPL_STATE_CLOCK)) { + new_state &= ~SPL_STATE_CLOCK; + cyg_scheduler_unlock(); + } + if ((spl_state & SPL_STATE_IMP) && !(old_state & SPL_STATE_IMP)) { + new_state &= ~SPL_STATE_IMP; + cyg_scheduler_unlock(); + } + spl_state = new_state; + cyg_scheduler_unlock(); } - -void -cyg_splx(cyg_uint32 old_lev) -{ - SPL_EXIT(old_lev); -} +//---------------------------- splx() emulation ------------------------------ void setsoftnet(void) @@ -405,7 +439,6 @@ cyg_kmem_init(void) mclrefcnt = net_clusters_refcnt; } - void cyg_kmem_print_stats( void ) { cyg_mempool_info info; @@ -557,6 +590,7 @@ ovbcopy(const void *s, void *d, size_t l memcpy(d, s, len); } +//------------------ tsleep() and wakeup() emulation --------------------------- // // Structure used to keep track of 'tsleep' style events // @@ -600,15 +634,13 @@ cyg_tsleep(void *chan, int pri, char *wm int i, res = 0; struct wakeup_event *ev; cyg_tick_count_t sleep_time; -#ifdef SPLSOFTNET_IS_A_MUTEX - int olock; // this does the same as safe_lock() but keeping the old state + int olock; // current state of scheduler lock - so it can be replaced + cyg_handle_t self = cyg_thread_self(); + cyg_scheduler_lock(); // ...around. olock = cyg_scheduler_read_lock(); if ( olock > 1 ) cyg_scheduler_unlock(); -#else - cyg_scheduler_safe_lock(); // Ensure safe scan -#endif for (i = 0, ev = wakeup_list; i < CYGPKG_NET_NUM_WAKEUP_EVENTS; i++, ev++) { if (ev->chan == 0) { @@ -619,40 +651,40 @@ cyg_tsleep(void *chan, int pri, char *wm if (i == CYGPKG_NET_NUM_WAKEUP_EVENTS) { panic("no sleep slots"); } - CYG_ASSERT( 1 == cyg_scheduler_read_lock(), "Sleep won't!" ); + if ( 1 != cyg_scheduler_read_lock()) { + panic("Tsleep - called with scheduler locked\n"); + } + + // Then we must release the 'softnet' mutex when we wait - if we have it + if ( self == softnet_thread ) { + softnet_thread = 0; + spl_state &= ~SPL_STATE_SOFTNET; + cyg_mutex_unlock( &softnet_mutex ); + } else { + self = 0; // Flag no need to reclaim + } -#ifdef SPLSOFTNET_IS_A_MUTEX - { // Then we must release the mutex when we wait - if we have it - cyg_handle_t self = cyg_thread_self(); - if ( self == owner ) { - owner = 0; - cyg_mutex_unlock( &mutex ); - } else { - self = 0; // Flag no need to reclaim + // This part actually does the wait: + cyg_scheduler_unlock(); + if (timo) { + sleep_time = cyg_current_time() + timo; + if (!cyg_semaphore_timed_wait(&ev->sem, sleep_time)) { + res = ETIMEDOUT; + ev->chan = 0; // Free slot } -#endif + } else { + cyg_semaphore_wait(&ev->sem); + } - // This part actually does the wait: + if ( self ) { // return to previous state + cyg_mutex_lock( &softnet_mutex ); // this might wait + cyg_scheduler_lock(); + softnet_thread = self; // got it now... + spl_state |= SPL_STATE_SOFTNET; cyg_scheduler_unlock(); - if (timo) { - sleep_time = cyg_current_time() + timo; - if (!cyg_semaphore_timed_wait(&ev->sem, sleep_time)) { - res = ETIMEDOUT; - ev->chan = 0; // Free slot - } - } else { - cyg_semaphore_wait(&ev->sem); - } - -#ifdef SPLSOFTNET_IS_A_MUTEX - if ( self ) { // return to previous state - cyg_mutex_lock( &mutex ); // this might wait - owner = self; // got it now... - } - if ( olock > 1 ) - cyg_scheduler_lock(); } -#endif + if ( olock > 1 ) + cyg_scheduler_lock(); return res; } @@ -669,6 +701,7 @@ cyg_timeout_init(void) cyg_semaphore_init(&ev->sem, 0); } } +//------------------ tsleep() and wakeup() emulation --------------------------- // // Network software interrupt handler @@ -680,10 +713,11 @@ static void cyg_netint(cyg_addrword_t param) { cyg_flag_value_t curisr; + int s; while (true) { curisr = cyg_flag_wait(&netint_flags, NETISR_ANY, CYG_FLAG_WAITMODE_OR|CYG_FLAG_WAITMODE_CLR); - cyg_scheduler_lock(); // This code should not be preempted + s = splsoftnet(); // Prevent any overlapping "stack" processing #ifdef INET if (curisr & (1 << NETISR_ARP)) { // Pending ARP requests @@ -700,7 +734,7 @@ cyg_netint(cyg_addrword_t param) ip6intr(); } #endif - cyg_scheduler_unlock(); + splx(s); } } @@ -719,6 +753,9 @@ cyg_net_init(void) static int _init = false; cyg_netdevtab_entry_t *t; +#ifdef CYGIMPL_TRACE_SPLX + show_sched_events(); +#endif if (_init) return; cyg_do_net_init(); // Just forces the linking in of the initializer/constructor // Initialize interrupt "flags" @@ -765,3 +802,71 @@ cyg_net_init(void) // Done _init = true; } + +#ifdef CYGIMPL_TRACE_SPLX +#undef cyg_scheduler_lock +#undef cyg_scheduler_safe_lock +#undef cyg_scheduler_unlock + +#define MAX_SCHED_EVENTS 256 +static struct _sched_event { + char *fun, *file; + int line, lock; +} sched_event[MAX_SCHED_EVENTS]; +static int next_sched_event = 0; +static int total_sched_events = 0; + +static void +do_sched_event(char *fun, char *file, int line, int lock) +{ + struct _sched_event *se = &sched_event[next_sched_event]; + if (++next_sched_event == MAX_SCHED_EVENTS) { + next_sched_event = 0; + } + se->fun = fun; + se->file = file; + se->line = line; + se->lock = lock; + total_sched_events++; +} + +static void +show_sched_events(void) +{ + int i; + struct _sched_event *se; + if (total_sched_events < MAX_SCHED_EVENTS) { + i = 0; + } else { + i = next_sched_event + 1; + if (i == MAX_SCHED_EVENTS) i = 0; + } + diag_printf("%d total scheduler events\n", total_sched_events); + while (i != next_sched_event) { + se = &sched_event[i]; + diag_printf("%s - lock: %d, called from %s.%d\n", se->fun, se->lock, se->file, se->line); + if (++i == MAX_SCHED_EVENTS) i = 0; + } +} + +void +_cyg_scheduler_lock(char *file, int line) +{ + cyg_scheduler_lock(); + do_sched_event(__FUNCTION__, file, line, cyg_scheduler_read_lock()); +} + +void +_cyg_scheduler_safe_lock(char *file, int line) +{ + cyg_scheduler_safe_lock(); + do_sched_event(__FUNCTION__, file, line, cyg_scheduler_read_lock()); +} + +void +_cyg_scheduler_unlock(char *file, int line) +{ + cyg_scheduler_unlock(); + do_sched_event(__FUNCTION__, file, line, cyg_scheduler_read_lock()); +} +#endif // CYGIMPL_TRACE_SPLX
--- a/packages/net/tcpip/current/src/lib/bootp_support.c +++ b/packages/net/tcpip/current/src/lib/bootp_support.c @@ -52,7 +52,10 @@ // //========================================================================== -// BOOTP support +// BOOTP support (and a little DHCP support also) + +#include <pkgconf/system.h> +#include <pkgconf/net.h> #include <network.h> @@ -71,6 +74,7 @@ do_bootp(const char *intf, struct bootp struct bootp bootp_xmit; unsigned char mincookie[] = {99,130,83,99,255} ; struct timeval tv; + cyg_bool_t retcode = true; // Ensure clean slate route_reinit(); // Force any existing routes to be forgotten @@ -196,11 +200,13 @@ do_bootp(const char *intf, struct bootp addrlen = sizeof(bootp_server_addr); if (recvfrom(s, recv, sizeof(struct bootp), 0, (struct sockaddr *)&bootp_server_addr, &addrlen) < 0) { - perror("recvfrom error"); - return false; + // This is an "acceptable" error, it means there is no server for + // us: do not initialize the interface. + retcode = false; } - + // Shut things down regardless of success of rx, otherwise other + // interfaces cannot be initialised! memset(addrp, 0, sizeof(*addrp)); addrp->sin_family = AF_INET; addrp->sin_len = sizeof(*addrp); @@ -221,22 +227,30 @@ do_bootp(const char *intf, struct bootp // All done with socket close(s); - return true; + return retcode; } static char *_bootp_op[] = {"", "REQUEST", "REPLY"}; static char *_bootp_hw_type[] = {"", "Ethernet", "Exp Ethernet", "AX25", "Pronet", "Chaos", "IEEE802", "Arcnet"}; +static char *_dhcpmsgs[] = {"","DISCOVER", "OFFER", "REQUEST", "DECLINE", + "ACK", "NAK", "RELEASE" }; + void show_bootp(const char *intf, struct bootp *bp) { int i, len; - unsigned char *op, *ap = 0; + unsigned char *op, *ap = 0, optover; unsigned char name[128]; struct in_addr addr[32]; diag_printf("BOOTP[%s] op: %s\n", intf, _bootp_op[bp->bp_op]); - diag_printf(" hw_type: %s\n", _bootp_hw_type[bp->bp_htype]); + diag_printf(" htype: %s\n", _bootp_hw_type[bp->bp_htype]); + diag_printf(" hlen: %d\n", bp->bp_hlen ); + diag_printf(" hops: %d\n", bp->bp_hops ); + diag_printf(" xid: 0x%x\n", bp->bp_xid ); + diag_printf(" secs: %d\n", bp->bp_secs ); + diag_printf(" flags: 0x%x\n", bp->bp_flags ); diag_printf(" hw_addr: "); for (i = 0; i < bp->bp_hlen; i++) { diag_printf("%02x", bp->bp_chaddr[i]); @@ -247,12 +261,13 @@ show_bootp(const char *intf, struct boot diag_printf(" my IP: %s\n", inet_ntoa(bp->bp_yiaddr)); diag_printf(" server IP: %s\n", inet_ntoa(bp->bp_siaddr)); diag_printf(" gateway IP: %s\n", inet_ntoa(bp->bp_giaddr)); - if (bp->bp_sname[0]) { + + optover = 0; // See whether sname and file are overridden for options + (void)get_bootp_option( bp, TAG_DHCP_OPTOVER, &optover ); + if ( !(1 & optover) && bp->bp_sname[0] ) diag_printf(" server: %s\n", bp->bp_sname); - } - if (bp->bp_file[0]) { + if ( ! (2 & optover) && bp->bp_file[0] ) diag_printf(" file: %s\n", bp->bp_file); - } if (bp->bp_vend[0]) { diag_printf(" options:\n"); op = &bp->bp_vend[4]; @@ -291,8 +306,51 @@ show_bootp(const char *intf, struct boot if (*op == TAG_HOST_NAME) ap = " host name"; diag_printf(" %s: %s\n", ap, name); break; + case TAG_DHCP_MESS_TYPE: + diag_printf(" DHCP message: %d %s\n", + op[2], _dhcpmsgs[op[2]] ); + break; + case TAG_DHCP_REQ_IP: + diag_printf(" DHCP requested ip: %d.%d.%d.%d\n", + op[2], op[3], op[4], op[5] ); + break; + case TAG_DHCP_LEASE_TIME : + case TAG_DHCP_RENEWAL_TIME : + case TAG_DHCP_REBIND_TIME : + diag_printf(" DHCP time %d: %d\n", + *op, ((((((op[2]<<8)+op[3])<<8)+op[4])<<8)+op[5]) ); + + break; + case TAG_DHCP_SERVER_ID : + diag_printf(" DHCP server id: %d.%d.%d.%d\n", + op[2], op[3], op[4], op[5] ); + break; + + case TAG_DHCP_OPTOVER : + case TAG_DHCP_PARM_REQ_LIST: + case TAG_DHCP_TEXT_MESSAGE : + case TAG_DHCP_MAX_MSGSZ : + case TAG_DHCP_CLASSID : + case TAG_DHCP_CLIENTID : + diag_printf(" DHCP option: %x/%d.%d:", *op, *op, *(op+1)); + if ( 1 == op[1] ) + diag_printf( " %d", op[2] ); + else if ( 2 == op[1] ) + diag_printf( " %d", (op[2]<<8)+op[3] ); + else if ( 4 == op[1] ) + diag_printf( " %d", ((((((op[2]<<8)+op[3])<<8)+op[4])<<8)+op[5]) ); + else + for ( i = 2; i < 2 + op[1]; i++ ) + diag_printf(" %d",op[i]); + diag_printf("\n"); + break; + default: - diag_printf("Unknown option: %x.%d\n", *op, *(op+1)); + diag_printf("Unknown option: %x/%d.%d:", *op, *op, *(op+1)); + for ( i = 2; i < 2 + op[1]; i++ ) + diag_printf(" %d",op[i]); + diag_printf("\n"); + break; } op += *(op+1)+2; } @@ -302,19 +360,38 @@ show_bootp(const char *intf, struct boot cyg_bool_t get_bootp_option(struct bootp *bp, unsigned char tag, void *opt) { - unsigned char *op; unsigned char *val = (unsigned char *)opt; int i; - op = &bp->bp_vend[4]; - while (*op != TAG_END) { - if (*op == tag) { - for (i = 0; i < *(op+1); i++) { - *val++ = *(op+i+2); - } - return true; - } - op += *(op+1)+2; - } + cyg_uint8 optover; + +#define SCANTAG( ptr ) CYG_MACRO_START \ + unsigned char *op = (ptr); \ + while (*op != TAG_END) { \ + if (*op == tag) { \ + for (i = 0; i < *(op+1); i++) { \ + *val++ = *(op+i+2); \ + } \ + return true; \ + } \ + op += *(op+1)+2; \ + } \ +CYG_MACRO_END + + SCANTAG( &bp->bp_vend[4] ); + + if ( TAG_DHCP_OPTOVER == tag ) // prevent recursion > once + return false; + // else, look for that tag to see if there's more... + optover = 0; + if ( ! get_bootp_option( bp, TAG_DHCP_OPTOVER, &optover ) ) + return false; + + if ( 1 & optover ) // then the file field also holds options + SCANTAG( &bp->bp_file[0] ); + + if ( 2 & optover ) // then the sname field also holds options + SCANTAG( &bp->bp_sname[0] ); + return false; }
new file mode 100644 --- /dev/null +++ b/packages/net/tcpip/current/src/lib/dhcp_prot.c @@ -0,0 +1,1024 @@ +/*========================================================================== +// +// dhcp_prot.c +// +// DHCP protocol implementation for DHCP client +// +//========================================================================== +//####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): hmt +// Contributors: gthomas +// Date: 2000-07-01 +// Purpose: DHCP support +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include <pkgconf/system.h> +#include <pkgconf/net.h> + +#ifdef CYGPKG_NET_DHCP + +#if 0 +#define perror( txt ) // nothing +#endif + +#include <network.h> +#include <dhcp.h> + +#include <cyg/infra/cyg_ass.h> + +// ------------------------------------------------------------------------ +// Get the actual packet size of an initialized buffer + +static int +dhcp_size( struct bootp *ppkt ) +{ + unsigned char *op; + + op = &ppkt->bp_vend[0]; + // First check for the cookie! + if ( op[0] != 99 || + op[1] != 130 || + op[2] != 83 || + op[3] != 99 ) { + CYG_FAIL( "Bad DHCP cookie" ); + return 0; + } + op += 4; + while (*op != TAG_END) { + op += *(op+1)+2; + if ( op > &ppkt->bp_vend[BP_VEND_LEN-1] ) { + CYG_FAIL( "Oversize DHCP packet in dhcp_size" ); + return 0; + } + } + return (op - (unsigned char *)ppkt) + 1; +} + +// ------------------------------------------------------------------------ +// Insert/set an option value in an initialized buffer + +static int +set_fixed_tag( struct bootp *ppkt, + unsigned char tag, + cyg_uint32 value, + int len) +{ + unsigned char *op; + + // Initially this will only scan the options field. + + op = &ppkt->bp_vend[4]; + while (*op != TAG_END) { + if ( op > &ppkt->bp_vend[BP_VEND_LEN-1] ) { + CYG_FAIL( "Oversize DHCP packet in set_fixed_tag" ); + return false; + } + if (*op == tag) // Found it... + break; + op += *(op+1)+2; + } + + if (*op == tag) { // Found it... + if ( *(op+1) != len ) { + CYG_FAIL( "Wrong size in set_fixed_tag" ); + return false; // wrong size + } + } + else { // overwrite the end tag and install a new one + if ( op + len + 2 > &ppkt->bp_vend[BP_VEND_LEN-1] ) { + CYG_FAIL( "Oversize DHCP packet in set_fixed_tag append" ); + return false; + } + *op = tag; + *(op+1) = len; + *(op + len + 2) = TAG_END; + } + // and insert the value. Net order is BE. + op += len + 2 - 1; // point to end of value + while ( len-- > 0 ) { + *op-- = (unsigned char)(value & 255); + value >>= 8; + } + return true; +} + +// ------------------------------------------------------------------------ +// Bring up an interface enough to broadcast, before we know who we are + +static int +bring_half_up(const char *intf, struct ifreq *ifrp ) +{ + int s; + int one = 1; + + struct sockaddr_in *addrp; + struct ecos_rtentry route; + + // Ensure clean slate + route_reinit(); // Force any existing routes to be forgotten + + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) { + perror("socket"); + return false; + } + + if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one))) { + perror("setsockopt"); + return false; + } + + addrp = (struct sockaddr_in *) &ifrp->ifr_addr; + memset(addrp, 0, sizeof(*addrp)); + addrp->sin_family = AF_INET; + addrp->sin_len = sizeof(*addrp); + addrp->sin_port = 0; + addrp->sin_addr.s_addr = INADDR_ANY; + + strcpy(ifrp->ifr_name, intf); + if (ioctl(s, SIOCSIFADDR, ifrp)) { /* set ifnet address */ + perror("SIOCSIFADDR"); + return false; + } + + if (ioctl(s, SIOCSIFNETMASK, ifrp)) { /* set net addr mask */ + perror("SIOCSIFNETMASK"); + return false; + } + + /* the broadcast address is 255.255.255.255 */ + memset(&addrp->sin_addr, 255, sizeof(addrp->sin_addr)); + if (ioctl(s, SIOCSIFBRDADDR, ifrp)) { /* set broadcast addr */ + perror("SIOCSIFBRDADDR"); + return false; + } + + ifrp->ifr_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING; + if (ioctl(s, SIOCSIFFLAGS, ifrp)) { /* set ifnet flags */ + perror("SIOCSIFFLAGS up"); + return false; + } + + if (ioctl(s, SIOCGIFHWADDR, ifrp) < 0) { /* get MAC address */ + perror("SIOCGIFHWADDR 1"); + return false; + } + + // Set up routing + /* the broadcast address is 255.255.255.255 */ + memset(&addrp->sin_addr, 255, sizeof(addrp->sin_addr)); + memset(&route, 0, sizeof(route)); + memcpy(&route.rt_gateway, addrp, sizeof(*addrp)); + + addrp->sin_family = AF_INET; + addrp->sin_port = 0; + addrp->sin_addr.s_addr = INADDR_ANY; + memcpy(&route.rt_dst, addrp, sizeof(*addrp)); + memcpy(&route.rt_genmask, addrp, sizeof(*addrp)); + + route.rt_dev = ifrp->ifr_name; + route.rt_flags = RTF_UP|RTF_GATEWAY; + route.rt_metric = 0; + + if (ioctl(s, SIOCADDRT, &route)) { /* add route */ + if (errno != EEXIST) { + perror("SIOCADDRT 3"); + return false; + } + } + + close(s); + + return true; +} + + +// ------------------------------------------------------------------------ +// DHCP retransmission timeouts and number of tries + +static unsigned char timeout_random = 0; + +static inline void reset_timeout( struct timeval *ptv ) +{ + timeout_random++; + ptv->tv_sec = 3 + (timeout_random & 3); + ptv->tv_usec = 65536 * (timeout_random & 15); +} + +static inline int next_timeout( struct timeval *ptv ) +{ + timeout_random++; + ptv->tv_sec = ptv->tv_sec * 2 - 2 + (timeout_random & 3); + return ptv->tv_sec < 48; // If longer, too many tries... +} + +// ------------------------------------------------------------------------ +// Lease expiry and alarms to notify it + +static cyg_alarm_t alarm_function; + +static void alarm_function(cyg_handle_t alarm, cyg_addrword_t data) +{ + struct dhcp_lease *lease = (struct dhcp_lease *)data; + lease->which |= lease->next; + cyg_semaphore_post( &dhcp_needs_attention ); + + // Step the lease on into its next state of being alarmed ;-) + if ( lease->next & DHCP_LEASE_EX ) { + cyg_alarm_disable( alarm ); + } + else if ( lease->next & DHCP_LEASE_T2 ) { + cyg_alarm_initialize( lease->alarm, lease->expiry, 0 ); + cyg_alarm_enable( lease->alarm ); + lease->next = DHCP_LEASE_EX; + } + else if ( lease->next & DHCP_LEASE_T1 ) { + cyg_alarm_initialize( lease->alarm, lease->t2, 0 ); + cyg_alarm_enable( lease->alarm ); + lease->next = DHCP_LEASE_T2; + } +} + +static inline void no_lease( struct dhcp_lease *lease ) +{ + if ( lease->alarm ) { + // Already set: delete this. + cyg_alarm_disable( lease->alarm ); + cyg_alarm_delete( lease->alarm ); + lease->alarm = 0; + } +} + +static inline void new_lease( struct bootp *bootp, struct dhcp_lease *lease ) +{ + cyg_tick_count_t now = cyg_current_time(); + cyg_tick_count_t then; + cyg_uint32 tag = 0; + cyg_resolution_t resolution = + cyg_clock_get_resolution(cyg_real_time_clock()); + cyg_handle_t h; + + // Silence any jabbering from past lease on this interface + no_lease( lease ); + lease->which = lease->next = 0; + cyg_clock_to_counter(cyg_real_time_clock(), &h); + cyg_alarm_create( h, alarm_function, (cyg_addrword_t)lease, + &lease->alarm, &lease->alarm_obj ); + + // extract the lease time and scale it &c to now. + get_bootp_option( bootp, TAG_DHCP_LEASE_TIME, &tag ); + + if ( 0xffffffff == tag ) { + lease->expiry = 0xffffffffffffffff; + lease->t2 = 0xffffffffffffffff; + lease->t1 = 0xffffffffffffffff; + return; // it's an infinite lease, hurrah! + } + + then = (cyg_uint64)(ntohl(tag)); + + then *= 1000000000; // into nS - we know there is room in a tick_count_t + then = (then / resolution.dividend) * resolution.divisor; // into system ticks + lease->expiry = now + then; + + get_bootp_option( bootp, TAG_DHCP_REBIND_TIME, &tag ); + then = (cyg_uint64)(ntohl(tag)); + then *= 1000000000; // into nS - we know there is room in a tick_count_t + then = (then / resolution.dividend) * resolution.divisor; // into system ticks + lease->t2 = now + then; + + get_bootp_option( bootp, TAG_DHCP_RENEWAL_TIME, &tag ); + then = (cyg_uint64)(ntohl(tag)); + then *= 1000000000; // into nS - we know there is room in a tick_count_t + then = (then / resolution.dividend) * resolution.divisor; // into system ticks + lease->t1 = now + then; + +#if 0 // for testing this mechanism + lease->expiry = now + 5000; // 1000 here makes for failure in the DHCP test + lease->t2 = now + 3500; + lease->t1 = now + 2500; +#endif + + lease->next = DHCP_LEASE_T1; + + cyg_alarm_initialize( lease->alarm, lease->t1, 0 ); + cyg_alarm_enable( lease->alarm ); +} + + +// ------------------------------------------------------------------------ +// the DHCP state machine - this does all the work + +int +do_dhcp(const char *intf, struct bootp *res, + cyg_uint8 *pstate, struct dhcp_lease *lease) +{ + struct ifreq ifr; + struct sockaddr_in cli_addr, broadcast_addr, server_addr, rx_addr; + int s, addrlen; + int one = 1; + unsigned char mincookie[] = {99,130,83,99,255} ; + struct timeval tv; + cyg_uint8 oldstate = *pstate; + cyg_uint8 msgtype = 0, seen_bootp_reply = 0; + + cyg_uint32 xid; + + // IMPORTANT: xmit is the same as res throughout this; *received is a + // scratch buffer for reception; its contents are always copied to res + // when we are happy with them. So we always transmit from the + // existing state. + struct bootp rx_local; + struct bootp *received = &rx_local; + struct bootp *xmit = res; + + // First, get a socket on the interface in question. But Zeroth, if + // needs be, bring it to the half-up broadcast only state if needs be. + + if ( DHCPSTATE_INIT == oldstate + || DHCPSTATE_FAILED == oldstate + || 0 == oldstate ) { + // either explicit init state or the beginning of time or retry + if ( ! bring_half_up( intf, &ifr ) ) + return false; + *pstate = DHCPSTATE_INIT; + xid = (cyg_uint32)res + (cyg_uint32)(0xffffffff & cyg_current_time()); + } + else + xid = res->bp_xid; // use what's there already + + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) { + perror("socket"); + return false; + } + + if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one))) { + perror("setsockopt"); + return false; + } + + memset((char *) &cli_addr, 0, sizeof(cli_addr)); + cli_addr.sin_family = AF_INET; + cli_addr.sin_addr.s_addr = htonl(INADDR_ANY); + cli_addr.sin_port = htons(IPPORT_BOOTPC); + + memset((char *) &broadcast_addr, 0, sizeof(broadcast_addr)); + broadcast_addr.sin_family = AF_INET; + broadcast_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST); + broadcast_addr.sin_port = htons(IPPORT_BOOTPS); + + memset((char *) &server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST); // overwrite later + server_addr.sin_port = htons(IPPORT_BOOTPS); + + if(bind(s, (struct sockaddr *) &cli_addr, sizeof(cli_addr)) < 0) { + perror("bind error"); + return false; + } + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) { + perror("setsockopt SO_REUSEADDR"); + return false; + } + if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one))) { + perror("setsockopt SO_REUSEPORT"); + return false; + } + + // Now, we can launch into the DHCP state machine. I think this will + // be the neatest way to do it; it returns from within the switch arms + // when all is well, or utterly failed. + + reset_timeout( &tv ); + + while ( 1 ) { + + // If we are active rather than in the process of shutting down, + // check for any lease expiry every time round, so that alarms + // *can* change the course of events even when already renewing, + // for example. + if ( DHCPSTATE_DO_RELEASE != *pstate + && DHCPSTATE_NOTBOUND != *pstate + && DHCPSTATE_FAILED != *pstate ) { + cyg_uint8 lease_state; + + cyg_scheduler_lock(); + lease_state = lease->which; + lease->which = 0; // flag that we have noticed it + cyg_scheduler_unlock(); + + if ( lease_state & DHCP_LEASE_EX ) { + // then the lease has expired completely! + *pstate = DHCPSTATE_NOTBOUND; + } + else if ( lease_state & DHCP_LEASE_T2 ) { + // Time to renew + reset_timeout( &tv ); // for the next conversation + *pstate = DHCPSTATE_REBINDING; + } + else if ( lease_state & DHCP_LEASE_T1 ) { + // Time to renew + reset_timeout( &tv ); // for the next conversation + *pstate = DHCPSTATE_RENEWING; + } + } + + switch ( *pstate ) { + + case DHCPSTATE_INIT: + + // Send the DHCPDISCOVER packet + + if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) { /* get MAC address */ + perror("SIOCGIFHWADDR 2"); + return false; + } + + // Fill in the BOOTP request - DHCPDISCOVER packet + bzero(xmit, sizeof(*xmit)); + xmit->bp_op = BOOTREQUEST; + xmit->bp_htype = ifr.ifr_hwaddr.sa_family; + xmit->bp_hlen = IFHWADDRLEN; + xmit->bp_xid = xid; + xmit->bp_secs = 0; + bcopy(ifr.ifr_hwaddr.sa_data, &xmit->bp_chaddr, xmit->bp_hlen); + bcopy(mincookie, xmit->bp_vend, sizeof(mincookie)); + + // remove the next line to test ability to handle bootp packets. + set_fixed_tag( xmit, TAG_DHCP_MESS_TYPE, DHCPDISCOVER, 1 ); + + set_fixed_tag( xmit, TAG_DHCP_MAX_MSGSZ, BP_MINPKTSZ, 2 ); + +#ifdef DHCP_CHATTER + diag_printf( "---------DHCPSTATE_INIT sending:\n" ); + show_bootp( intf, xmit ); +#endif + if(sendto(s, xmit, dhcp_size(xmit), 0, + (struct sockaddr *)&broadcast_addr, sizeof(broadcast_addr)) < 0) { + *pstate = DHCPSTATE_FAILED; + break; + } + + seen_bootp_reply = 0; + *pstate = DHCPSTATE_SELECTING; + break; + + case DHCPSTATE_SELECTING: + // This is a separate state so that we can listen again + // *without* retransmitting. + + // listen for the DHCPOFFER reply + + setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + + addrlen = sizeof(rx_addr); + if (recvfrom(s, received, sizeof(struct bootp), 0, + (struct sockaddr *)&rx_addr, &addrlen) < 0) { + // No packet arrived (this time) + if ( seen_bootp_reply ) { // then already have a bootp reply + // Save the good packet in *xmit + bcopy( received, xmit, dhcp_size(received) ); + *pstate = DHCPSTATE_BOOTP_FALLBACK; + reset_timeout( &tv ); + break; + } + // go to the next larger timeout and re-send: + if ( ! next_timeout( &tv ) ) { + *pstate = DHCPSTATE_FAILED; + break; + } + *pstate = DHCPSTATE_INIT; // to retransmit + break; + } + +#ifdef DHCP_CHATTER + diag_printf( "---------DHCPSTATE_SELECTING received:\n" ); + diag_printf( "...rx_addr is family %d, addr %08x, port %d\n", + rx_addr.sin_family, + rx_addr.sin_addr.s_addr, + rx_addr.sin_port ); + show_bootp( intf, received ); +#endif + if ( received->bp_xid != xid ) // not the same transaction; + break; // listen again... + + if ( 0 == received->bp_siaddr.s_addr ) { + // then fill in from the options... + get_bootp_option( received, TAG_DHCP_SERVER_ID, + &received->bp_siaddr.s_addr ); + } + + // see if it was a DHCP reply or a bootp reply; it could be + // either. + if ( get_bootp_option( received, TAG_DHCP_MESS_TYPE, &msgtype ) ) { + if ( DHCPOFFER == msgtype ) { // all is well + // Save the good packet in *xmit + bcopy( received, xmit, dhcp_size(received) ); + // we like the packet, so reset the timeout for next time + reset_timeout( &tv ); + *pstate = DHCPSTATE_REQUESTING; + } + } + else // No TAG_DHCP_MESS_TYPE entry so it's a bootp reply + seen_bootp_reply = 1; // (keep the bootp packet in received) + + // If none of the above state changes occurred, we got a packet + // that "should not happen", OR we have a bootp reply in our + // hand; so listen again with the same timeout, without + // retrying the send, in the hope of getting a DHCP reply. + break; + + case DHCPSTATE_REQUESTING: + // Just send what you got with a DHCPREQUEST in the message type. + // then wait for an ACK in DHCPSTATE_REQUEST_RECV. + + // Fill in the BOOTP request - DHCPREQUEST packet + xmit->bp_op = BOOTREQUEST; + + set_fixed_tag( xmit, TAG_DHCP_MESS_TYPE, DHCPREQUEST, 1 ); + set_fixed_tag( xmit, TAG_DHCP_MAX_MSGSZ, BP_MINPKTSZ, 2 ); + + // And this will be a new one: + set_fixed_tag( xmit, TAG_DHCP_REQ_IP, ntohl(xmit->bp_yiaddr.s_addr), 4 ); + +#ifdef DHCP_CHATTER + diag_printf( "---------DHCPSTATE_REQUESTING sending:\n" ); + show_bootp( intf, xmit ); +#endif + if(sendto(s, xmit, dhcp_size(xmit), 0, + (struct sockaddr *)&broadcast_addr, sizeof(broadcast_addr)) < 0) { + *pstate = DHCPSTATE_FAILED; + break; + } + + *pstate = DHCPSTATE_REQUEST_RECV; + break; + + case DHCPSTATE_REQUEST_RECV: + // wait for an ACK or a NACK - retry by going back to + // DHCPSTATE_REQUESTING; NACK means go back to INIT. + + setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + + addrlen = sizeof(rx_addr); + if (recvfrom(s, received, sizeof(struct bootp), 0, + (struct sockaddr *)&rx_addr, &addrlen) < 0) { + // No packet arrived + // go to the next larger timeout and re-send: + if ( ! next_timeout( &tv ) ) { + *pstate = DHCPSTATE_FAILED; + break; + } + *pstate = DHCPSTATE_REQUESTING; + break; + } + +#ifdef DHCP_CHATTER + diag_printf( "---------DHCPSTATE_REQUEST_RECV received:\n" ); + diag_printf( "...rx_addr is family %d, addr %08x, port %d\n", + rx_addr.sin_family, + rx_addr.sin_addr.s_addr, + rx_addr.sin_port ); + show_bootp( intf, received ); +#endif + if ( received->bp_xid != xid ) // not the same transaction; + break; // listen again... + + if ( 0 == received->bp_siaddr.s_addr ) { + // then fill in from the options... + get_bootp_option( received, TAG_DHCP_SERVER_ID, + &received->bp_siaddr.s_addr ); + } + + // check it was a DHCP reply + if ( get_bootp_option( received, TAG_DHCP_MESS_TYPE, &msgtype ) ) { + if ( DHCPACK == msgtype // Same offer & server? + && received->bp_yiaddr.s_addr == xmit->bp_yiaddr.s_addr + && received->bp_siaddr.s_addr == xmit->bp_siaddr.s_addr) { + // Save the good packet in *xmit + bcopy( received, xmit, dhcp_size(received) ); + // we like the packet, so reset the timeout for next time + reset_timeout( &tv ); + // Record the new lease and set up timers &c + new_lease( received, lease ); + *pstate = DHCPSTATE_BOUND; + break; + } + if ( DHCPNAK == msgtype ) { // 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. + // Just listen again, which implicitly discards it. + } + break; + + case DHCPSTATE_BOUND: + + // We are happy now, we have our address. + + // All done with socket + close(s); + + // Re-initialize the interface with the new state + if ( DHCPSTATE_BOUND != oldstate ) { + // Then need to go down and up + do_dhcp_down_net( intf, res, &oldstate, lease ); // oldstate used + if ( 0 != oldstate ) { + // Then not called from init_all_network_interfaces() + // so we must initialize the interface ourselves + if (!init_net(intf, res)) { + do_dhcp_down_net( intf, res, pstate, lease ); + *pstate = DHCPSTATE_FAILED; + return false; + } + } + } + + // Otherwise, nothing whatsoever to do... + return true; + + case DHCPSTATE_RENEWING: + // Just send what you got with a DHCPREQUEST in the message + // type UNICAST straight to the server. Then wait for an ACK. + + // Fill in the BOOTP request - DHCPREQUEST packet + xmit->bp_op = BOOTREQUEST; + + set_fixed_tag( xmit, TAG_DHCP_MESS_TYPE, DHCPREQUEST, 1 ); + set_fixed_tag( xmit, TAG_DHCP_MAX_MSGSZ, BP_MINPKTSZ, 2 ); + + // And this will be a new one: + set_fixed_tag( xmit, TAG_DHCP_REQ_IP, ntohl(xmit->bp_yiaddr.s_addr), 4 ); + + // Set unicast address to *server* + server_addr.sin_addr.s_addr = res->bp_siaddr.s_addr; + +#ifdef DHCP_CHATTER + diag_printf( "---------DHCPSTATE_RENEWING sending:\n" ); + diag_printf( "UNICAST to family %d, addr %08x, port %d\n", + server_addr.sin_family, + server_addr.sin_addr.s_addr, + server_addr.sin_port ); + show_bootp( intf, xmit ); +#endif + + if(sendto(s, xmit, dhcp_size(xmit), 0, + // UNICAST address of the server: + (struct sockaddr *)&server_addr, + sizeof(server_addr)) < 0) { + *pstate = DHCPSTATE_FAILED; + break; + } + + *pstate = DHCPSTATE_RENEW_RECV; + break; + + case DHCPSTATE_RENEW_RECV: + // wait for an ACK or a NACK - retry by going back to + // DHCPSTATE_RENEWING; NACK means go to NOTBOUND. + + setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + + addrlen = sizeof(rx_addr); + if (recvfrom(s, received, sizeof(struct bootp), 0, + (struct sockaddr *)&rx_addr, &addrlen) < 0) { + // No packet arrived + // go to the next larger timeout and re-send: + if ( ! next_timeout( &tv ) ) { + reset_timeout( &tv ); + *pstate = DHCPSTATE_REBINDING; + break; + } + *pstate = DHCPSTATE_RENEWING; + break; + } + +#ifdef DHCP_CHATTER + diag_printf( "---------DHCPSTATE_RENEW_RECV received:\n" ); + diag_printf( "...rx_addr is family %d, addr %08x, port %d\n", + rx_addr.sin_family, + rx_addr.sin_addr.s_addr, + rx_addr.sin_port ); + show_bootp( intf, received ); +#endif + if ( received->bp_xid != xid ) // not the same transaction; + break; // listen again... + + if ( 0 == received->bp_siaddr.s_addr ) { + // then fill in from the options... + get_bootp_option( received, TAG_DHCP_SERVER_ID, + &received->bp_siaddr.s_addr ); + } + + // check it was a DHCP reply + if ( get_bootp_option( received, TAG_DHCP_MESS_TYPE, &msgtype ) ) { + if ( DHCPACK == msgtype // Same offer? + && received->bp_yiaddr.s_addr == xmit->bp_yiaddr.s_addr) { + // Save the good packet in *xmit + bcopy( received, xmit, dhcp_size(received) ); + // we like the packet, so reset the timeout for next time + reset_timeout( &tv ); + // Record the new lease and set up timers &c + new_lease( received, lease ); + *pstate = DHCPSTATE_BOUND; + break; + } + if ( DHCPNAK == msgtype ) { // we're bounced! + *pstate = DHCPSTATE_NOTBOUND; // So quit out. + reset_timeout( &tv ); + break; + } + // otherwise it's something else, maybe another offer. + // Just listen again, which implicitly discards it. + } + break; + + case DHCPSTATE_REBINDING: + // Just send what you got with a DHCPREQUEST in the message type. + // Then wait for an ACK. This one is BROADCAST. + + // Fill in the BOOTP request - DHCPREQUEST packet + xmit->bp_op = BOOTREQUEST; + + set_fixed_tag( xmit, TAG_DHCP_MESS_TYPE, DHCPREQUEST, 1 ); + set_fixed_tag( xmit, TAG_DHCP_MAX_MSGSZ, BP_MINPKTSZ, 2 ); + + // And this will be a new one: + set_fixed_tag( xmit, TAG_DHCP_REQ_IP, ntohl(xmit->bp_yiaddr.s_addr), 4 ); + +#ifdef DHCP_CHATTER + diag_printf( "---------DHCPSTATE_REBINDING sending:\n" ); + show_bootp( intf, xmit ); +#endif + if(sendto(s, xmit, dhcp_size(xmit), 0, + (struct sockaddr *)&broadcast_addr, sizeof(broadcast_addr)) < 0) { + *pstate = DHCPSTATE_FAILED; + break; + } + + *pstate = DHCPSTATE_REBIND_RECV; + break; + + case DHCPSTATE_REBIND_RECV: + // wait for an ACK or a NACK - retry by going back to + // DHCPSTATE_REBINDING; NACK means go to NOTBOUND. + + setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + + addrlen = sizeof(rx_addr); + if (recvfrom(s, received, sizeof(struct bootp), 0, + (struct sockaddr *)&rx_addr, &addrlen) < 0) { + // No packet arrived + // go to the next larger timeout and re-send: + if ( ! next_timeout( &tv ) ) { + reset_timeout( &tv ); + *pstate = DHCPSTATE_FAILED; + break; + } + *pstate = DHCPSTATE_REBINDING; + break; + } + +#ifdef DHCP_CHATTER + diag_printf( "---------DHCPSTATE_REBIND_RECV received:\n" ); + diag_printf( "...rx_addr is family %d, addr %08x, port %d\n", + rx_addr.sin_family, + rx_addr.sin_addr.s_addr, + rx_addr.sin_port ); + show_bootp( intf, received ); +#endif + if ( received->bp_xid != xid ) // not the same transaction; + break; // listen again... + + if ( 0 == received->bp_siaddr.s_addr ) { + // then fill in from the options... + get_bootp_option( received, TAG_DHCP_SERVER_ID, + &received->bp_siaddr.s_addr ); + } + + // check it was a DHCP reply + if ( get_bootp_option( received, TAG_DHCP_MESS_TYPE, &msgtype ) ) { + if ( DHCPACK == msgtype // Same offer? + && received->bp_yiaddr.s_addr == xmit->bp_yiaddr.s_addr) { + // Save the good packet in *xmit + bcopy( received, xmit, dhcp_size(received) ); + // we like the packet, so reset the timeout for next time + reset_timeout( &tv ); + // Record the new lease and set up timers &c + new_lease( received, lease ); + *pstate = DHCPSTATE_BOUND; + break; + } + else if ( DHCPNAK == msgtype ) { // we're bounced! + *pstate = DHCPSTATE_NOTBOUND; // So back the start of the rigmarole. + reset_timeout( &tv ); + break; + } + // otherwise it's something else, maybe another offer. + // Just listen again, which implicitly discards it. + } + break; + + case DHCPSTATE_BOOTP_FALLBACK: + // All done with socket + close(s); + // And no lease should have become active, but JIC + no_lease( lease ); + // Re-initialize the interface with the new state + if ( DHCPSTATE_BOOTP_FALLBACK != oldstate ) { + // Then need to go down and up + do_dhcp_down_net( intf, res, &oldstate, lease ); // oldstate used + if ( 0 != oldstate ) { + // Then not called from init_all_network_interfaces() + // so we must initialize the interface ourselves + if (!init_net(intf, res)) { + do_dhcp_down_net( intf, res, pstate, lease ); + *pstate = DHCPSTATE_FAILED; + return false; + } + } + } + + // Otherwise, nothing whatsoever to do... + return true; + + case DHCPSTATE_NOTBOUND: + // All done with socket + close(s); + // No lease active + no_lease( lease ); + // Leave interface up so app can tidy. + return false; + + case DHCPSTATE_FAILED: + // All done with socket + close(s); + // No lease active + no_lease( lease ); + // Unconditionally down the interface. + do_dhcp_down_net( intf, res, &oldstate, lease ); + return false; + + case DHCPSTATE_DO_RELEASE: + // We have been forced here by external means, to release the + // lease for graceful shutdown. + + // Just send what you got with a DHCPRELEASE in the message + // type UNICAST straight to the server. No ACK. Then go to + // NOTBOUND state. + + xmit->bp_op = BOOTREQUEST; + set_fixed_tag( xmit, TAG_DHCP_MESS_TYPE, DHCPRELEASE, 1 ); + + // Set unicast address to *server* + server_addr.sin_addr.s_addr = res->bp_siaddr.s_addr; + +#ifdef DHCP_CHATTER + diag_printf( "---------DHCPSTATE_DO_RELEASE sending:\n" ); + diag_printf( "UNICAST to family %d, addr %08x, port %d\n", + server_addr.sin_family, + server_addr.sin_addr.s_addr, + server_addr.sin_port ); + show_bootp( intf, xmit ); +#endif + if(sendto(s, xmit, dhcp_size(xmit), 0, + // UNICAST address of the server: + (struct sockaddr *)&server_addr, + sizeof(server_addr)) < 0) { + *pstate = DHCPSTATE_FAILED; + break; + } + + *pstate = DHCPSTATE_NOTBOUND; + break; + + default: + no_lease( lease ); + close(s); + return false; + } + } + /* NOTREACHED */ + return false; +} + +// ------------------------------------------------------------------------ +// Bring an interface down, failed to initialize it or lease is expired +// Also part of normal startup, bring down for proper reinitialization + +int +do_dhcp_down_net(const char *intf, struct bootp *res, + cyg_uint8 *pstate, struct dhcp_lease *lease) +{ + struct sockaddr_in *addrp; + struct ifreq ifr; + int s; + + // Ensure clean slate + route_reinit(); // Force any existing routes to be forgotten + + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) { + perror("socket"); + return false; + } + + addrp = (struct sockaddr_in *) &ifr.ifr_addr; + + // Remove any existing address + if ( DHCPSTATE_FAILED == *pstate + || DHCPSTATE_INIT == *pstate + || 0 == *pstate ) { + // it was configured for broadcast only, "half-up" + memset(addrp, 0, sizeof(*addrp)); + addrp->sin_family = AF_INET; + addrp->sin_len = sizeof(*addrp); + addrp->sin_port = 0; + addrp->sin_addr.s_addr = INADDR_ANY; + } + else { + // get the specific address that was used + strcpy(ifr.ifr_name, intf); + if (ioctl(s, SIOCGIFADDR, &ifr)) { + perror("SIOCGIFADDR 1"); + return false; + } + } + + strcpy(ifr.ifr_name, intf); + if (ioctl(s, SIOCDIFADDR, &ifr)) { /* delete IF addr */ + perror("SIOCDIFADDR1"); + } + + // Shut down interface so it can be reinitialized + ifr.ifr_flags &= ~(IFF_UP | IFF_RUNNING); + if (ioctl(s, SIOCSIFFLAGS, &ifr)) { /* set ifnet flags */ + perror("SIOCSIFFLAGS down"); + return false; + } + + // All done with socket + close(s); + + if ( 0 != *pstate ) // preserve initial state + *pstate = DHCPSTATE_INIT; + + return true; +} + +// ------------------------------------------------------------------------ +// Release (relinquish) a leased address - if we have one - and bring down +// the interface. +int +do_dhcp_release(const char *intf, struct bootp *res, + cyg_uint8 *pstate, struct dhcp_lease *lease) +{ + if ( 0 != *pstate + && DHCPSTATE_INIT != *pstate + && DHCPSTATE_NOTBOUND != *pstate + && DHCPSTATE_FAILED != *pstate + && DHCPSTATE_BOOTP_FALLBACK != *pstate ) { + *pstate = DHCPSTATE_DO_RELEASE; + do_dhcp( intf, res, pstate, lease ); // to send the release packet + cyg_thread_delay( 100 ); // to let it leave the building + } + return true; +} + +// ------------------------------------------------------------------------ + +#endif // CYGPKG_NET_DHCP + +// EOF dhcp_prot.c
new file mode 100644 --- /dev/null +++ b/packages/net/tcpip/current/src/lib/dhcp_support.c @@ -0,0 +1,235 @@ +/*========================================================================== +// +// dhcp_support.c +// +// Support code == friendly API for DHCP client +// +//========================================================================== +//####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): hmt +// Contributors: gthomas +// Date: 2000-07-01 +// Purpose: DHCP support +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include <pkgconf/system.h> +#include <pkgconf/net.h> + +#ifdef CYGPKG_NET_DHCP + +#include <network.h> +#include <dhcp.h> + +// --------------------------------------------------------------------------- +#ifdef CYGHWR_NET_DRIVER_ETH0 +cyg_uint8 eth0_dhcpstate = 0; +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 +cyg_uint8 eth1_dhcpstate = 0; +#endif + +cyg_sem_t dhcp_needs_attention; + +#ifdef CYGHWR_NET_DRIVER_ETH0 +struct dhcp_lease eth0_lease = { 0,0,0,0 }; +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 +struct dhcp_lease eth1_lease = { 0,0,0,0 }; +#endif + +// --------------------------------------------------------------------------- +// +// The point of this module is to deal with all the horrid written out in +// full stuff of having two interfaces; it's ugly but it's also most +// flexible. The dhcp_prot.c module should do all the work... +// +// --------------------------------------------------------------------------- + +// return value: 1 => everything OK, no change. +// 0 => close your connections, then call do_dhcp_halt() to halt the +// interface(s) in question (it knows because the state will be NOTBOUND). +// After that you can return to the start and use +// init_all_network_interfaces(); as usual, or call do_dhcp_bind() by hand, +// or whatever... +int dhcp_bind( void ) +{ +#ifdef CYGHWR_NET_DRIVER_ETH0 + cyg_uint8 old_eth0_dhcpstate = eth0_dhcpstate; +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 + cyg_uint8 old_eth1_dhcpstate = eth1_dhcpstate; +#endif + + // If there are no interfaces at all, init it every time, doesn't + // matter. + if ( 1 +#ifdef CYGHWR_NET_DRIVER_ETH0 + && eth0_dhcpstate == 0 +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 + && eth1_dhcpstate == 0 +#endif + ) + cyg_semaphore_init( &dhcp_needs_attention, 0 ); + + // Run the state machine... +#ifdef CYGHWR_NET_DRIVER_ETH0 + if (eth0_up + && DHCPSTATE_FAILED != eth0_dhcpstate ) + eth0_up = do_dhcp(eth0_name, ð0_bootp_data, ð0_dhcpstate, ð0_lease); +#endif +#ifdef CYGHWR_NET_DRIVER_ETH0 + if (eth1_up + && DHCPSTATE_FAILED != eth1_dhcpstate ) + eth1_up = do_dhcp(eth1_name, ð1_bootp_data, ð1_dhcpstate, ð1_lease); +#endif + + // If the interface newly came up, initialize it: + // (this duplicates the code in init_all_network_interfaces() really). +#ifdef CYGHWR_NET_DRIVER_ETH0 + if ( eth0_up + && eth0_dhcpstate == DHCPSTATE_BOUND + && old_eth0_dhcpstate != eth0_dhcpstate ) { + if (!init_net(eth0_name, ð0_bootp_data)) { + eth0_up = false; + } + } +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 + if ( eth1_up + && eth1_dhcpstate == DHCPSTATE_BOUND + && old_eth1_dhcpstate != eth1_dhcpstate ) { + if (!init_net(eth1_name, ð1_bootp_data)) { + eth1_up = false; + } + } +#endif + +#ifdef CYGHWR_NET_DRIVER_ETH0 + if ( old_eth0_dhcpstate == DHCPSTATE_BOUND && + eth0_dhcpstate == DHCPSTATE_NOTBOUND ) + return 0; // a lease timed out; we became unbound +#endif +#ifdef CYGHWR_NET_DRIVER_ETH0 + if ( old_eth1_dhcpstate == DHCPSTATE_BOUND && + eth1_dhcpstate == DHCPSTATE_NOTBOUND ) + return 0; // a lease timed out; we became unbound +#endif + return 1; // all is well +} + + +// Shutdown any interface whose state is DHCPSTATE_NOTBOUND. +int dhcp_halt( void ) +{ +#ifdef CYGHWR_NET_DRIVER_ETH0 + if ( eth0_up + && eth0_dhcpstate != DHCPSTATE_FAILED ) { + do_dhcp_down_net(eth0_name, ð0_bootp_data, ð0_dhcpstate, ð0_lease); + } + eth0_up = false; +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 + if ( eth1_up + && eth1_dhcpstate != DHCPSTATE_FAILED ) { + do_dhcp_down_net(eth1_name, ð1_bootp_data, ð1_dhcpstate, ð1_lease); + } + eth1_up = false; +#endif +} + + +// Release (and set state to DHCPSTATE_NOTBOUND) all interfaces - we are +// closing down. (unlikely but maybe useful for testing) +int dhcp_release( void ) +{ +#ifdef CYGHWR_NET_DRIVER_ETH0 + if (eth0_up) + do_dhcp_release(eth0_name, ð0_bootp_data, ð0_dhcpstate, ð0_lease); +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 + if (eth1_up) + do_dhcp_release(eth1_name, ð1_bootp_data, ð1_dhcpstate, ð1_lease); +#endif +} + + +// ------------------------------------------------------------------------ +// The management thread function +void dhcp_mgt_entry( cyg_addrword_t loop_on_failure ) +{ + while ( 1 ) { + while ( 1 ) { + cyg_semaphore_wait( &dhcp_needs_attention ); + if ( ! dhcp_bind() ) // a lease expired + break; // If we need to re-bind + } + dhcp_halt(); // tear everything down + if ( loop_on_failure ) + init_all_network_interfaces(); // re-initialize + else + return; // exit the thread/return + } +} + +#ifdef CYGOPT_NET_DHCP_DHCP_THREAD +// Then we provide such a thread... +cyg_handle_t dhcp_mgt_thread_h = 0; +cyg_thread dhcp_mgt_thread; + +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + sizeof(struct bootp)) +static cyg_uint8 dhcp_mgt_stack[ STACK_SIZE ]; + +void dhcp_start_dhcp_mgt_thread( void ) +{ + if ( ! dhcp_mgt_thread_h ) { + cyg_thread_create( + CYGPKG_NET_THREAD_PRIORITY+1, /* scheduling info (eg pri) */ + dhcp_mgt_entry, /* entry point function */ + CYGOPT_NET_DHCP_DHCP_THREAD_PARAM, /* entry data */ + "DHCP lease mgt", /* optional thread name */ + dhcp_mgt_stack, /* stack base, NULL = alloc */ + STACK_SIZE, /* stack size, 0 = default */ + &dhcp_mgt_thread_h, /* returned thread handle */ + &dhcp_mgt_thread /* put thread here */ + ); + + cyg_thread_resume(dhcp_mgt_thread_h); + } +} + + +#endif // CYGOPT_NET_DHCP_DHCP_THREAD + +#endif // CYGPKG_NET_DHCP + +// EOF dhcp_support.c
--- a/packages/net/tcpip/current/src/lib/network_support.c +++ b/packages/net/tcpip/current/src/lib/network_support.c @@ -76,6 +76,12 @@ #include <network.h> #include <arpa/inet.h> +#include <eth_drv.h> + +#ifdef CYGPKG_NET_DHCP +#include <dhcp.h> +#endif + #ifdef CYGHWR_NET_DRIVER_ETH0 struct bootp eth0_bootp_data; cyg_bool_t eth0_up = false; @@ -181,8 +187,6 @@ cyg_bool_t init_loopback_interface(int l #endif -#if defined(CYGHWR_NET_DRIVER_ETH0_ADDRS_IP) \ - || defined(CYGHWR_NET_DRIVER_ETH1_ADDRS_IP) // // Internal function which builds up a fake BOOTP database for // an interface. @@ -204,7 +208,7 @@ add_tag(unsigned char *vp, return vp; } -static void +void build_bootp_record(struct bootp *bp, const char *addrs_ip, const char *addrs_netmask, @@ -235,9 +239,11 @@ build_bootp_record(struct bootp *bp, vp = add_tag(vp, TAG_SUBNET_MASK, &addr, sizeof(in_addr_t)); addr = inet_addr(addrs_broadcast); vp = add_tag(vp, TAG_IP_BROADCAST, &addr, sizeof(in_addr_t)); + addr = inet_addr(addrs_gateway); + vp = add_tag(vp, TAG_GATEWAY, &addr, sizeof(in_addr_t)); *vp = TAG_END; } -#endif + // // Initialize network interface[s] using BOOTP/DHCP @@ -262,12 +268,22 @@ init_all_network_interfaces(void) #ifdef CYGHWR_NET_DRIVER_ETH0_BOOTP // Perform a complete initialization, using BOOTP/DHCP eth0_up = true; - if (do_bootp(eth0_name, ð0_bootp_data)) { +#ifdef CYGHWR_NET_DRIVER_ETH0_DHCP + eth0_dhcpstate = 0; // Says that initialization is external to dhcp + if (do_dhcp(eth0_name, ð0_bootp_data, ð0_dhcpstate, ð0_lease)) +#else +#ifdef CYGPKG_NET_DHCP + eth0_dhcpstate = DHCPSTATE_BOOTP_FALLBACK; + // so the dhcp machine does no harm if called +#endif + if (do_bootp(eth0_name, ð0_bootp_data)) +#endif + { #ifdef CYGHWR_NET_DRIVER_ETH0_BOOTP_SHOW show_bootp(eth0_name, ð0_bootp_data); #endif } else { - diag_printf("BOOTP failed on eth0\n"); + diag_printf("BOOTP/DHCP failed on eth0\n"); eth0_up = false; } #elif defined(CYGHWR_NET_DRIVER_ETH0_ADDRS_IP) @@ -287,12 +303,22 @@ init_all_network_interfaces(void) #ifdef CYGHWR_NET_DRIVER_ETH1_BOOTP // Perform a complete initialization, using BOOTP/DHCP eth1_up = true; - if (do_bootp(eth1_name, ð1_bootp_data)) { +#ifdef CYGHWR_NET_DRIVER_ETH1_DHCP + eth1_dhcpstate = 0; // Says that initialization is external to dhcp + if (do_dhcp(eth1_name, ð1_bootp_data, ð1_dhcpstate, ð1_lease)) +#else +#ifdef CYGPKG_NET_DHCP + eth1_dhcpstate = DHCPSTATE_BOOTP_FALLBACK; + // so the dhcp machine does no harm if called +#endif + if (do_bootp(eth1_name, ð1_bootp_data)) +#endif + { #ifdef CYGHWR_NET_DRIVER_ETH1_BOOTP_SHOW show_bootp(eth1_name, ð1_bootp_data); #endif } else { - diag_printf("BOOTP failed on eth1\n"); + diag_printf("BOOTP/DHCP failed on eth1\n"); eth1_up = false; } #elif defined(CYGHWR_NET_DRIVER_ETH1_ADDRS_IP) @@ -340,6 +366,13 @@ init_all_network_interfaces(void) #endif #endif +#ifdef CYGOPT_NET_DHCP_DHCP_THREAD + dhcp_start_dhcp_mgt_thread(); +#endif + // Open the monitor to other threads. in_init_all_network_interfaces = 0; + } + +// EOF network_support.c
--- a/packages/net/tcpip/current/src/sys/net/if.c +++ b/packages/net/tcpip/current/src/sys/net/if.c @@ -311,6 +311,10 @@ void if_attach(ifp) struct ifnet *ifp; { +// Initialize queue - moved here to support "late" attaches + if (ifp->if_snd.ifq_maxlen == 0) + ifp->if_snd.ifq_maxlen = ifqmaxlen; +// if (if_index == 0) TAILQ_INIT(&ifnet); TAILQ_INIT(&ifp->if_addrlist);
new file mode 100644 --- /dev/null +++ b/packages/net/tcpip/current/tests/dhcp_test.c @@ -0,0 +1,341 @@ +//========================================================================== +// +// tests/dhcp_test.c +// +// Simple test of DHCP (ICMP) and networking support +// +//========================================================================== +//####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): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +// DHCP test code + +#include <network.h> + +#include <pkgconf/system.h> +#include <pkgconf/net.h> + +#include <dhcp.h> + +#include <cyg/infra/testcase.h> + +#ifdef CYGBLD_DEVS_ETH_DEVICE_H // Get the device config if it exists +#include CYGBLD_DEVS_ETH_DEVICE_H // May provide CYGTST_DEVS_ETH_TEST_NET_REALTIME +#endif + +#ifdef CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS // do we use the rt test? +# ifdef CYGTST_DEVS_ETH_TEST_NET_REALTIME // Get the test ancilla if it exists +# include CYGTST_DEVS_ETH_TEST_NET_REALTIME +# endif +#endif + +// Fill in the blanks if necessary +#ifndef TNR_OFF +# define TNR_OFF() +#endif +#ifndef TNR_ON +# define TNR_ON() +#endif +#ifndef TNR_INIT +# define TNR_INIT() +#endif +#ifndef TNR_PRINT_ACTIVITY +# define TNR_PRINT_ACTIVITY() +#endif + + + +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000) +static char stack[STACK_SIZE]; +static cyg_thread thread_data; +static cyg_handle_t thread_handle; + +#define NUM_PINGS 16 +#define MAX_PACKET 4096 +#define MIN_PACKET 64 +#define MAX_SEND 4000 + +#define PACKET_ADD ((MAX_SEND - MIN_PACKET)/NUM_PINGS) +#define nPACKET_ADD 1 + +static unsigned char pkt1[MAX_PACKET], pkt2[MAX_PACKET]; + +#define UNIQUEID 0x1234 + +void +pexit(char *s) +{ + CYG_TEST_FAIL_FINISH(s); +} + +// Compute INET checksum +int +inet_cksum(u_short *addr, int len) +{ + register int nleft = len; + register u_short *w = addr; + register u_short answer; + register u_int sum = 0; + u_short odd_byte = 0; + + /* + * Our algorithm is simple, using a 32 bit accumulator (sum), + * we add sequential 16 bit words to it, and at the end, fold + * back all the carry bits from the top 16 bits into the lower + * 16 bits. + */ + while( nleft > 1 ) { + sum += *w++; + nleft -= 2; + } + + /* mop up an odd byte, if necessary */ + if( nleft == 1 ) { + *(u_char *)(&odd_byte) = *(u_char *)w; + sum += odd_byte; + } + + /* + * add back carry outs from top 16 bits to low 16 bits + */ + sum = (sum >> 16) + (sum & 0x0000ffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* truncate to 16 bits */ + return (answer); +} + +static int +show_icmp(unsigned char *pkt, int len, + struct sockaddr_in *from, struct sockaddr_in *to) +{ + cyg_tick_count_t *tp, tv; + struct ip *ip; + struct icmp *icmp; + tv = cyg_current_time(); + ip = (struct ip *)pkt; + if ((len < sizeof(*ip)) || ip->ip_v != IPVERSION) { + diag_printf("%s: Short packet or not IP! - Len: %d, Version: %d\n", + inet_ntoa(from->sin_addr), len, ip->ip_v); + return 0; + } + icmp = (struct icmp *)(pkt + sizeof(*ip)); + len -= (sizeof(*ip) + 8); + tp = (cyg_tick_count_t *)&icmp->icmp_data; + if (icmp->icmp_type != ICMP_ECHOREPLY) { + diag_printf("%s: Invalid ICMP - type: %d\n", + inet_ntoa(from->sin_addr), icmp->icmp_type); + return 0; + } + if (icmp->icmp_id != UNIQUEID) { + diag_printf("%s: ICMP received for wrong id - sent: %x, recvd: %x\n", + inet_ntoa(from->sin_addr), UNIQUEID, icmp->icmp_id); + } + diag_printf("%d bytes from %s: ", len, inet_ntoa(from->sin_addr)); + diag_printf("icmp_seq=%d", icmp->icmp_seq); + diag_printf(", time=%dms\n", (int)(tv - *tp)*10); + return (from->sin_addr.s_addr == to->sin_addr.s_addr); +} + +static void +ping_host(int s, struct sockaddr_in *host) +{ + struct icmp *icmp = (struct icmp *)pkt1; + int icmp_len = MIN_PACKET; + int seq, ok_recv, bogus_recv; + cyg_tick_count_t *tp; + long *dp; + struct sockaddr_in from; + int i, len, fromlen; + + ok_recv = 0; + bogus_recv = 0; + diag_printf("PING server %s\n", inet_ntoa(host->sin_addr)); + for (seq = 0; seq < NUM_PINGS; seq++, icmp_len += PACKET_ADD ) { + TNR_ON(); + // Build ICMP packet + icmp->icmp_type = ICMP_ECHO; + icmp->icmp_code = 0; + icmp->icmp_cksum = 0; + icmp->icmp_seq = seq; + icmp->icmp_id = 0x1234; + // Set up ping data + tp = (cyg_tick_count_t *)&icmp->icmp_data; + *tp++ = cyg_current_time(); + dp = (long *)tp; + for (i = sizeof(*tp); i < icmp_len; i += sizeof(*dp)) { + *dp++ = i; + } + // Add checksum + icmp->icmp_cksum = inet_cksum( (u_short *)icmp, icmp_len+8); + // Send it off + if (sendto(s, icmp, icmp_len+8, 0, (struct sockaddr *)host, sizeof(*host)) < 0) { + TNR_OFF(); + perror("sendto"); + continue; + } + // Wait for a response + fromlen = sizeof(from); + len = recvfrom(s, pkt2, sizeof(pkt2), 0, (struct sockaddr *)&from, &fromlen); + TNR_OFF(); + if (len < 0) { + perror("recvfrom"); + seq+=4; + } else { + if (show_icmp(pkt2, len, &from, host)) { + ok_recv++; + } else { + bogus_recv++; + } + } + } + TNR_OFF(); +} + +static void +ping_test(struct bootp *bp) +{ + struct protoent *p; + struct timeval tv; + struct sockaddr_in host; + int s; + + if ((p = getprotobyname("icmp")) == (struct protoent *)0) { + pexit("getprotobyname"); + return; + } + s = socket(AF_INET, SOCK_RAW, p->p_proto); + if (s < 0) { + pexit("socket"); + return; + } + tv.tv_sec = 1; + tv.tv_usec = 0; + setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + // Set up host address + host.sin_family = AF_INET; + host.sin_addr = bp->bp_siaddr; + host.sin_port = 0; + ping_host(s, &host); + // Now try a bogus host + host.sin_addr.s_addr = htonl(ntohl(host.sin_addr.s_addr) + 32); + ping_host(s, &host); + close(s); +} + +void +net_test(cyg_addrword_t p) +{ +#ifndef CYGPKG_NET_DHCP + CYG_TEST_NA_FINISH( "DHCP is not enabled" ); +#else + int i; + diag_printf("Start DHCP test\n"); + TNR_INIT(); + init_all_network_interfaces(); + + for ( i = 10; i > 0; i-- ) { +#ifdef CYGHWR_NET_DRIVER_ETH0 + if (eth0_up) { + ping_test(ð0_bootp_data); + } +#endif + // Now do the DHCP renewal ritual... + if ( cyg_semaphore_trywait( &dhcp_needs_attention )) { + if ( ! dhcp_bind() ) { + // All done + dhcp_halt(); + CYG_TEST_FAIL_FINISH( "Rebind after lease failed"); + break; + } + } +#ifdef CYGHWR_NET_DRIVER_ETH1 + if (eth1_up) { + ping_test(ð1_bootp_data); + } +#endif + +#ifndef CYGOPT_NET_DHCP_DHCP_THREAD + // Now do the DHCP renewal ritual... + if ( cyg_semaphore_trywait( &dhcp_needs_attention )) { + if ( ! dhcp_bind() ) { + // All done + dhcp_halt(); + CYG_TEST_FAIL_FINISH( "Rebind after lease failed"); + break; + } + } +#endif // not CYGOPT_NET_DHCP_DHCP_THREAD + + if ( 1 == (i & 3) ) { + dhcp_release(); // relinquish leases + dhcp_halt(); + init_all_network_interfaces(); + } + } + dhcp_release(); + + TNR_PRINT_ACTIVITY(); + CYG_TEST_PASS_FINISH("Dhcp test OK"); +#endif +} + +void +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 + net_test, // entry + 0, // entry parameter + "Network test", // Name + &stack[0], // Stack + STACK_SIZE, // Size + &thread_handle, // Handle + &thread_data // Thread data structure + ); + cyg_thread_resume(thread_handle); // Start it + cyg_scheduler_start(); +}
--- a/packages/net/tcpip/current/tests/flood.c +++ b/packages/net/tcpip/current/tests/flood.c @@ -88,7 +88,7 @@ #define MAX_PACKET 4096 #define NUMTHREADS 3 -#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + MAX_PACKET + MAX_PACKET) +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + MAX_PACKET + MAX_PACKET + 0x1000) static char thread_stack[NUMTHREADS][STACK_SIZE]; static cyg_thread thread_data[NUMTHREADS]; static cyg_handle_t thread_handle[NUMTHREADS];
--- a/packages/net/tcpip/current/tests/ftp_test.c +++ b/packages/net/tcpip/current/tests/ftp_test.c @@ -55,7 +55,7 @@ #include <network.h> -#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000) static char stack[STACK_SIZE]; static cyg_thread thread_data; static cyg_handle_t thread_handle;
--- a/packages/net/tcpip/current/tests/nc_test_master.c +++ b/packages/net/tcpip/current/tests/nc_test_master.c @@ -57,7 +57,7 @@ #include "nc_test_framework.h" #ifdef __ECOS -#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000) static char stack[STACK_SIZE]; static cyg_thread thread_data; static cyg_handle_t thread_handle;
--- a/packages/net/tcpip/current/tests/nc_test_slave.c +++ b/packages/net/tcpip/current/tests/nc_test_slave.c @@ -58,7 +58,7 @@ #include <math.h> #ifdef __ECOS -#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000) #define MAX_LOAD_THREAD_LEVEL 20 #define MIN_LOAD_THREAD_LEVEL 0 #define NUM_LOAD_THREADS 10
--- a/packages/net/tcpip/current/tests/ping_lo_test.c +++ b/packages/net/tcpip/current/tests/ping_lo_test.c @@ -58,7 +58,7 @@ #include <cyg/infra/testcase.h> -#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000) static char stack[STACK_SIZE]; static cyg_thread thread_data; static cyg_handle_t thread_handle;
--- a/packages/net/tcpip/current/tests/ping_test.c +++ b/packages/net/tcpip/current/tests/ping_test.c @@ -87,7 +87,7 @@ -#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000) static char stack[STACK_SIZE]; static cyg_thread thread_data; static cyg_handle_t thread_handle;
--- a/packages/net/tcpip/current/tests/server_test.c +++ b/packages/net/tcpip/current/tests/server_test.c @@ -55,7 +55,7 @@ #include <stdio.h> #include <network.h> -#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000) static char stack[STACK_SIZE]; static cyg_thread thread_data; static cyg_handle_t thread_handle;
--- a/packages/net/tcpip/current/tests/set_mac_address.c +++ b/packages/net/tcpip/current/tests/set_mac_address.c @@ -66,7 +66,7 @@ #include <netinet/if_ether.h> #define NUMTHREADS 1 -#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL) +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000) static char thread_stack[NUMTHREADS][STACK_SIZE]; static cyg_thread thread_data[NUMTHREADS]; static cyg_handle_t thread_handle[NUMTHREADS];
--- a/packages/net/tcpip/current/tests/tcp_echo.c +++ b/packages/net/tcpip/current/tests/tcp_echo.c @@ -108,7 +108,7 @@ struct test_status { long ok; }; -#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000) static char stack[STACK_SIZE]; static cyg_thread thread_data; static cyg_handle_t thread_handle;
--- a/packages/net/tcpip/current/tests/tftp_client_test.c +++ b/packages/net/tcpip/current/tests/tftp_client_test.c @@ -58,7 +58,7 @@ // Note: the TFTP client calls need at least (SEGSIZE==512)+4 // additional bytes of workspace, thus the padding. -#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL+1024) +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL+0x1000) static char stack[STACK_SIZE]; static cyg_thread thread_data; static cyg_handle_t thread_handle;
--- a/packages/net/tcpip/current/tests/tftp_server_test.c +++ b/packages/net/tcpip/current/tests/tftp_server_test.c @@ -86,7 +86,7 @@ #include <network.h> #include <tftp_support.h> -#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000) static char stack[STACK_SIZE]; static cyg_thread thread_data; static cyg_handle_t thread_handle;
