# HG changeset patch # User jlarmour # Date 968099052 0 # Node ID 6bd9d475ed4b48c97a45737ee4d9dbbcbc558400 # Parent 0e17207f29f3285bc7898d7c0290b83a7498285e Merge from eCos master repository on 2000-09-04-20:50:20-BST diff --git a/packages/NEWS b/packages/NEWS --- a/packages/NEWS +++ b/packages/NEWS @@ -11,8 +11,8 @@ * Added flash memory support for ARM-EBSA285 and ARM-EDB7xxx boards * Added Compact Flash Ethernet driver * Hitachi SH7707a variant support added. -* Support added for both software and hardware flow control (the latter - initially only for the ARM PID board) +* Support added for both software and hardware flow control with an initial + version of the latter available only for the ARM PID board at present. * Loopback serial device driver added * POSIX termios support added for EL/IX level 1 compatibility * Improved dynamic memory management support in the memory allocator @@ -58,9 +58,10 @@ * Most targets now implement a standard form of "virtual vectors" - a mechanism to allow enhanced co-operation between ROM monitors and running applications. This allows the application to leave to the ROM things that - the ROM supports rather than duplicating. It also will permit network - debugging in future. To take advantage of this, new GDB stub - images/CygMon images should be programmed onto boards. + the ROM supports rather than duplicating, including debug channels that may + be via serial or ethernet. To take advantage of this, new GDB stub + images/CygMon images should be programmed onto boards, although old images + will continue to work - they will just not be able to use the new facilities. * DHCP support has been added to the TCP/IP support, in addition to the existing BOOTP support * CDL now supports type bool and booldata for interfaces diff --git a/packages/compat/posix/current/ChangeLog b/packages/compat/posix/current/ChangeLog --- a/packages/compat/posix/current/ChangeLog +++ b/packages/compat/posix/current/ChangeLog @@ -1,3 +1,12 @@ +2000-09-04 Nick Garnett + + * tests/pthread2.c: + * tests/pthread3.c: + Fixed bug in calculation of thread stack addresses. + + * src/misc.cxx (sysconf): Change zero returns to -1 when a feature + is not supported. + 2000-08-08 Jonathan Larmour * include/limits.h: Don't define SSIZE_MAX here, leave it to the diff --git a/packages/compat/posix/current/src/misc.cxx b/packages/compat/posix/current/src/misc.cxx --- a/packages/compat/posix/current/src/misc.cxx +++ b/packages/compat/posix/current/src/misc.cxx @@ -145,168 +145,168 @@ #ifdef _POSIX_ASYNCHRONOUS_IO return 1; #else - return 0; + return -1; #endif case _SC_FSYNC: #ifdef _POSIX_FSYNC return 1; #else - return 0; + return -1; #endif case _SC_JOB_CONTROL: #ifdef _POSIX_JOB_CONTROL return 1; #else - return 0; + return -1; #endif case _SC_MAPPED_FILES: #ifdef _POSIX_MAPPED_FILES return 1; #else - return 0; + return -1; #endif case _SC_MEMLOCK: #ifdef _POSIX_MEMLOCK return 1; #else - return 0; + return -1; #endif case _SC_MEMLOCK_RANGE: #ifdef _POSIX_MEMLOCK_RANGE return 1; #else - return 0 ; + return -1 ; #endif case _SC_MEMORY_PROTECTION: #ifdef _POSIX_MEMORY_PROTECTION return 1; #else - return 0; + return -1; #endif case _SC_MESSAGE_PASSING: #ifdef _POSIX_MESSAGE_PASSING return 1; #else - return 0; + return -1; #endif case _SC_PRIORITIZED_IO: #ifdef _POSIX_PRIORITIZED_IO return 1; #else - return 0; + return -1; #endif case _SC_PRIORITY_SCHEDULING: #ifdef _POSIX_PRIORITY_SCHEDULING return 1; #else - return 0; + return -1; #endif case _SC_REALTIME_SIGNALS: #ifdef _POSIX_REALTIME_SIGNALS return 1; #else - return 0; + return -1; #endif case _SC_SAVED_IDS: #ifdef _POSIX_SAVED_IDS return 1; #else - return 0; + return -1; #endif case _SC_SEMAPHORES: #ifdef _POSIX_SEMAPHORES return 1; #else - return 0; + return -1; #endif case _SC_SHARED_MEMORY_OBJECTS: #ifdef _POSIX_SHARED_MEMORY_OBJECTS return 1; #else - return 0; + return -1; #endif case _SC_SYNCHRONIZED_IO: #ifdef _POSIX_SYNCHRONIZED_IO return 1; #else - return 0; + return -1; #endif case _SC_THREADS: #ifdef _POSIX_THREADS return 1; #else - return 0; + return -1; #endif case _SC_THREAD_ATTR_STACKADDR: #ifdef _POSIX_THREAD_ATTR_STACKADDR return 1; #else - return 0; + return -1; #endif case _SC_THREAD_ATTR_STACKSIZE: #ifdef _POSIX_THREAD_ATTR_STACKSIZE return 1; #else - return 0; + return -1; #endif case _SC_THREAD_PRIO_INHERIT: #ifdef _POSIX_THREAD_PRIO_INHERIT return 1; #else - return 0; + return -1; #endif case _SC_THREAD_PRIO_PROTECT: #ifdef _POSIX_THREAD_PRIO_PROTECT return 1; #else - return 0; + return -1; #endif case _SC_THREAD_PRIORITY_SCHEDULING: #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING return 1; #else - return 0; + return -1; #endif case _SC_THREAD_PROCESS_SHARED: #ifdef _POSIX_THREAD_PROCESS_SHARED return 1; #else - return 0; + return -1; #endif case _SC_THREAD_SAFE_FUNCTIONS: #ifdef _POSIX_THREAD_SAFE_FUNCTIONS return 1; #else - return 0; + return -1; #endif case _SC_TIMERS: #ifdef _POSIX_TIMERS return 1; #else - return 0; + return -1; #endif diff --git a/packages/compat/posix/current/tests/pthread2.c b/packages/compat/posix/current/tests/pthread2.c --- a/packages/compat/posix/current/tests/pthread2.c +++ b/packages/compat/posix/current/tests/pthread2.c @@ -119,7 +119,7 @@ int main(int argc, char **argv) pthread_attr_t attr; pthread_attr_init( &attr ); - pthread_attr_setstackaddr( &attr, (void *)&thread_stack[i][sizeof(thread_stack)] ); + pthread_attr_setstackaddr( &attr, (void *)&thread_stack[i][sizeof(thread_stack[i])] ); pthread_attr_setstacksize( &attr, sizeof(thread_stack[i]) ); ret = pthread_create( &thread[i], diff --git a/packages/compat/posix/current/tests/pthread3.c b/packages/compat/posix/current/tests/pthread3.c --- a/packages/compat/posix/current/tests/pthread3.c +++ b/packages/compat/posix/current/tests/pthread3.c @@ -171,7 +171,7 @@ int main(int argc, char **argv) pthread_attr_t attr; pthread_attr_init( &attr ); - pthread_attr_setstackaddr( &attr, (void *)&thread_stack[i][sizeof(thread_stack)] ); + pthread_attr_setstackaddr( &attr, (void *)&thread_stack[i][sizeof(thread_stack[i])] ); pthread_attr_setstacksize( &attr, sizeof(thread_stack[i]) ); ret = pthread_create( &thread[i], diff --git a/packages/devs/eth/arm/ebsa285/current/ChangeLog b/packages/devs/eth/arm/ebsa285/current/ChangeLog --- a/packages/devs/eth/arm/ebsa285/current/ChangeLog +++ b/packages/devs/eth/arm/ebsa285/current/ChangeLog @@ -1,3 +1,34 @@ +2000-09-01 Hugo Tyson + + * OVERVIEW: This is part of the change to the network stack to + greatly reduce latencies both of (other) DSRs and of thread + scheduling. All the work that the network stack *and* individual + ether drivers used to do in DSRs (including alarm callbacks and + data copies to/from the device memory) is moved into a "fast + network thread" instead. It calls a device's "deliver" function + to do the work that was previously in the DSR. This is a separate + thread so that it can be set higher priority than application + threads in order to minimize packet loss (depending on the + driver), if required (the application threads presumed to be + higher priority in turn than the network thread). A crucial + consequence of this is that we are no longer locking against DSRs, + so a plain mutex can be used rather than the global scheduler + lock, thus simplifying all the splfoo/splx() style functions. + + * src/if_ebsa285.c: Minor: fix the big assert in i82559_send() + which suffered a race condition when called from the fast thread + rather than from a DSR. Major: Add a "deliver" entry to the + interface record for the "fast thread" implementation of the + network internal comms system. Provide a pass-up DSR to the + logical ether driver's DSR and appropriate delivery routine(s). + i82559_poll() now calls i82559_deliver() rather than the DSR. Add + valid data for mux'd DSR to pass on up. + +2000-09-01 Hugo Tyson + + * tests/test_net_realtime.h: Tighten up the latency requirements + by a factor of 5; it all seems happy, so committed. + 2000-08-25 Hugo Tyson * src/if_ebsa285.c (i82559_ioctl): A little further diddling; have diff --git a/packages/devs/eth/arm/ebsa285/current/src/if_ebsa285.c b/packages/devs/eth/arm/ebsa285/current/src/if_ebsa285.c --- a/packages/devs/eth/arm/ebsa285/current/src/if_ebsa285.c +++ b/packages/devs/eth/arm/ebsa285/current/src/if_ebsa285.c @@ -408,6 +408,7 @@ ETH_DRV_SC(ebsa285_sc0, i82559_can_send, i82559_send, i82559_recv, + i82559_deliver, i82559_poll, i82559_int_vector); @@ -429,6 +430,7 @@ ETH_DRV_SC(ebsa285_sc1, i82559_can_send, i82559_send, i82559_recv, + i82559_deliver, i82559_poll, i82559_int_vector); @@ -1134,7 +1136,7 @@ static void ResetRxRing(struct i82559* p // ------------------------------------------------------------------------ // -// Function : PacketRxReady (Called from DSR) +// Function : PacketRxReady (Called from delivery thread) // // ------------------------------------------------------------------------ static void PacketRxReady(struct i82559* p_i82559) @@ -1395,8 +1397,8 @@ static void TxMachine(struct i82559* p_i tx_descriptor_active = p_i82559->tx_descriptor_active; ioaddr = p_i82559->io_address; - // See if the CU is idle when we think it isn't: - // (Recovers from a dropped interrupt) + // See if the CU is idle when we think it isn't; this is the only place + // tx_descriptor_active is advanced. (Also recovers from a dropped intr) if ( p_i82559->tx_in_progress ) { cyg_uint16 status; status = INW(ioaddr + SCBStatus); @@ -1435,7 +1437,7 @@ static void TxMachine(struct i82559* p_i // ------------------------------------------------------------------------ // -// Function : TxDone (Called from DSR) +// Function : TxDone (Called from delivery thread) // // This returns Tx's from the Tx Machine to the stack (ie. reports // completion) - allowing for missed interrupts, and so on. @@ -1607,6 +1609,9 @@ i82559_send(struct eth_drv_sc *sc, tx_descriptor_add = 0; p_i82559->tx_descriptor_add = tx_descriptor_add; + // From this instant, interrupts can advance the world and start, + // even complete, this tx request... + if ( p_i82559->tx_descriptor_remove == tx_descriptor_add ) p_i82559->tx_queue_full = 1; } @@ -1618,11 +1623,17 @@ i82559_send(struct eth_drv_sc *sc, // Check that either: // tx is already active, there is other stuff queued, - // OR this tx just added is the current active one. - CYG_ASSERT( (p_i82559->tx_in_progress == 1) || - ((p_i82559->tx_descriptor_add-1) == p_i82559->tx_descriptor_active) - || ((0 == p_i82559->tx_descriptor_add) && - ((MAX_TX_DESCRIPTORS-1) == p_i82559->tx_descriptor_active)), + // OR this tx just added is the current active one + // OR this tx just added is already complete + CYG_ASSERT( + // The machine is busy: + (p_i82559->tx_in_progress == 1) || + // or: The machine is idle and this just added is the next one + (((p_i82559->tx_descriptor_add-1) == p_i82559->tx_descriptor_active) + || ((0 == p_i82559->tx_descriptor_add) && + ((MAX_TX_DESCRIPTORS-1) == p_i82559->tx_descriptor_active))) || + // or: This tx is already complete + (p_i82559->tx_descriptor_add == p_i82559->tx_descriptor_active), "Active/add mismatch" ); // Advance TxMachine atomically @@ -1732,10 +1743,23 @@ static cyg_uint32 eth_mux_isr(cyg_vector // ------------------------------------------------------------------------ +static void eth_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) { struct i82559* p_i82559 = (struct i82559 *)data; - + struct cyg_netdevtab_entry *ndp = + (struct cyg_netdevtab_entry *)(p_i82559->ndp); + struct eth_drv_sc *sc = (struct eth_drv_sc *)(ndp->device_instance); + + // but here, it must be a *sc: + eth_drv_dsr( vector, count, (cyg_addrword_t)sc ); +} + +// ------------------------------------------------------------------------ +// This is called from the function below (used to be uni-DSR) +static inline void +uni_deliver(struct i82559* p_i82559) +{ // First pass any rx data up the stack PacketRxReady(p_i82559); @@ -1745,17 +1769,18 @@ void eth_dsr(cyg_vector_t vector, cyg_uc // ------------------------------------------------------------------------ -void eth_mux_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +void i82559_deliver(struct eth_drv_sc *sc) { + struct i82559* p_i82559; int device_index = mux_device_index; - struct i82559* p_i82559; + + // Since this must mux both devices, the incoming arg is ignored. mux_device_index ^= 1; // look at the other one first next time. - // (non-atomicity wrt IRQ does not matter) do { p_i82559 = &i82559[device_index]; if ( p_i82559->active ) - eth_dsr( vector, count, (cyg_addrword_t)p_i82559 ); + uni_deliver( p_i82559 ); device_index ^= 1; } while ( device_index == mux_device_index ); } @@ -1777,10 +1802,13 @@ void i82559_poll(struct eth_drv_sc *sc) // As it happens, this driver always requests the DSR to be called: (void)eth_mux_isr( CYGNUM_HAL_INTERRUPT_PCI_IRQ, (cyg_addrword_t)p_i82559 ); - eth_mux_dsr( CYGNUM_HAL_INTERRUPT_PCI_IRQ, 1, (cyg_addrword_t)p_i82559 ); + + i82559_deliver( NULL /* arg is not used */ ); } -// Determine interrupt vector used by a device +// ------------------------------------------------------------------------ +// Determine interrupt vector used by a device - for attaching GDB stubs +// packet handler. int i82559_int_vector(struct eth_drv_sc *sc) { @@ -1879,9 +1907,9 @@ pci_init_find_82559s( void ) cyg_drv_interrupt_create( CYGNUM_HAL_INTERRUPT_PCI_IRQ, 0, // Priority - unused - 0, // Data item passed to ISR (not used) + (CYG_ADDRWORD)p_i82559,// Data item passed to ISR and DSR eth_mux_isr, // ISR - eth_mux_dsr, // DSR + eth_dsr, // DSR &mux_interrupt_handle, &mux_interrupt_object ); diff --git a/packages/devs/eth/arm/ebsa285/current/tests/test_net_realtime.h b/packages/devs/eth/arm/ebsa285/current/tests/test_net_realtime.h --- a/packages/devs/eth/arm/ebsa285/current/tests/test_net_realtime.h +++ b/packages/devs/eth/arm/ebsa285/current/tests/test_net_realtime.h @@ -95,9 +95,16 @@ // 100[characters] * 8[bits/byte] / 38400[Baud] [Seconds] = 20mS. // Use the fclk_in divided-by 256 mode: +#if 0 // Default, really 1mS, 2mS, 500uS #define TNR_TIMER1_PERIOD_1mS ((50 * 1000) >>8) #define TNR_TIMER1_PERIOD_2mS ((50 * 1000 * 2) >>8) #define TNR_TIMER2_PERIOD_500uS ((50 * 500) >>8) +#else // pushing the envelope... 1/5 as much: +#define FACTOR 200 // 1000 is "normal" +#define TNR_TIMER1_PERIOD_1mS ((50 * FACTOR) >>8) +#define TNR_TIMER1_PERIOD_2mS ((50 * FACTOR * 2) >>8) +#define TNR_TIMER2_PERIOD_500uS ((50 * FACTOR / 2) >>8) +#endif #define TNR_TIMER1_INIT (0x88) // Enabled, free running, fclk_in/256 #define TNR_TIMER2_INIT (0xc8) // Enabled, periodic, fclk_in/256 diff --git a/packages/devs/eth/arm/edb7xxx/current/ChangeLog b/packages/devs/eth/arm/edb7xxx/current/ChangeLog --- a/packages/devs/eth/arm/edb7xxx/current/ChangeLog +++ b/packages/devs/eth/arm/edb7xxx/current/ChangeLog @@ -1,3 +1,14 @@ +2000-09-01 Hugo Tyson + + * src/if_edb7xxx.c (edb7xxx_cs8900_init): Work with new fast net + thread to do all the copying work instead of loading up DSR time. + In detail: + o New "deliver" function in the interface record. + o The DSR changed to be that new function; its arg is now the sc + pointer already, no cast needed. + o In creating the interrupt, use eth_drv_dsr (from the logical + driver) instead of cs8900_dsr (which is gone). + 2000-08-23 Gary Thomas * src/if_edb7xxx.c: Add new function which returns the interrupt diff --git a/packages/devs/eth/arm/edb7xxx/current/src/if_edb7xxx.c b/packages/devs/eth/arm/edb7xxx/current/src/if_edb7xxx.c --- a/packages/devs/eth/arm/edb7xxx/current/src/if_edb7xxx.c +++ b/packages/devs/eth/arm/edb7xxx/current/src/if_edb7xxx.c @@ -114,7 +114,8 @@ ETH_DRV_SC(edb7xxx_sc, cs8900_can_send, cs8900_send, cs8900_recv, - cs8900_int, + cs8900_deliver, // "pseudoDSR" called from fast net thread + cs8900_int, // poll function, encapsulates ISR and DSR cs8900_int_vector); NETDEVTAB_ENTRY(edb7xxx_netdev, @@ -140,11 +141,11 @@ cs8900_isr(cyg_vector_t vector, cyg_addr return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR); // Run the DSR } -// This DSR handles the ethernet [logical] processing +// The deliver function (ex-DSR) handles the ethernet [logical] processing static void -cs8900_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +cs8900_deliver(struct eth_drv_sc *sc) { - cs8900_int((struct eth_drv_sc *)data); + cs8900_int(sc); // Allow interrupts to happen again cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_EINT3); cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_EINT3); @@ -168,7 +169,7 @@ edb7xxx_cs8900_init(struct cyg_netdevtab 99, // Priority - what goes here? (cyg_addrword_t)sc, // Data item passed to interrupt handler (cyg_ISR_t *)cs8900_isr, - (cyg_DSR_t *)cs8900_dsr, + (cyg_DSR_t *)eth_drv_dsr, // The logical driver DSR &cs8900_interrupt_handle, &cs8900_interrupt); cyg_drv_interrupt_attach(cs8900_interrupt_handle); diff --git a/packages/devs/eth/cf/current/ChangeLog b/packages/devs/eth/cf/current/ChangeLog --- a/packages/devs/eth/cf/current/ChangeLog +++ b/packages/devs/eth/cf/current/ChangeLog @@ -1,3 +1,13 @@ +2000-09-01 Hugo Tyson + + * src/if_sc_lpe.c (sc_lpe_init): Work with new fast net + thread to do all the copying work instead of loading up DSR time. + In detail: + o New "deliver" function in the interface record. It's the same + function as the poll entry; sc_lpe_int(). + o In registering the interrupt handler, use eth_drv_dsr (from the + logical driver) instead of sc_lpe_int. + 2000-08-29 Gary Thomas * src/if_sc_lpe.c (sc_lpe_recv): Better handling if upper layer diff --git a/packages/devs/eth/cf/current/src/if_sc_lpe.c b/packages/devs/eth/cf/current/src/if_sc_lpe.c --- a/packages/devs/eth/cf/current/src/if_sc_lpe.c +++ b/packages/devs/eth/cf/current/src/if_sc_lpe.c @@ -92,6 +92,7 @@ ETH_DRV_SC(sc_lpe_sc, sc_lpe_can_send, sc_lpe_send, sc_lpe_recv, + sc_lpe_int, // deliver function, called from fast net thread sc_lpe_int, sc_lpe_int_vector ); @@ -266,7 +267,8 @@ sc_lpe_init(struct cyg_netdevtab_entry * cyg_thread_resume(sc_lpe_card_handler_thread_handle); // Start it // Initialize environment, setup interrupt handler - cf_register_handler(dp->slot, sc_lpe_int, sc); + // eth_drv_dsr is used to tell the fast net thread to run the deliver funcion. + cf_register_handler(dp->slot, eth_drv_dsr, sc); return false; // Device is not ready until inserted, powered up, etc. #else diff --git a/packages/devs/eth/powerpc/quicc/current/ChangeLog b/packages/devs/eth/powerpc/quicc/current/ChangeLog --- a/packages/devs/eth/powerpc/quicc/current/ChangeLog +++ b/packages/devs/eth/powerpc/quicc/current/ChangeLog @@ -1,3 +1,15 @@ +2000-09-01 Hugo Tyson + + * src/if_quicc.c (quicc_eth_init): Work with new fast net + thread to do all the copying work instead of loading up DSR time. + In detail: + o New "deliver" function in the interface record. + o The DSR changed to be that new function; its arg is now the sc + pointer already, no cast needed. + o In creating the interrupt, use eth_drv_dsr (from the logical + driver) instead of quicc_eth_dsr (which is gone). + + 2000-08-23 Gary Thomas * src/if_quicc.c: Add function to return interrupt vector used diff --git a/packages/devs/eth/powerpc/quicc/current/src/if_quicc.c b/packages/devs/eth/powerpc/quicc/current/src/if_quicc.c --- a/packages/devs/eth/powerpc/quicc/current/src/if_quicc.c +++ b/packages/devs/eth/powerpc/quicc/current/src/if_quicc.c @@ -85,6 +85,7 @@ ETH_DRV_SC(quicc_eth0_sc, quicc_eth_can_send, quicc_eth_send, quicc_eth_recv, + quicc_eth_deliver, quicc_eth_int, quicc_eth_int_vector); @@ -107,11 +108,11 @@ quicc_eth_isr(cyg_vector_t vector, cyg_a return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR); // Run the DSR } -// This DSR handles the ethernet [logical] processing +// Deliver function (ex-DSR) handles the ethernet [logical] processing static void -quicc_eth_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +quicc_eth_deliver(struct eth_drv_sc * sc) { - quicc_eth_int((struct eth_drv_sc *)data); + quicc_eth_int(sc); // Allow interrupts to happen again cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_CPM_SCC1); cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_CPM_SCC1); @@ -150,7 +151,7 @@ quicc_eth_init(struct cyg_netdevtab_entr CYGARC_SIU_PRIORITY_HIGH, (cyg_addrword_t)sc, // Data item passed to interrupt handler (cyg_ISR_t *)quicc_eth_isr, - (cyg_DSR_t *)quicc_eth_dsr, + (cyg_DSR_t *)eth_drv_dsr, &quicc_eth_interrupt_handle, &quicc_eth_interrupt); cyg_drv_interrupt_attach(quicc_eth_interrupt_handle); diff --git a/packages/devs/flash/arm/assabet/current/src/assabet_flash.c b/packages/devs/flash/arm/assabet/current/src/assabet_flash.c new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/assabet/current/src/assabet_flash.c @@ -0,0 +1,120 @@ +//========================================================================== +// +// assabet_flash.c +// +// Flash programming +// +//========================================================================== +//####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: 2000-07-26 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include +#include + +#define _FLASH_PRIVATE_ +#include + +#include "flash.h" + +#define _si(p) ((p[1]<<8)|p[0]) + +int +flash_hwr_init(void) +{ + struct FLASH_query data, *qp; + extern char flash_query, flash_query_end; + typedef int code_fun(unsigned char *); + code_fun *_flash_query; + int code_len, stat, num_regions, region_size; + + // Copy 'program' code to RAM for execution + code_len = (unsigned long)&flash_query_end - (unsigned long)&flash_query; + _flash_query = (code_fun *)flash_info.work_space; + memcpy(_flash_query, &flash_query, code_len); + HAL_DCACHE_SYNC(); // Should guarantee this code will run + HAL_ICACHE_DISABLE(); // is also required to avoid old contents + + stat = (*_flash_query)(&data); + HAL_ICACHE_ENABLE(); + + qp = &data; + if (/*(qp->manuf_code == FLASH_Intel_code) && */ + (strncmp(qp->id, "QRY", 3) == 0)) { + num_regions = _si(qp->num_regions)+1; + region_size = _si(qp->region_size)*256; + + flash_info.block_size = region_size*2; // Pairs of chips + flash_info.blocks = num_regions; + flash_info.start = (void *)0x50000000; + flash_info.end = (void *)(0x50000000+(num_regions*region_size*2)); + return FLASH_ERR_OK; + } else { + printf("Can't identify FLASH, sorry\n"); + diag_dump_buf(data, sizeof(data)); + return FLASH_ERR_HWR; + } +} + +// Map a hardware status to a package error +int +flash_hwr_map_error(int err) +{ + if (err & 0x007E007E) { + printf("Err = %x\n", err); + if (err & 0x00100010) { + return FLASH_ERR_PROGRAM; + } else + if (err & 0x00200020) { + return FLASH_ERR_ERASE; + } else + return FLASH_ERR_HWR; // FIXME + } else { + return FLASH_ERR_OK; + } +} + +// See if a range of FLASH addresses overlaps currently running code +bool +flash_code_overlaps(void *start, void *end) +{ + extern char _stext, _etext; + + return ((((unsigned long)&_stext >= (unsigned long)start) && + ((unsigned long)&_stext < (unsigned long)end)) || + (((unsigned long)&_etext >= (unsigned long)start) && + ((unsigned long)&_etext < (unsigned long)end))); +} diff --git a/packages/devs/flash/arm/assabet/current/src/flash.h b/packages/devs/flash/arm/assabet/current/src/flash.h new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/assabet/current/src/flash.h @@ -0,0 +1,88 @@ +//========================================================================== +// +// flash.h +// +// Flash programming - device constants, etc. +// +//========================================================================== +//####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: 2000-07-26 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#ifndef _FLASH_HWR_H_ +#define _FLASH_HWR_H_ + +#define FLASH_BOOT_BLOCK_SIZE 0x4000 + +#define FLASH_Intel_code 0x89 + +#define FLASH_Read_ID 0x00900090 +#define FLASH_Read_Query 0x00980098 +#define FLASH_Read_Status 0x00700070 +#define FLASH_Clear_Status 0x00500050 +#define FLASH_Status_Ready 0x00800080 +#define FLASH_Write_Buffer 0x00E800E8 +#define FLASH_Program 0x00100010 +#define FLASH_Block_Erase 0x00200020 +#define FLASH_Set_Lock 0x00600060 +#define FLASH_Clear_Locks 0x00600060 +#define FLASH_Confirm 0x00D000D0 +#define FLASH_Configure 0x00B800B8 +#define FLASH_Configure_ReadyWait 0x00000000 +#define FLASH_Configure_PulseOnErase 0x00010001 +#define FLASH_Configure_PulseOnProgram 0x00020002 +#define FLASH_Configure_PulseOnBoth 0x00030003 +#define FLASH_Reset 0x00FF00FF + +#define FLASH_BLOCK_SIZE 0x10000 + +#define FLASH_Intel_code 0x89 + +// Extended query information +struct FLASH_query { + unsigned char manuf_code; + unsigned char device_code; + unsigned char _unused0[14]; + unsigned char id[3]; // Q R Y + unsigned char _unused1[20]; + unsigned char device_size; + unsigned char device_interface[2]; + unsigned char buffer_size[2]; + unsigned char is_block_oriented; + unsigned char num_regions[2]; + unsigned char region_size[2]; +}; + +#endif // _FLASH_HWR_H_ diff --git a/packages/devs/flash/arm/assabet/current/src/flash_erase_block.c b/packages/devs/flash/arm/assabet/current/src/flash_erase_block.c new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/assabet/current/src/flash_erase_block.c @@ -0,0 +1,100 @@ +//========================================================================== +// +// flash_erase_block.c +// +// Flash programming +// +//========================================================================== +//####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: 2000-07-14 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include "flash.h" + +#include +#include +#include + +// +// CAUTION! This code must be copied to RAM before execution. Therefore, +// it must not contain any code which might be position dependent! +// + +int flash_erase_block(volatile unsigned long *block) +{ + volatile unsigned long *ROM; + unsigned long stat; + int timeout = 50000; + int cache_on; + int len; + + HAL_DCACHE_IS_ENABLED(cache_on); + if (cache_on) { + HAL_DCACHE_SYNC(); + HAL_DCACHE_DISABLE(); + } + + ROM = (volatile unsigned long *)((unsigned long)block & 0xFF800000); + + // Clear any error conditions + ROM[0] = FLASH_Clear_Status; + + // Erase block + ROM[0] = FLASH_Block_Erase; + *block = FLASH_Confirm; + timeout = 5000000; + while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) { + if (--timeout == 0) break; + } + + // Restore ROM to "normal" mode + ROM[0] = FLASH_Reset; + + // If an error was reported, see if the block erased anyway + if (stat & 0x007E007E) { + len = FLASH_BLOCK_SIZE; + while (len > 0) { + if (*block++ != 0xFFFFFFFF) break; + len -= sizeof(*block); + } + if (len == 0) stat = 0; + } + + if (cache_on) { + HAL_DCACHE_ENABLE(); + } + + return stat; +} diff --git a/packages/devs/flash/arm/assabet/current/src/flash_program_buf.c b/packages/devs/flash/arm/assabet/current/src/flash_program_buf.c new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/assabet/current/src/flash_program_buf.c @@ -0,0 +1,103 @@ +//========================================================================== +// +// flash_program_buf.c +// +// Flash programming +// +//========================================================================== +//####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: 2000-07-14 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include "flash.h" + +#include +#include +#include + +// +// CAUTION! This code must be copied to RAM before execution. Therefore, +// it must not contain any code which might be position dependent! +// + +int +flash_program_buf(volatile unsigned long *addr, unsigned long *data, int len) +{ + volatile unsigned long *ROM; + unsigned long stat = 0; + int timeout = 50000; + int cache_on; + + HAL_DCACHE_IS_ENABLED(cache_on); + if (cache_on) { + HAL_DCACHE_SYNC(); + HAL_DCACHE_DISABLE(); + } + + ROM = (volatile unsigned long *)((unsigned long)addr & 0xFF800000); + + // Clear any error conditions + ROM[0] = FLASH_Clear_Status; + + while (len > 0) { + ROM[0] = FLASH_Program; + *addr = *data; + timeout = 5000000; + while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) { + if (--timeout == 0) { + goto bad; + } + } + if (stat & 0x007E007E) { + break; + } + ROM[0] = FLASH_Reset; + if (*addr++ != *data++) { + stat = 0x99109910; + break; + } + len -= 4; + } + + // Restore ROM to "normal" mode + bad: + ROM[0] = FLASH_Reset; + + if (cache_on) { + HAL_DCACHE_ENABLE(); + } + + return stat; +} diff --git a/packages/devs/flash/arm/assabet/current/src/flash_query.c b/packages/devs/flash/arm/assabet/current/src/flash_query.c new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/assabet/current/src/flash_query.c @@ -0,0 +1,94 @@ +//========================================================================== +// +// flash_query.c +// +// Flash programming - query device +// +//========================================================================== +//####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: 2000-07-26 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include "flash.h" + +#include +#include +#include +#include CYGHWR_MEMORY_LAYOUT_H + +// +// CAUTION! This code must be copied to RAM before execution. Therefore, +// it must not contain any code which might be position dependent! +// + +#define CNT 20*1000*10 // Approx 20ms + +int +flash_query(unsigned char *data) +{ + volatile unsigned long *ROM; + int i, cnt; + int cache_on; + + HAL_DCACHE_IS_ENABLED(cache_on); + if (cache_on) { + HAL_DCACHE_SYNC(); + HAL_DCACHE_DISABLE(); + } + +#if 0 + ROM = (volatile unsigned long *)0x50000000; + + ROM[0] = FLASH_Read_ID; + for (cnt = CNT; cnt > 0; cnt--) ; + *data++ = *ROM++; // Manufacturer code + *data++ = *ROM++; // Device identifier +#endif + + ROM = (volatile unsigned long *)0x50000000; + ROM[0] = FLASH_Read_Query; + for (cnt = CNT; cnt > 0; cnt--) ; + for (i = 0; i < sizeof(struct FLASH_query); i++) { + *data++ = *ROM++; + } + + ROM[0] = FLASH_Reset; + + if (cache_on) { + HAL_DCACHE_ENABLE(); + } + + return 0; +} diff --git a/packages/ecos.db b/packages/ecos.db --- a/packages/ecos.db +++ b/packages/ecos.db @@ -1368,7 +1368,6 @@ target tx39_sim { use any of the eCos device drivers when the simulator is running in this mode." } - target vrc4373 { alias { "NEC VRC4373 board" } packages { CYGPKG_HAL_MIPS diff --git a/packages/hal/common/current/ChangeLog b/packages/hal/common/current/ChangeLog --- a/packages/hal/common/current/ChangeLog +++ b/packages/hal/common/current/ChangeLog @@ -1,3 +1,21 @@ +2000-09-04 Jonathan Larmour + + * include/hal_tables.h (CYG_HAL_TABLE_END): Use CYGARC_P2ALIGNMENT + to align label + (CYG_HAL_TABLE_TYPE): Define + +2000-09-01 Jonathan Larmour + + * src/hal_stub.c (__build_t_packet): Ensure sign extension applies + in the higher word, not the lower. + (__build_t_packet): Don't need to conditionalize on + CYGARC_REGSIZE_DIFFERS_FROM_TARGET_REGISTER_T as there should be no + problems with the current code. + * src/generic-stub.c (stub_format_registers): Likewise + + * include/hal_if.h (CYGACC_COMM_IF_CONTROL): Remove warning due to + unnecessary use of cpp paste operator + 2000-08-28 Gary Thomas * src/hal_if.c: diff --git a/packages/hal/common/current/include/hal_if.h b/packages/hal/common/current/include/hal_if.h --- a/packages/hal/common/current/include/hal_if.h +++ b/packages/hal/common/current/include/hal_if.h @@ -168,7 +168,7 @@ typedef cyg_uint8 (*__comm_if_getc_t)(vo typedef int (*__comm_if_control_t)(void *__ch_data, __comm_control_cmd_t __func, ...); #define CYGACC_COMM_IF_CONTROL(_t_, args...) \ - ((__comm_if_control_t)(((_t_))[CYGNUM_COMM_IF_CONTROL]))(CYGACC_COMM_IF_CH_DATA(_t_), ## args) + ((__comm_if_control_t)(((_t_))[CYGNUM_COMM_IF_CONTROL]))(CYGACC_COMM_IF_CH_DATA(_t_), args) #define CYGACC_COMM_IF_CONTROL_SET(_t_, _x_) \ (_t_)[CYGNUM_COMM_IF_CONTROL]=(CYG_ADDRWORD)(_x_) diff --git a/packages/hal/common/current/include/hal_tables.h b/packages/hal/common/current/include/hal_tables.h --- a/packages/hal/common/current/include/hal_tables.h +++ b/packages/hal/common/current/include/hal_tables.h @@ -35,14 +35,13 @@ //#####DESCRIPTIONBEGIN#### // // Author(s): nickg -// Date: 1999-02-24 -// Purpose: Driver API -// Description: This file defines the API used by device drivers to access -// system services. When the kernel is present it maps directly -// to the Kernel C API. When the kernel is absent, it is provided -// by a set of HAL functions. +// Date: 2000-09-04 +// Purpose: Provide HAL tables +// Description: This file defines a mechanism to include "tables" of objects +// that are always included in the image no matter what, and are +// constrained between labels. // -// Usage: #include +// Usage: #include // //####DESCRIPTIONEND#### // @@ -59,40 +58,49 @@ #define __xstring(_x) __string(_x) #ifndef CYG_HAL_TABLE_BEGIN -#define CYG_HAL_TABLE_BEGIN( _label, _name ) \ -__asm__(".section \"" __string(.ecos.table.##_name##.begin) "\",\"aw\"\n" \ - ".globl " __xstring(CYG_LABEL_DEFN(_label)) "\n" \ - ".type " __xstring(CYG_LABEL_DEFN(_label)) ",@object\n" \ - ".p2align 2\n" \ -__xstring(CYG_LABEL_DEFN(_label)) ":\n" \ - ".previous\n" \ +#define CYG_HAL_TABLE_BEGIN( _label, _name ) \ +__asm__(".section \"" __string(.ecos.table.##_name##.begin) "\",\"aw\"\n" \ + ".globl " __xstring(CYG_LABEL_DEFN(_label)) "\n" \ + ".type " __xstring(CYG_LABEL_DEFN(_label)) ",@object\n" \ + ".p2align " __xstring(CYGARC_P2ALIGNMENT) "\n" \ +__xstring(CYG_LABEL_DEFN(_label)) ":\n" \ + ".previous\n" \ ) #endif #ifndef CYG_HAL_TABLE_END -#define CYG_HAL_TABLE_END( _label, _name ) \ -__asm__(".section \"" __string(.ecos.table.##_name##.finish) "\",\"aw\"\n" \ - ".globl " __xstring(CYG_LABEL_DEFN(_label)) "\n" \ - ".type " __xstring(CYG_LABEL_DEFN(_label)) ",@object\n" \ - ".p2align 2\n" \ -__xstring(CYG_LABEL_DEFN(_label)) ":\n" \ - ".previous\n" \ +#define CYG_HAL_TABLE_END( _label, _name ) \ +__asm__(".section \"" __string(.ecos.table.##_name##.finish) "\",\"aw\"\n" \ + ".globl " __xstring(CYG_LABEL_DEFN(_label)) "\n" \ + ".type " __xstring(CYG_LABEL_DEFN(_label)) ",@object\n" \ + ".p2align " __xstring(CYGARC_P2ALIGNMENT) "\n" \ +__xstring(CYG_LABEL_DEFN(_label)) ":\n" \ + ".previous\n" \ ) #endif +// This macro must be applied to any types whose objects are to be placed in +// tables +#ifndef CYG_HAL_TABLE_TYPE +#define CYG_HAL_TABLE_TYPE CYGBLD_ATTRIB_ALIGN( CYGARC_ALIGNMENT ) +#endif + #ifndef CYG_HAL_TABLE_EXTRA #define CYG_HAL_TABLE_EXTRA( _name ) \ - CYGBLD_ATTRIB_SECTION(.ecos.table.##_name##.extra) + CYGBLD_ATTRIB_SECTION(.ecos.table.##_name##.extra) \ + CYGBLD_ATTRIB_ALIGN( CYGARC_ALIGNMENT ) #endif #ifndef CYG_HAL_TABLE_ENTRY #define CYG_HAL_TABLE_ENTRY( _name ) \ - CYGBLD_ATTRIB_SECTION(.ecos.table.##_name##.data) + CYGBLD_ATTRIB_SECTION(.ecos.table.##_name##.data) \ + CYGBLD_ATTRIB_ALIGN( CYGARC_ALIGNMENT ) #endif #ifndef CYG_HAL_TABLE_QUALIFIED_ENTRY #define CYG_HAL_TABLE_QUALIFIED_ENTRY( _name, _qual ) \ - CYGBLD_ATTRIB_SECTION(.ecos.table.##_name##.data.##_qual) + CYGBLD_ATTRIB_SECTION(.ecos.table.##_name##.data.##_qual) \ + CYGBLD_ATTRIB_ALIGN( CYGARC_ALIGNMENT ) #endif /*------------------------------------------------------------------------*/ diff --git a/packages/hal/common/current/src/generic-stub.c b/packages/hal/common/current/src/generic-stub.c --- a/packages/hal/common/current/src/generic-stub.c +++ b/packages/hal/common/current/src/generic-stub.c @@ -909,7 +909,7 @@ stub_format_registers(char *ptr) int x; char extend_val = 0; -#if defined(CYGARC_REGSIZE_DIFFERS_FROM_TARGET_REGISTER_T) && defined(CYGARC_SIGN_EXTEND_REGISTERS) +#ifdef CYGARC_SIGN_EXTEND_REGISTERS { unsigned long bits_in_addr = (sizeof(addr) << 3); // ie Size in bytes * 8 target_register_t sign_bit_mask = (1 << (bits_in_addr - 1)); diff --git a/packages/hal/common/current/src/hal_stub.c b/packages/hal/common/current/src/hal_stub.c --- a/packages/hal/common/current/src/hal_stub.c +++ b/packages/hal/common/current/src/hal_stub.c @@ -656,8 +656,6 @@ void *ptr++ = __tohex (PC); *ptr++ = ':'; addr = get_register (PC); -#ifdef CYGARC_REGSIZE_DIFFERS_FROM_TARGET_REGISTER_T - ptr = __mem2hex((char *)&addr, ptr, sizeof(addr), 0); if (sizeof(addr) < REGSIZE(PC)) { // GDB is expecting REGSIZE(PC) number of bytes. @@ -674,17 +672,13 @@ void #endif ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(PC) - sizeof(addr), 0); } -#else - ptr = __mem2hex((char *)&addr, ptr, REGSIZE(PC), 0); -#endif + ptr = __mem2hex((char *)&addr, ptr, sizeof(addr), 0); *ptr++ = ';'; *ptr++ = __tohex (SP >> 4); *ptr++ = __tohex (SP); *ptr++ = ':'; addr = (target_register_t) get_register (SP); -#ifdef CYGARC_REGSIZE_DIFFERS_FROM_TARGET_REGISTER_T - ptr = __mem2hex((char *)&addr, ptr, sizeof(addr), 0); if (sizeof(addr) < REGSIZE(SP)) { // GDB is expecting REGSIZE(SP) number of bytes. @@ -701,9 +695,7 @@ void #endif ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(SP) - sizeof(addr), 0); } -#else - ptr = __mem2hex((char *)&addr, ptr, REGSIZE(SP), 0); -#endif + ptr = __mem2hex((char *)&addr, ptr, sizeof(addr), 0); *ptr++ = ';'; *ptr++ = 0; diff --git a/packages/hal/mips/arch/current/ChangeLog b/packages/hal/mips/arch/current/ChangeLog --- a/packages/hal/mips/arch/current/ChangeLog +++ b/packages/hal/mips/arch/current/ChangeLog @@ -1,7 +1,19 @@ +2000-09-01 Jonathan Larmour + + * include/mips-stub.h: No longer need to define + CYGARC_REGSIZE_DIFFERS_FROM_TARGET_REGISTER_T + (CYGARC_SIGN_EXTEND_REGISTERS): + + * include/mips-stub.h: Change vr4300 register sizes to use 32-bit + target_register_t, and tell the generic stub to use sign extension. + * include/hal_cache.h (_HAL_ASM_SET_MIPS_ISA): Don't use pasting + when it doesn't result in a preprocessing token. Just use string + concatenation. + 2000-07-21 Drew Moseley - * src/vectors.S: Only jump uncached to _start if CYGARC_START_FUNC_UNCACHED - is defined. + * src/vectors.S: Only jump uncached to _start if + CYGARC_START_FUNC_UNCACHED is defined. 2000-07-14 Drew Moseley diff --git a/packages/hal/mips/arch/current/include/hal_cache.h b/packages/hal/mips/arch/current/include/hal_cache.h --- a/packages/hal/mips/arch/current/include/hal_cache.h +++ b/packages/hal/mips/arch/current/include/hal_cache.h @@ -60,7 +60,7 @@ #define _hal_asm_mips_cpp_stringize( _x_ ) #_x_ #define _HAL_ASM_SET_MIPS_ISA( _isal_ ) asm volatile ( \ - ".set mips" ## _hal_asm_mips_cpp_stringize(_isal_) ) + ".set mips" _hal_asm_mips_cpp_stringize(_isal_) ) //============================================================================= diff --git a/packages/hal/mips/arch/current/include/mips-stub.h b/packages/hal/mips/arch/current/include/mips-stub.h --- a/packages/hal/mips/arch/current/include/mips-stub.h +++ b/packages/hal/mips/arch/current/include/mips-stub.h @@ -57,8 +57,11 @@ extern "C" { #define REGSIZE(X) 8 typedef unsigned long long target_register_t; #elif defined(CYGPKG_HAL_MIPS_VR4300) + // Even though we are only working with 32 bit registers, GDB expects 64 bits #define REGSIZE(X) 8 - typedef unsigned long long target_register_t; + typedef unsigned long target_register_t; + // We need to sign-extend the registers so GDB doesn't get confused. + #define CYGARC_SIGN_EXTEND_REGISTERS #else #define REGSIZE(X) 4 typedef unsigned long target_register_t; diff --git a/packages/hal/mips/vr4300/current/ChangeLog b/packages/hal/mips/vr4300/current/ChangeLog --- a/packages/hal/mips/vr4300/current/ChangeLog +++ b/packages/hal/mips/vr4300/current/ChangeLog @@ -1,3 +1,8 @@ +2000-09-01 Jonathan Larmour + + * include/var_arch.h (CYG_HAL_GDB_REG): vr4300 GDB stubs now use + 32-bits internally to represent registers + 2000-06-21 Nick Garnett * src/mips_vr4300.ld: diff --git a/packages/hal/mips/vr4300/current/include/var_arch.h b/packages/hal/mips/vr4300/current/include/var_arch.h --- a/packages/hal/mips/vr4300/current/include/var_arch.h +++ b/packages/hal/mips/vr4300/current/include/var_arch.h @@ -50,11 +50,12 @@ #include // ------------------------------------------------------------------------- -// Because the 4300 is really a 64 bit CPU, GDB expects all registers -// to be 64 bits wide. We redefine the type used to store GDB -// registers here: +// Although the VR4300 is really a 64 bit CPU, we have defined +// target_register_t elsewhere to be 32-bits because we only support +// 32-bit mode. Registers will still be sent to GDB as 64-bit, but that's +// not relevant for CYG_HAL_GDB_REG. -#define CYG_HAL_GDB_REG CYG_WORD64 +#define CYG_HAL_GDB_REG CYG_WORD32 //-------------------------------------------------------------------------- #endif // CYGONCE_HAL_VAR_ARCH_H diff --git a/packages/hal/mn10300/arch/current/ChangeLog b/packages/hal/mn10300/arch/current/ChangeLog --- a/packages/hal/mn10300/arch/current/ChangeLog +++ b/packages/hal/mn10300/arch/current/ChangeLog @@ -1,3 +1,8 @@ +2000-09-04 Jonathan Larmour + + * include/basetype.h (CYGARC_ALIGNMENT): mn10300 has 4 byte alignment + (CYGARC_P2ALIGNMENT): Likewise + 2000-08-29 Jonathan Larmour * src/vectors.S (__default_nmi_vsr): Fix quoting in comment problem diff --git a/packages/hal/mn10300/arch/current/include/basetype.h b/packages/hal/mn10300/arch/current/include/basetype.h --- a/packages/hal/mn10300/arch/current/include/basetype.h +++ b/packages/hal/mn10300/arch/current/include/basetype.h @@ -56,6 +56,12 @@ #define CYG_LABEL_DEFN(_name_) _##_name_ //----------------------------------------------------------------------------- +// MN10300 only requires four byte alignment + +#define CYGARC_ALIGNMENT 4 +#define CYGARC_P2ALIGNMENT 2 + +//----------------------------------------------------------------------------- // Define the standard variable sizes // The MN10300 architecture uses the default definitions of the base types, diff --git a/packages/hal/powerpc/quicc/current/ChangeLog b/packages/hal/powerpc/quicc/current/ChangeLog --- a/packages/hal/powerpc/quicc/current/ChangeLog +++ b/packages/hal/powerpc/quicc/current/ChangeLog @@ -1,3 +1,8 @@ +2000-08-30 Jesper Skov + + * src/quicc_smc1.c (cyg_hal_plf_serial_init_channel): Move all + init code to init_channel. + 2000-06-30 Jesper Skov * src/quicc_smc1.c: calling i/f macro changes. diff --git a/packages/hal/powerpc/quicc/current/src/quicc_smc1.c b/packages/hal/powerpc/quicc/current/src/quicc_smc1.c --- a/packages/hal/powerpc/quicc/current/src/quicc_smc1.c +++ b/packages/hal/powerpc/quicc/current/src/quicc_smc1.c @@ -93,6 +93,7 @@ void cyg_hal_plf_serial_init_channel(void) { EPPC *eppc; + int i; volatile struct smc_uart_pram *uart_pram; struct cp_bufdesc *txbd, *rxbd; @@ -102,6 +103,12 @@ cyg_hal_plf_serial_init_channel(void) eppc = eppc_base(); + /* + * Reset communications processor + */ + eppc->cp_cr = QUICC_CPM_CR_RESET | QUICC_CPM_CR_BUSY; + for (i = 0; i < 100000; i++); + /* SMC1 Uart parameter ram */ uart_pram = &eppc->pram[2].scc.pothers.smc_modem.psmc.u; @@ -460,18 +467,11 @@ 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); volatile EPPC *eppc = eppc_base(); - int i; static int init = 0; // It's wrong to do this more than once if (init) return; init++; - /* - * Reset communications processor - */ - eppc->cp_cr = QUICC_CPM_CR_RESET | QUICC_CPM_CR_BUSY; - for (i = 0; i < 100000; i++); - cyg_hal_plf_serial_init_channel(); // Setup procs in the vector table diff --git a/packages/hal/sh/arch/current/ChangeLog b/packages/hal/sh/arch/current/ChangeLog --- a/packages/hal/sh/arch/current/ChangeLog +++ b/packages/hal/sh/arch/current/ChangeLog @@ -1,3 +1,12 @@ +2000-08-31 Jesper Skov + + * include/mod_7709a.h: Added UBC definition. + * include/mod_7708.h: Same. + * include/mod_7707a.h: Same. + * include/sh_regs.h: Extra UBC definitions. + * src/sh_stub.c: If core supports UBC, use it for + single-stepping. + 2000-07-20 Jesper Skov * src/sh_stub.c (__single_step): Skip trap instructions. diff --git a/packages/hal/sh/arch/current/include/mod_7707a.h b/packages/hal/sh/arch/current/include/mod_7707a.h --- a/packages/hal/sh/arch/current/include/mod_7707a.h +++ b/packages/hal/sh/arch/current/include/mod_7707a.h @@ -54,6 +54,7 @@ #define CYGARC_SH_MOD_IRDA #define CYGARC_SH_MOD_SCIF #define CYGARC_SH_MOD_PFC +#define CYGARC_SH_MOD_UBC //----------------------------------------------------------------------------- // Extra details for Cache Module (CAC) diff --git a/packages/hal/sh/arch/current/include/mod_7708.h b/packages/hal/sh/arch/current/include/mod_7708.h --- a/packages/hal/sh/arch/current/include/mod_7708.h +++ b/packages/hal/sh/arch/current/include/mod_7708.h @@ -49,6 +49,7 @@ // Modules provided by the CPU #define CYGARC_SH_MOD_SCI_V2 +#define CYGARC_SH_MOD_UBC //----------------------------------------------------------------------------- diff --git a/packages/hal/sh/arch/current/include/mod_7709a.h b/packages/hal/sh/arch/current/include/mod_7709a.h --- a/packages/hal/sh/arch/current/include/mod_7709a.h +++ b/packages/hal/sh/arch/current/include/mod_7709a.h @@ -53,6 +53,7 @@ #define CYGARC_SH_MOD_IRDA #define CYGARC_SH_MOD_SCIF #define CYGARC_SH_MOD_PFC +#define CYGARC_SH_MOD_UBC //----------------------------------------------------------------------------- // Extra details for Cache Module (CAC) diff --git a/packages/hal/sh/arch/current/include/sh_regs.h b/packages/hal/sh/arch/current/include/sh_regs.h --- a/packages/hal/sh/arch/current/include/sh_regs.h +++ b/packages/hal/sh/arch/current/include/sh_regs.h @@ -247,11 +247,26 @@ #define CYGARC_REG_BRCR_CMFA 0x8000 // condition match flag A #define CYGARC_REG_BRCR_CMFB 0x4000 // condition match flag B -#define CYGARC_REG_BRCR_PCBA 0x0400 // PC break select A +#define CYGARC_REG_BRCR_PCBA 0x0400 // post execute channel A #define CYGARC_REG_BRCR_DBEB 0x0080 // data break enable B -#define CYGARC_REG_BRCR_PCBB 0x0040 // PC break select B +#define CYGARC_REG_BRCR_PCBB 0x0040 // post execute channel B #define CYGARC_REG_BRCR_SEQ 0x0008 // sequence condition select +#define CYGARC_REG_BAMRA_BASMA 0x04 // BASRA masked +#define CYGARC_REG_BAMRA_BARA_UNMASKED 0x00 // BARA not masked +#define CYGARC_REG_BAMRA_BARA_10BIT 0x01 // Lowest 10 bit masked +#define CYGARC_REG_BAMRA_BARA_12BIT 0x02 // Lowest 12 bit masked +#define CYGARC_REG_BAMRA_BARA_MASKED 0x03 // All bits masked + +#define CYGARC_REG_BBRA_DFETCH 0x0020 // Break on DFETCH +#define CYGARC_REG_BBRA_IFETCH 0x0010 // Break on IFETCH +#define CYGARC_REG_BBRA_WRITE 0x0008 // Break on WRITE +#define CYGARC_REG_BBRA_READ 0x0004 // Break on READ +#define CYGARC_REG_BBRA_SIZE_LONG 0x0003 // Break on long access +#define CYGARC_REG_BBRA_SIZE_WORD 0x0002 // Break on word access +#define CYGARC_REG_BBRA_SIZE_BYTE 0x0001 // Break on byte access +#define CYGARC_REG_BBRA_SIZE_ANY 0x0000 // Break on any size + //++++++ Module CPG ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/packages/hal/sh/arch/current/src/sh_stub.c b/packages/hal/sh/arch/current/src/sh_stub.c --- a/packages/hal/sh/arch/current/src/sh_stub.c +++ b/packages/hal/sh/arch/current/src/sh_stub.c @@ -112,6 +112,44 @@ set_pc(target_register_t pc) put_register(PC, pc); } +#ifdef CYGARC_SH_MOD_UBC + +// This implementation of the single-stepper relies on the User Break +// Controller which may not be available on all cores. + +// Note: This should be enhanced to coorperate with either two regular +// breakpoints or watchpoints. Requires GDB to be aware of the stub's +// ability though, so for now just use channel A without further +// considerations. + +/* Set things up so that the next user resume will execute one instruction. + This may be done by setting breakpoints or setting a single step flag + in the saved user registers, for example. */ + +void __single_step (void) +{ + // The address of the instruction to execute. + HAL_WRITE_UINT32(CYGARC_REG_BARA, get_register(PC)); + // Match entire address. + HAL_WRITE_UINT8(CYGARC_REG_BAMRA, CYGARC_REG_BAMRA_BARA_UNMASKED); + // Stop after instruction at matching address has executed. + HAL_WRITE_UINT16(CYGARC_REG_BRCR, CYGARC_REG_BRCR_PCBA); + // Stop on IFETCH/READ + HAL_WRITE_UINT16(CYGARC_REG_BBRA, + CYGARC_REG_BBRA_IFETCH|CYGARC_REG_BBRA_READ); +} + +/* Clear the single-step state. */ + +void __clear_single_step (void) +{ + // Don't stop on any condition + HAL_WRITE_UINT16(CYGARC_REG_BBRA, 0); + // Clear status flags + HAL_WRITE_UINT16(CYGARC_REG_BRCR, 0); +} + +#else // CYGARC_SH_MOD_UBC /*---------------------------------------------------------------------- * Single-step support, copied from gdb/sh-stub.c, written by Ben Lee @@ -248,6 +286,8 @@ void __clear_single_step (void) stepped = 0; } +#endif // CYGARC_SH_MOD_UBC + void __install_breakpoints (void) { diff --git a/packages/infra/current/ChangeLog b/packages/infra/current/ChangeLog --- a/packages/infra/current/ChangeLog +++ b/packages/infra/current/ChangeLog @@ -1,3 +1,11 @@ +2000-09-04 Jonathan Larmour + + * include/cyg_type.h (CYGARC_ALIGNMENT): Add default of 8 + (CYGARC_P2ALIGNMENT): Add corresponding default of 3 + (CYGBLD_ATTRIB_ALIGN): Define to allow alignment + * include/cyg_type.inc: As above for CYGARC_ALIGNMENT and + CYGARC_P2ALIGNMENT + 2000-07-25 Jonathan Larmour * include/cyg_type.inc: Create. Used for the equivalent stuff of diff --git a/packages/infra/current/include/cyg_type.h b/packages/infra/current/include/cyg_type.h --- a/packages/infra/current/include/cyg_type.h +++ b/packages/infra/current/include/cyg_type.h @@ -123,6 +123,18 @@ #endif // ------------------------------------------------------------------------- +// Provide a default architecture alignment +// This may be overridden in basetype.h if necessary. + +#ifndef CYGARC_ALIGNMENT +# define CYGARC_ALIGNMENT 8 +#endif +// And corresponding power of two alignment +#ifndef CYGARC_P2ALIGNMENT +# define CYGARC_P2ALIGNMENT 3 +#endif + +// ------------------------------------------------------------------------- // The obvious few that compilers may define for you. // But in case they don't: @@ -291,6 +303,9 @@ typedef cyg_haladdrword CYG_ADDRWORD; // Assign a defined variable to a specific section # define CYGBLD_ATTRIB_SECTION(__sect__) __attribute__((section (#__sect__))) +// Give a type or object explicit minimum alignment +# define CYGBLD_ATTRIB_ALIGN(__align__) __attribute__((aligned(__align__))) + #else // non-GNU # define CYGBLD_ATTRIB_CONSTRUCTOR @@ -308,6 +323,8 @@ typedef cyg_haladdrword CYG_ADDRWORD; # define CYGBLD_ATTRIB_CONST +# define CYGBLD_ATTRIB_ALIGN(__align__) !!!-- Alignment alias not defined --!!! + #endif // How to define weak aliases. Currently this is simply a mixture of the diff --git a/packages/infra/current/include/cyg_type.inc b/packages/infra/current/include/cyg_type.inc --- a/packages/infra/current/include/cyg_type.inc +++ b/packages/infra/current/include/cyg_type.inc @@ -47,10 +47,32 @@ #include +// ------------------------------------------------------------------------- +// Label name macros. Some toolsets generate labels with initial +// underscores and others don't. CYG_LABEL_NAME should be used on +// labels in C/C++ code that are defined in assembly code or linker +// scripts. CYG_LABEL_DEFN is for use in assembly code and linker +// scripts where we need to manufacture labels that can be used from +// C/C++. +// These are default implementations that should work for most targets. +// They may be overridden in basetype.h if necessary. + #ifndef CYG_LABEL_DEFN # define CYG_LABEL_DEFN(_label) _label #endif +// ------------------------------------------------------------------------- +// Provide a default architecture alignment. +// This may be overridden in basetype.h if necessary. + +#ifndef CYGARC_ALIGNMENT +# define CYGARC_ALIGNMENT 8 +#endif +// And corresponding power of two alignment +#ifndef CYGARC_P2ALIGNMENT +# define CYGARC_P2ALIGNMENT 3 +#endif + #endif /* CYGONCE_INFRA_CYG_TYPE_INC */ // EOF cyg_type.inc diff --git a/packages/io/common/current/ChangeLog b/packages/io/common/current/ChangeLog --- a/packages/io/common/current/ChangeLog +++ b/packages/io/common/current/ChangeLog @@ -1,3 +1,7 @@ +2000-09-04 Jonathan Larmour + + * include/devtab.h (cyg_devtab_entry_t): Apply CYG_HAL_TABLE_TYPE + 2000-08-01 Jonathan Larmour * include/config_keys.h: diff --git a/packages/io/common/current/include/devtab.h b/packages/io/common/current/include/devtab.h --- a/packages/io/common/current/include/devtab.h +++ b/packages/io/common/current/include/devtab.h @@ -132,7 +132,7 @@ typedef struct cyg_devtab_entry { const char *name); void *priv; unsigned long status; -} cyg_devtab_entry_t; +} cyg_devtab_entry_t CYG_HAL_TABLE_TYPE; #define CYG_DEVTAB_STATUS_AVAIL 0x0001 #define CYG_DEVTAB_STATUS_CHAR 0x1000 diff --git a/packages/io/eth/current/ChangeLog b/packages/io/eth/current/ChangeLog --- a/packages/io/eth/current/ChangeLog +++ b/packages/io/eth/current/ChangeLog @@ -1,3 +1,40 @@ +2000-09-01 Hugo Tyson + + * src/stand_alone/eth_drv.c (eth_drv_dsr): New function, never + called but maybe referenced in stand_alone context, which lets + redboot work in the new world. + +2000-09-01 Hugo Tyson + + * OVERVIEW: This is part of the change to the network stack to + greatly reduce latencies both of (other) DSRs and of thread + scheduling. All the work that the network stack *and* individual + ether drivers used to do in DSRs (including alarm callbacks and + data copies to/from the device memory) is moved into a "fast + network thread" instead. It calls a device's "deliver" function + to do the work that was previously in the DSR. This is a separate + thread so that it can be set higher priority than application + threads in order to minimize packet loss (depending on the + driver), if required (the application threads presumed to be + higher priority in turn than the network thread). A crucial + consequence of this is that we are no longer locking against DSRs, + so a plain mutex can be used rather than the global scheduler + lock, thus simplifying all the splfoo/splx() style functions. + + These changes WILL BREAK individual device drivers until they are + updated AND the standalone logical ether driver in this component, + until it is updated also. + + * include/eth_drv.h (ETH_DRV_SC): Add "deliver" entry to struct + eth_hwr_funs interface record; declare available DSR and flag for + "needs delivery" in SC status field. + + * src/net/eth_drv.c (eth_drv_run_deliveries): New function, + performs callbacks to deliver funcs for all devs that want it. + (eth_drv_dsr): New function, sets flag in sc and calls up to net + stack to schedule the fast network thread. + (eth_drv_send): No need to lock scheduler here. + 2000-08-29 Gary Thomas * src/stand_alone/eth_drv.c: Use null buffer, (char *)0, diff --git a/packages/io/eth/current/include/eth_drv.h b/packages/io/eth/current/include/eth_drv.h --- a/packages/io/eth/current/include/eth_drv.h +++ b/packages/io/eth/current/include/eth_drv.h @@ -127,6 +127,9 @@ struct eth_hwr_funs { void (*recv)(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len); + // Deliver data to/from device from/to stack memory space + // (moves lots of memcpy()s out of DSRs into thread) + void (*deliver)(struct eth_drv_sc *sc); // Poll for interrupts/device service void (*poll)(struct eth_drv_sc *sc); // Get interrupt information from hardware driver @@ -149,13 +152,14 @@ struct eth_drv_sc { struct arpcom sc_arpcom; /* ethernet common */ }; -#define ETH_DRV_SC(sc,priv,name,start,stop,control,can_send,send,recv,poll,int_vector) \ +#define ETH_DRV_SC(sc,priv,name,start,stop,control,can_send,send,recv,deliver,poll,int_vector) \ static void start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags); \ static void stop(struct eth_drv_sc *sc); \ static int control(struct eth_drv_sc *sc, unsigned long key, void *data, int data_length); \ static int can_send(struct eth_drv_sc *sc); \ static void send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int total, unsigned long key); \ static void recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len); \ +static void deliver(struct eth_drv_sc *sc); \ static void poll(struct eth_drv_sc *sc); \ static int int_vector(struct eth_drv_sc *sc); \ static struct eth_hwr_funs sc##_funs = { \ @@ -165,14 +169,23 @@ static struct eth_hwr_funs sc##_funs = { can_send, \ send, \ recv, \ + deliver, \ poll, \ int_vector, \ ð_drv_funs, \ (struct eth_drv_funs *)0 }; \ struct eth_drv_sc sc = {&sc##_funs, priv, name}; -#define ETH_DRV_STATE_ACTIVE 0x0001 -#define ETH_DRV_STATE_DEBUG 0x1000 +#define ETH_DRV_STATE_ACTIVE 0x0001 +#define ETH_DRV_NEEDS_DELIVERY 0x0002 +#define ETH_DRV_STATE_DEBUG 0x1000 + +// Register this as your DSR within your driver: it will cause your deliver +// routine to be called from the network thread. The "data" parameter +// *must* be your own "struct eth_drv_sc *sc" pointer. +extern void eth_drv_dsr(cyg_vector_t vector, + cyg_ucount32 count, + cyg_addrword_t data); extern struct eth_drv_funs eth_drv_funs; diff --git a/packages/io/eth/current/src/net/eth_drv.c b/packages/io/eth/current/src/net/eth_drv.c --- a/packages/io/eth/current/src/net/eth_drv.c +++ b/packages/io/eth/current/src/net/eth_drv.c @@ -83,6 +83,7 @@ #include #include #include +#include static int eth_drv_ioctl(struct ifnet *, u_long, caddr_t); static void eth_drv_send(struct ifnet *); @@ -93,7 +94,7 @@ extern int net_debug; // FIXME static void eth_drv_init(struct eth_drv_sc *sc, unsigned char *enaddr); static void eth_drv_recv(struct eth_drv_sc *sc, int total_len); -static void eth_drv_tx_done(struct eth_drv_sc *sc, unsigned long key, int status); +static void eth_drv_tx_done(struct eth_drv_sc *sc, CYG_ADDRESS key, int status); struct eth_drv_funs eth_drv_funs = {eth_drv_init, eth_drv_recv, eth_drv_tx_done}; @@ -295,10 +296,11 @@ eth_drv_send(struct ifnet *ifp) int len, total_len; unsigned char *data; - cyg_scheduler_lock(); // Prevent DSRs from running + // This is now only called from network threads, so no guarding is + // required; locking is in place via the splfoo() mechanism already. + if ((ifp->if_flags & IFF_RUNNING) != IFF_RUNNING) { - cyg_scheduler_unlock(); - return; + return; } while ((sc->funs->can_send)(sc) > 0) { @@ -346,8 +348,6 @@ eth_drv_send(struct ifnet *ifp) if ( sg_len ) (sc->funs->send)(sc, sg_list, sg_len, total_len, (unsigned long)m0); } - - cyg_scheduler_unlock(); // Allow DSRs to run } // @@ -357,7 +357,7 @@ eth_drv_send(struct ifnet *ifp) static struct mbuf *mbuf_key; static void -eth_drv_tx_done(struct eth_drv_sc *sc, unsigned long key, int status) +eth_drv_tx_done(struct eth_drv_sc *sc, CYG_ADDRESS key, int status) { struct ifnet *ifp = &sc->sc_arpcom.ac_if; struct mbuf *m0 = (struct mbuf *)key; @@ -495,6 +495,45 @@ eth_drv_recv(struct eth_drv_sc *sc, int ether_input(ifp, eh, m); } + +// ------------------------------------------------------------------------ +// DSR to schedule network delivery thread + +extern void ecos_synch_eth_drv_dsr(void); // from ecos/timeout.c in net stack + +void +eth_drv_dsr(cyg_vector_t vector, + cyg_ucount32 count, + cyg_addrword_t data) +{ + struct eth_drv_sc *sc = (struct eth_drv_sc *)data; + + sc->state |= ETH_DRV_NEEDS_DELIVERY; + + ecos_synch_eth_drv_dsr(); // [request] run delivery function for this dev +} + +// This is called from the delivery thread, to do just that: +void eth_drv_run_deliveries( void ) +{ + cyg_netdevtab_entry_t *t; + for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) { + struct eth_drv_sc *sc = (struct eth_drv_sc *)t->device_instance; + int state = sc->state; + sc->state &=~ETH_DRV_NEEDS_DELIVERY; + if ( ETH_DRV_NEEDS_DELIVERY & state ) { + (*sc->funs->deliver)(sc); + } + } +} + + +// ------------------------------------------------------------------------ + + + + + #ifdef CYGPKG_IO_PCMCIA // Lookup a 'netdev' entry, assuming that it is an ethernet device. cyg_netdevtab_entry_t * diff --git a/packages/io/eth/current/src/stand_alone/eth_drv.c b/packages/io/eth/current/src/stand_alone/eth_drv.c --- a/packages/io/eth/current/src/stand_alone/eth_drv.c +++ b/packages/io/eth/current/src/stand_alone/eth_drv.c @@ -433,3 +433,15 @@ eth_drv_int_vector(void) struct eth_drv_sc *sc = __local_enet_sc; return sc->funs->int_vector(sc); } + + +void eth_drv_dsr(cyg_vector_t vector, + cyg_ucount32 count, + cyg_addrword_t data) +{ + printf( "eth_drv_dsr should not be called: vector %d, data %x\n", + vector, data ); +} + + +// EOF src/stand_alone/eth_drv.c diff --git a/packages/io/fileio/current/ChangeLog b/packages/io/fileio/current/ChangeLog --- a/packages/io/fileio/current/ChangeLog +++ b/packages/io/fileio/current/ChangeLog @@ -1,3 +1,9 @@ +2000-09-04 Jonathan Larmour + + * include/sockio.h (struct cyg_nstab_entry): Apply CYG_HAL_TABLE_TYPE + * include/fileio.h (struct cyg_mtab_entry): Ditto + (FSTAB_ENTRY): Ditto + 2000-08-31 Nick Garnett * src/select.cxx (select): Added scheduler unlock in timeout diff --git a/packages/io/fileio/current/include/fileio.h b/packages/io/fileio/current/include/fileio.h --- a/packages/io/fileio/current/include/fileio.h +++ b/packages/io/fileio/current/include/fileio.h @@ -138,7 +138,7 @@ struct cyg_fstab_entry cyg_fsop_stat *stat; cyg_fsop_getinfo *getinfo; cyg_fsop_setinfo *setinfo; -}; +} CYG_HAL_TABLE_TYPE; //----------------------------------------------------------------------------- // Keys for getinfo() and setinfo() @@ -192,7 +192,7 @@ struct cyg_mtab_entry cyg_bool valid; // Valid entry? cyg_fstab_entry *fs; // pointer to fstab entry cyg_dir root; // root directory pointer -}; +} CYG_HAL_TABLE_TYPE; // This macro defines an initialized mtab entry diff --git a/packages/io/fileio/current/include/sockio.h b/packages/io/fileio/current/include/sockio.h --- a/packages/io/fileio/current/include/sockio.h +++ b/packages/io/fileio/current/include/sockio.h @@ -96,7 +96,7 @@ struct cyg_nstab_entry int (*init)( cyg_nstab_entry *nste ); int (*socket)( cyg_nstab_entry *nste, int domain, int type, int protocol, cyg_file *file ); -}; +} CYG_HAL_TABLE_TYPE; #define NSTAB_ENTRY( _l, _syncmode, _name, _devname, _data, _init, _socket ) \ struct cyg_nstab_entry _l CYG_HAL_TABLE_ENTRY(nstab) = \ diff --git a/packages/io/flash/current/ChangeLog b/packages/io/flash/current/ChangeLog --- a/packages/io/flash/current/ChangeLog +++ b/packages/io/flash/current/ChangeLog @@ -1,3 +1,9 @@ +2000-09-01 Hugo Tyson + + * include/flash.h: + * src/flash.c: CYGHWR_IO_FLASH_BLOCK_LOCKING is an interface, so + it's always defined; look for > 0 instead. + 2000-08-28 Gary Thomas * src/flash.c: diff --git a/packages/io/flash/current/include/flash.h b/packages/io/flash/current/include/flash.h --- a/packages/io/flash/current/include/flash.h +++ b/packages/io/flash/current/include/flash.h @@ -51,7 +51,7 @@ extern int flash_init(void *work_space, int work_space_length); extern int flash_erase(void *base, int len, void **err_address); extern int flash_program(void *flash_base, void *ram_base, int len, void **err_address); -#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING +#if 0 < CYGHWR_IO_FLASH_BLOCK_LOCKING // This is an *interface* extern int flash_lock(void *base, int len, void **err_address); extern int flash_unlock(void *base, int len, void **err_address); #endif diff --git a/packages/io/flash/current/src/flash.c b/packages/io/flash/current/src/flash.c --- a/packages/io/flash/current/src/flash.c +++ b/packages/io/flash/current/src/flash.c @@ -189,7 +189,7 @@ flash_program(void *_addr, void *_data, return (stat); } -#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING +#if 0 < CYGHWR_IO_FLASH_BLOCK_LOCKING // This is an *interface* int flash_lock(void *addr, int len, void **err_addr) diff --git a/packages/language/c/libm/current/ChangeLog b/packages/language/c/libm/current/ChangeLog --- a/packages/language/c/libm/current/ChangeLog +++ b/packages/language/c/libm/current/ChangeLog @@ -1,3 +1,7 @@ +2000-09-01 Jonathan Larmour + + * src/misc/infconst.c: Silence warning about number of brackets + 2000-08-31 Jonathan Larmour * include/math.h: Declare cyg_libm_infinity as an array type for correct diff --git a/packages/language/c/libm/current/src/misc/infconst.c b/packages/language/c/libm/current/src/misc/infconst.c --- a/packages/language/c/libm/current/src/misc/infconst.c +++ b/packages/language/c/libm/current/src/misc/infconst.c @@ -62,11 +62,11 @@ #if (CYG_BYTEORDER == CYG_MSBFIRST) // Big endian -const Cyg_libm_ieee_double_shape_type cyg_libm_infinity[] = { {0x7ff00000, 0} }; +const Cyg_libm_ieee_double_shape_type cyg_libm_infinity[] = { { {0x7ff00000, 0} } }; #else // Little endian -const Cyg_libm_ieee_double_shape_type cyg_libm_infinity[] = { {0, 0x7ff00000} }; +const Cyg_libm_ieee_double_shape_type cyg_libm_infinity[] = { { {0, 0x7ff00000} } }; #endif diff --git a/packages/net/tcpip/current/ChangeLog b/packages/net/tcpip/current/ChangeLog --- a/packages/net/tcpip/current/ChangeLog +++ b/packages/net/tcpip/current/ChangeLog @@ -1,3 +1,54 @@ +2000-09-01 Hugo Tyson + + * src/ecos/support.c (cyg_net_init): You can't print things while + initializing the network! Well, not if connected to GDB over the + network anyway. The printf("Init device '%s'...); removed. + +2000-09-01 Hugo Tyson + + * OVERVIEW: This is part of the change to the network stack to + greatly reduce latencies both of (other) DSRs and of thread + scheduling. All the work that the network stack *and* individual + ether drivers used to do in DSRs (including alarm callbacks and + data copies to/from the device memory) is moved into a "fast + network thread" instead. It calls a device's "deliver" function + to do the work that was previously in the DSR. This is a separate + thread so that it can be set higher priority than application + threads in order to minimize packet loss (depending on the + driver), if required (the application threads presumed to be + higher priority in turn than the network thread). A crucial + consequence of this is that we are no longer locking against DSRs, + so a plain mutex can be used rather than the global scheduler + lock, thus simplifying all the splfoo/splx() style functions. + + * src/ecos/timeout.c (alarm_thread): Addition of the "fast network + thread" which runs DSR-like activities. + (do_timeout): Timeout function morphed for calling from that. + (do_alarm, ecos_synch_eth_drv_dsr): new DSR functions to signal to + the thread. + (timeout): Race condition fixed. splinternal() used for locking + instead of scheduler. + + * src/ecos/support.c (cyg_net_init): Splfoo/splx() functions, + together with tsleep/wakeup functions, all removed to separate + them from the mixed bag of utilities in this file. What remains + is mbuf wrapper routines and the like, plus the network "netisr" + thread itself, the caller into the stack that does the slower + priority work. + + * src/ecos/synch.c: New file; implemtation of new splfoo/splx() + functions, together with tsleep/wakeup functions, since they are + related now. + + * cdl/net.cdl: Compile new file synch.c; two new options, one for + "fast thread" priority, and one for DHCP manager thread priority, + as I was adding prio configury. CYGPKG_NET_FAST_THREAD_PRIORITY + and CYGPKG_NET_DHCP_THREAD_PRIORITY resp, with suitable default + values relative to the CYGPKG_NET_THREAD_PRIORITY. + + * src/lib/dhcp_support.c (dhcp_start_dhcp_mgt_thread): Use the + configured priority rather than just "net thread - 1" + 2000-08-31 Hugo Tyson * tests/tcp_echo.c: Change the priorities of the main and loading diff --git a/packages/net/tcpip/current/cdl/net.cdl b/packages/net/tcpip/current/cdl/net.cdl --- a/packages/net/tcpip/current/cdl/net.cdl +++ b/packages/net/tcpip/current/cdl/net.cdl @@ -56,6 +56,7 @@ cdl_package CYGPKG_NET { requires { CYGBLD_ISO_BSDTYPES_HEADER == "" } compile ecos/support.c \ + ecos/synch.c \ ecos/timeout.c \ ecos/init.cxx \ sys/kern/uipc_mbuf.c \ @@ -255,6 +256,17 @@ cdl_package CYGPKG_NET { 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_DHCP_THREAD_PRIORITY { + display "DHCP management thread priority" + flavor data + default_value CYGPKG_NET_THREAD_PRIORITY + 1 + active_if CYGOPT_NET_DHCP_DHCP_THREAD + description " + This option sets the thread priority level used by the DHCP + management thread. It should be high enough that it can run + when necessary, but it does not need to be as high as the + network thread itself." + } } cdl_option CYGPKG_NET_SYSCTL { @@ -277,6 +289,21 @@ cdl_package CYGPKG_NET { threads can have precedence over network processing." } + cdl_option CYGPKG_NET_FAST_THREAD_PRIORITY { + display "Priority level for fast network processing." + flavor data + default_value CYGPKG_NET_THREAD_PRIORITY - 1 + description " + This option sets the thread priority level used by the fast + network thread. The fast network thread runs often but briefly, to + service network device interrupts and network timeout events. This + thread should have higher priority than the background network + thread. It is reasonable to set this thread's priority higher than + application threads for best network throughput, or to set it lower + than application threads for best latency for those application + threads themselves, potentially at a cost to network throughput." + } + cdl_option CYGPKG_NET_NBPF { display "Number of BPF filters" flavor data diff --git a/packages/net/tcpip/current/src/ecos/support.c b/packages/net/tcpip/current/src/ecos/support.c --- a/packages/net/tcpip/current/src/ecos/support.c +++ b/packages/net/tcpip/current/src/ecos/support.c @@ -115,214 +115,6 @@ cyg_panic(const char *msg, ...) cyg_test_exit(); // FIXME } -//---------------------------- 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 - -static cyg_mutex_t softnet_mutex; -static volatile cyg_handle_t softnet_thread; - -#define SPLINIT() CYG_MACRO_START \ - cyg_mutex_init( &softnet_mutex ); \ - softnet_thread = 0; \ -CYG_MACRO_END - -// -// 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 -{ - 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(); - } - return old_ints; -} - -// -// 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 -cyg_splclock(void) -#endif -{ - 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_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; - 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; -} - -cyg_uint32 -#ifdef CYGIMPL_TRACE_SPLX -cyg_splhigh(const char *file, const int line) -#else -cyg_splhigh(void) -#endif -{ - // splhigh did SPLSOFTNET in the contrib, so this is the same - return cyg_splsoftnet( -#ifdef CYGIMPL_TRACE_SPLX - file, line -#endif - ); -} - -// -// Prevent all other stack processing, including interrupts (DSRs), etc. -// -// NB a thread in this state can tsleep(); see below. Tsleep releases and -// reclaims the locks and so on. This necessary because of the possible -// conflict where -// I splsoft -// I tsleep -// He runs, he is lower priority -// He splsofts -// He or something else awakens me -// I want to run, but he has splsoft, so I wait -// He runs and releases splsoft -// I awaken and go. - -cyg_uint32 -#ifdef CYGIMPL_TRACE_SPLX -cyg_splsoftnet(const char *file, const int line) -#else -cyg_splsoftnet(void) -#endif -{ - cyg_uint32 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; - cyg_scheduler_unlock(); - return old_ints; - } - } - // As of the new kernel, we can do this without unlocking the scheduler - cyg_mutex_lock(&softnet_mutex); - - CYG_ASSERT( 0 == softnet_thread, "Softnet thread still set" ); - CYG_ASSERT( 0 == (spl_state & SPL_STATE_SOFTNET), "Softnet bit set" ); - - softnet_thread = cyg_thread_self(); - old_ints = spl_state; - spl_state |= SPL_STATE_SOFTNET; - // NB we keep the sched locked here. - return old_ints; -} - -// -// 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 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(); -} -//---------------------------- splx() emulation ------------------------------ - -void -setsoftnet(void) -{ - diag_printf("setsoftnet\n"); - schednetisr(NETISR_SOFTNET); -} // Round a number 'n' up to a multiple of 'm' #define round(n,m) ((((n)+((m)-1))/(m))*(m)) @@ -633,134 +425,8 @@ 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 -// -struct wakeup_event { - void *chan; - cyg_sem_t sem; -}; -static struct wakeup_event wakeup_list[CYGPKG_NET_NUM_WAKEUP_EVENTS]; - -// -// Signal an event -void -cyg_wakeup(void *chan) -{ - int i; - struct wakeup_event *ev; - cyg_scheduler_lock(); // Ensure scan is safe - for (i = 0, ev = wakeup_list; i < CYGPKG_NET_NUM_WAKEUP_EVENTS; i++, ev++) { - if (ev->chan == chan) { - cyg_semaphore_post(&ev->sem); - ev->chan = 0; - } - } - cyg_scheduler_unlock(); -} - -// -// Wait for an event with timeout -// tsleep(event, priority, state, timeout) -// event - the thing to wait for -// priority - unused -// state - a descriptive message -// timeout - max time (in ticks) to wait -// returns: -// 0 - event was "signalled" -// ETIMEDOUT - timeout occurred -// EINTR - thread broken out of sleep -// -int -cyg_tsleep(void *chan, int pri, char *wmesg, int timo) -{ - int i, res = 0; - struct wakeup_event *ev; - cyg_tick_count_t sleep_time; - 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(); - - for (i = 0, ev = wakeup_list; i < CYGPKG_NET_NUM_WAKEUP_EVENTS; i++, ev++) { - if (ev->chan == 0) { - ev->chan = chan; - break; - } - } - if (i == CYGPKG_NET_NUM_WAKEUP_EVENTS) { - panic("no sleep slots"); - } - 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 ) { - CYG_ASSERT( spl_state & SPL_STATE_SOFTNET, "Softnet bit not set" ); - // Also want to assert that the mutex is locked... - CYG_ASSERT( softnet_mutex.locked, "Softnet mutex not locked" ); - CYG_ASSERT( (cyg_handle_t)softnet_mutex.owner == self, "Softnet mutex not mine" ); - softnet_thread = 0; - spl_state &= ~SPL_STATE_SOFTNET; - cyg_mutex_unlock( &softnet_mutex ); - } else { - self = 0; // Flag no need to reclaim - } - - // This part actually does the wait: - // As of the new kernel, we can do this without unlocking the scheduler - if (timo) { - sleep_time = cyg_current_time() + timo; - if (!cyg_semaphore_timed_wait(&ev->sem, sleep_time)) { - if( cyg_current_time() >= sleep_time ) - res = ETIMEDOUT; - else - res = EINTR; - ev->chan = 0; // Free slot (no signaller to free it) - } - } else { - if (!cyg_semaphore_wait(&ev->sem) ) { - res = EINTR; - ev->chan = 0; // Free slot (ditto) - } - } - - if ( self ) { // return to previous state - // As of the new kernel, we can do this with the scheduler locked - cyg_mutex_lock( &softnet_mutex ); // this might wait - CYG_ASSERT( 0 == softnet_thread, "Softnet thread set in tsleep" ); - CYG_ASSERT( 0 == (spl_state & SPL_STATE_SOFTNET), "Softnet bit set in tsleep" ); - softnet_thread = self; // got it now... - spl_state |= SPL_STATE_SOFTNET; - // and leave the scheduler locked. - CYG_ASSERT( olock > 1, "Sched was not locked" ); - } - else if ( olock == 1 ) - cyg_scheduler_unlock(); - // otherwise leave it locked, as it was on entry. - - return res; -} - -// Called to initialize structures used by timeout functions -static void -cyg_timeout_init(void) -{ - int i; - struct wakeup_event *ev; - // Create list of "wakeup event" semaphores - for (i = 0, ev = wakeup_list; i < CYGPKG_NET_NUM_WAKEUP_EVENTS; i++, ev++) { - ev->chan = 0; - cyg_semaphore_init(&ev->sem, 0); - } -} -//------------------ tsleep() and wakeup() emulation --------------------------- - +// ------------------------------------------------------------------------ +// THE NETWORK THREAD ITSELF // // Network software interrupt handler // This function is run as a separate thread to allow @@ -771,11 +437,11 @@ static void cyg_netint(cyg_addrword_t param) { cyg_flag_value_t curisr; - int s; + int spl; while (true) { curisr = cyg_flag_wait(&netint_flags, NETISR_ANY, CYG_FLAG_WAITMODE_OR|CYG_FLAG_WAITMODE_CLR); - s = splsoftnet(); // Prevent any overlapping "stack" processing + spl = splsoftnet(); // Prevent any overlapping "stack" processing #ifdef INET if (curisr & (1 << NETISR_ARP)) { // Pending ARP requests @@ -798,10 +464,20 @@ cyg_netint(cyg_addrword_t param) bridgeintr(); } #endif - splx(s); + splx(spl); } } + +// This just sets one of the pseudo-ISR bits used above. +void +setsoftnet(void) +{ + diag_printf("setsoftnet\n"); + // No need to do this because it is ignored anyway: + // schednetisr(NETISR_SOFTNET); +} + // // Network initialization // This function is called during system initialization to setup the whole @@ -812,23 +488,29 @@ extern void ifinit(void); extern void loopattach(int); extern void bridgeattach(int); +// Internal init functions: +extern void cyg_alarm_timeout_init(void); +extern void cyg_tsleep_init(void); + void 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" cyg_flag_init(&netint_flags); - // Anthing else needed? -#ifdef SPLINIT - SPLINIT(); -#endif + // Initialize timeouts and net service thread (pseudo-DSRs) + cyg_alarm_timeout_init(); + // Initialize tsleep/wakeup support + cyg_tsleep_init(); + // Initialize network memory system + cyg_kmem_init(); + mbinit(); + // Create network background thread cyg_thread_create(CYGPKG_NET_THREAD_PRIORITY, // Priority cyg_netint, // entry @@ -840,14 +522,10 @@ cyg_net_init(void) &netint_thread_data // Thread data structure ); cyg_thread_resume(netint_thread_handle); // Start it - // Initialize timeout support - cyg_timeout_init(); - // Initialize network memory system - cyg_kmem_init(); - mbinit(); + // Initialize all network devices for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) { - diag_printf("Init device '%s'\n", t->name); +// diag_printf("Init device '%s'\n", t->name); if (t->init(t)) { t->status = CYG_NETDEVTAB_STATUS_AVAIL; } else { @@ -872,72 +550,4 @@ cyg_net_init(void) _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 - // EOF support.c diff --git a/packages/net/tcpip/current/src/ecos/synch.c b/packages/net/tcpip/current/src/ecos/synch.c new file mode 100644 --- /dev/null +++ b/packages/net/tcpip/current/src/ecos/synch.c @@ -0,0 +1,442 @@ +//========================================================================== +// +// ecos/synch.c +// +// eCos wrapper and synch functions +// +//========================================================================== +//####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, hmt +// Contributors: gthomas, hmt +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +// Synch routines, etc., used by network code + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +#include + +#include + +//---------------------------- splx() emulation ------------------------------ +// This contains both the SPLX stuff and tsleep/wakeup - because those must +// be SPLX aware. They release the SPLX lock when sleeping, and reclaim it +// (if needs be) at wakeup. +// +// The variable spl_state (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. +// +// SPL_IMP is called in order to protect internal data structures +// short-term, primarily so that interrupt processing does not interfere +// with them. +// +// SPL_CLOCK 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). +// +// SPL_SOFTNET is used to prevent all other stack processing, including +// interrupts (DSRs), etc. +// +// SPL_INTERNAL is used when running the pseudo-DSR in timeout.c - this +// runs what should really be the network interface device's DSR, and any +// timeout routines that are scheduled. (They are broken out into a thread +// to isolate the network locking from the rest of the system) +// +// NB a thread in thi state can tsleep(); see below. Tsleep releases and +// reclaims the locks and so on. This necessary because of the possible +// conflict where +// I splsoft +// I tsleep +// He runs, he is lower priority +// He splsofts +// He or something else awakens me +// I want to run, but he has splsoft, so I wait +// He runs and releases splsoft +// I awaken and go. + +static volatile cyg_uint32 spl_state = 0; +#define SPL_IMP 0x01 +#define SPL_NET 0x02 +#define SPL_CLOCK 0x04 +#define SPL_SOFTNET 0x08 +#define SPL_INTERNAL 0x10 + +static cyg_mutex_t splx_mutex; +static volatile cyg_handle_t splx_thread; + + +#ifdef CYGIMPL_TRACE_SPLX +#define SPLXARGS const char *file, const int line +#define SPLXMOREARGS , const char *file, const int line +#define SPLXTRACE do_sched_event(__FUNCTION__, file, line, spl_state) +#else +#define SPLXARGS void +#define SPLXMOREARGS +#define SPLXTRACE +#endif + + +static inline cyg_uint32 +spl_any( cyg_uint32 which ) +{ + cyg_uint32 old_spl = spl_state; + if ( cyg_thread_self() != splx_thread ) { + cyg_mutex_lock( &splx_mutex ); + old_spl = 0; // Free when we unlock this context + CYG_ASSERT( 0 == splx_thread, "Thread still owned" ); + CYG_ASSERT( 0 == spl_state, "spl still set" ); + splx_thread = cyg_thread_self(); + } + CYG_ASSERT( splx_mutex.locked, "spl_any: mutex not locked" ); + CYG_ASSERT( (cyg_handle_t)splx_mutex.owner == cyg_thread_self(), + "spl_any: mutex not mine" ); + spl_state |= which; + return old_spl; +} + + +cyg_uint32 +cyg_splimp(SPLXARGS) +{ + SPLXTRACE; + return spl_any( SPL_IMP ); +} + +cyg_uint32 +cyg_splclock(SPLXARGS) +{ + SPLXTRACE; + return spl_any( SPL_CLOCK ); +} + +cyg_uint32 +cyg_splnet(SPLXARGS) +{ + SPLXTRACE; + return spl_any( SPL_NET ); +} + +cyg_uint32 +cyg_splhigh(SPLXARGS) +{ + SPLXTRACE; + // splhigh did SPLSOFTNET in the contrib, so this is the same + return spl_any( SPL_SOFTNET ); +} + +cyg_uint32 +cyg_splsoftnet(SPLXARGS) +{ + SPLXTRACE; + return spl_any( SPL_SOFTNET ); +} + +cyg_uint32 +cyg_splinternal(SPLXARGS) +{ + SPLXTRACE; + return spl_any( SPL_INTERNAL ); +} + + +// +// Return to a previous interrupt state/level. +// +void +cyg_splx(cyg_uint32 old_state SPLXMOREARGS) +{ + SPLXTRACE; + + CYG_ASSERT( 0 != spl_state, "No state set" ); + CYG_ASSERT( splx_mutex.locked, "splx: mutex not locked" ); + CYG_ASSERT( (cyg_handle_t)splx_mutex.owner == cyg_thread_self(), + "splx: mutex not mine" ); + + spl_state &= old_state; + + if ( 0 == spl_state ) { + splx_thread = 0; + cyg_mutex_unlock( &splx_mutex ); + } +} + +//------------------ tsleep() and wakeup() emulation --------------------------- +// +// Structure used to keep track of 'tsleep' style events +// +struct wakeup_event { + void *chan; + cyg_sem_t sem; +}; +static struct wakeup_event wakeup_list[CYGPKG_NET_NUM_WAKEUP_EVENTS]; + + +// Called to initialize structures used by timeout functions +void +cyg_tsleep_init(void) +{ + int i; + struct wakeup_event *ev; + // Create list of "wakeup event" semaphores + for (i = 0, ev = wakeup_list; i < CYGPKG_NET_NUM_WAKEUP_EVENTS; i++, ev++) { + ev->chan = 0; + cyg_semaphore_init(&ev->sem, 0); + } + // Initialize the mutex and thread id: + cyg_mutex_init( &splx_mutex ); + splx_thread = 0; +} + + +// +// Signal an event +void +cyg_wakeup(void *chan) +{ + int i; + struct wakeup_event *ev; + cyg_scheduler_lock(); // Ensure scan is safe + // NB this is broadcast semantics because a sleeper/wakee holds the + // slot until they exit. This avoids a race condition whereby the + // semaphore can get an extra post - and then the slot is freed, so the + // sem wait returns immediately, AOK, so the slot wasn't freed. + for (i = 0, ev = wakeup_list; i < CYGPKG_NET_NUM_WAKEUP_EVENTS; i++, ev++) + if (ev->chan == chan) + cyg_semaphore_post(&ev->sem); + + cyg_scheduler_unlock(); +} + +// ------------------------------------------------------------------------ +// Wait for an event with timeout +// tsleep(event, priority, state, timeout) +// event - the thing to wait for +// priority - unused +// state - a descriptive message +// timeout - max time (in ticks) to wait +// returns: +// 0 - event was "signalled" +// ETIMEDOUT - timeout occurred +// EINTR - thread broken out of sleep +// +int +cyg_tsleep(void *chan, int pri, char *wmesg, int timo) +{ + int i, res = 0; + struct wakeup_event *ev; + cyg_tick_count_t sleep_time; + cyg_handle_t self = cyg_thread_self(); + int old_splflags = 0; // no flags held + + cyg_scheduler_lock(); + + // Safely find a free slot: + for (i = 0, ev = wakeup_list; i < CYGPKG_NET_NUM_WAKEUP_EVENTS; i++, ev++) { + if (ev->chan == 0) { + ev->chan = chan; + break; + } + } + CYG_ASSERT( i < CYGPKG_NET_NUM_WAKEUP_EVENTS, "no sleep slots" ); + CYG_ASSERT( 1 == cyg_scheduler_read_lock(), + "Tsleep - called with scheduler locked" ); + // Defensive: + if ( i >= CYGPKG_NET_NUM_WAKEUP_EVENTS ) { + cyg_scheduler_unlock(); + return ETIMEDOUT; + } + + // If we are the owner, then we must release the mutex when + // we wait. + if ( self == splx_thread ) { + old_splflags = spl_state; // Keep them for restoration + CYG_ASSERT( spl_state, "spl_state not set" ); + // Also want to assert that the mutex is locked... + CYG_ASSERT( splx_mutex.locked, "Splx mutex not locked" ); + CYG_ASSERT( (cyg_handle_t)splx_mutex.owner == self, "Splx mutex not mine" ); + splx_thread = 0; + spl_state = 0; + cyg_mutex_unlock( &splx_mutex ); + } + + // Re-initialize the semaphore - it might have counted up arbitrarily + // in the time between a prior sleeper being signalled and them + // actually running. + cyg_semaphore_init(&ev->sem, 0); + + // This part actually does the wait: + // As of the new kernel, we can do this without unlocking the scheduler + if (timo) { + sleep_time = cyg_current_time() + timo; + if (!cyg_semaphore_timed_wait(&ev->sem, sleep_time)) { + if( cyg_current_time() >= sleep_time ) + res = ETIMEDOUT; + else + res = EINTR; + } + } else { + if (!cyg_semaphore_wait(&ev->sem) ) { + res = EINTR; + } + } + + ev->chan = 0; // Free the slot - the wakeup call cannot do this. + + if ( old_splflags ) { // restore to previous state + // As of the new kernel, we can do this with the scheduler locked + cyg_mutex_lock( &splx_mutex ); // this might wait + CYG_ASSERT( 0 == splx_thread, "Splx thread set in tsleep" ); + CYG_ASSERT( 0 == spl_state, "spl_state set in tsleep" ); + splx_thread = self; // got it now... + spl_state = old_splflags; + } + + cyg_scheduler_unlock(); + return res; +} + + + +// ------------------------------------------------------------------------ +// DEBUGGING ROUTINES +#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; + } +} + +#define SPLX_TRACE_DATA() cyg_scheduler_read_lock() + +void +_cyg_scheduler_lock(char *file, int line) +{ + cyg_scheduler_lock(); + do_sched_event(__FUNCTION__, file, line, SPLX_TRACE_DATA()); +} + +void +_cyg_scheduler_safe_lock(char *file, int line) +{ + cyg_scheduler_safe_lock(); + do_sched_event(__FUNCTION__, file, line, SPLX_TRACE_DATA()); +} + +void +_cyg_scheduler_unlock(char *file, int line) +{ + cyg_scheduler_unlock(); + do_sched_event(__FUNCTION__, file, line, SPLX_TRACE_DATA()); +} +#endif // CYGIMPL_TRACE_SPLX + +// EOF synch.c diff --git a/packages/net/tcpip/current/src/ecos/timeout.c b/packages/net/tcpip/current/src/ecos/timeout.c --- a/packages/net/tcpip/current/src/ecos/timeout.c +++ b/packages/net/tcpip/current/src/ecos/timeout.c @@ -54,6 +54,8 @@ // Timeout support +void alarm_timeout_init(void); + #ifndef NTIMEOUTS #define NTIMEOUTS 8 #endif @@ -68,10 +70,23 @@ static cyg_alarm timeout_alarm; static cyg_int32 last_delta; static cyg_tick_count_t last_set_time; -extern cyg_uint32 cyg_in_softnet( void ); +#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL +static char alarm_stack[STACK_SIZE]; +static cyg_thread alarm_thread_data; +static cyg_handle_t alarm_thread_handle; + +static cyg_flag_t alarm_flag; +// ------------------------------------------------------------------------ +// This routine exists so that this module can synchronize: +extern cyg_uint32 cyg_splinternal(void); + +// ------------------------------------------------------------------------ +// CALLBACK FUNCTION +// Called from the thread, this runs the alarm callbacks. +// Locking is already in place when this is called. static void -do_timeout(cyg_handle_t alarm, cyg_addrword_t data) +do_timeout(void) { int i; cyg_int32 min_delta; @@ -118,25 +133,95 @@ do_timeout(cyg_handle_t alarm, cyg_addrw } } +// ------------------------------------------------------------------------ +// ALARM EVENT FUNCTION +// This is the DSR for the alarm firing: +static void +do_alarm(cyg_handle_t alarm, cyg_addrword_t data) +{ + cyg_flag_setbits( &alarm_flag, 1 ); +} + +void ecos_synch_eth_drv_dsr(void) +{ + cyg_flag_setbits( &alarm_flag, 2 ); +} + +// ------------------------------------------------------------------------ +// HANDLER THREAD ENTRY ROUTINE +// This waits on the DSR to tell it to run: +static void +alarm_thread(cyg_addrword_t param) +{ + // This is from the logical ethernet dev; it calls those delivery + // functions who need attention. + extern void eth_drv_run_deliveries( void ); + + while ( 1 ) { + int spl; + int x = cyg_flag_wait( + &alarm_flag, + -1, + CYG_FLAG_WAITMODE_OR | CYG_FLAG_WAITMODE_CLR ); + + CYG_ASSERT( 3 & x, "Lost my bits" ); + CYG_ASSERT( !((~3) & x), "Extra bits" ); + + spl = cyg_splinternal(); + + CYG_ASSERT( 0 == spl, "spl nonzero" ); + + if ( 2 & x ) + eth_drv_run_deliveries(); + + if ( 1 & x ) + do_timeout(); + + cyg_splx(spl); + } +} + +// ------------------------------------------------------------------------ +// INITIALIZATION FUNCTION +void +cyg_alarm_timeout_init( void ) +{ + // Init the alarm object, attached to the real time clock + cyg_handle_t h; + cyg_clock_to_counter(cyg_real_time_clock(), &h); + cyg_alarm_create(h, do_alarm, 0, &timeout_alarm_handle, &timeout_alarm); + // Init the flag of waking up + cyg_flag_init( &alarm_flag ); + // Create alarm background thread to run the callbacks + cyg_thread_create( + CYGPKG_NET_FAST_THREAD_PRIORITY, // Priority + alarm_thread, // entry + 0, // entry parameter + "Network alarm support", // Name + &alarm_stack[0], // Stack + STACK_SIZE, // Size + &alarm_thread_handle, // Handle + &alarm_thread_data // Thread data structure + ); + cyg_thread_resume(alarm_thread_handle); // Start it +} + +// ------------------------------------------------------------------------ +// EXPORTED API: SET A TIMEOUT +// This can be called from anywhere, including recursively from the timeout +// functions themselves. cyg_uint32 timeout(timeout_fun *fun, void *arg, cyg_int32 delta) { int i; - static bool init = false; timeout_entry *e; cyg_uint32 stamp; - CYG_ASSERT( 0 < delta, "delta is right now, or even sooner!" ); - - // this needs to be atomic wrt threads and DSRs - cyg_scheduler_lock(); + // this needs to be atomic - recursive calls from the alarm + // handler thread itself are allowed: + int spl = cyg_splinternal(); - if (!init) { - cyg_handle_t h; - cyg_clock_to_counter(cyg_real_time_clock(), &h); - cyg_alarm_create(h, do_timeout, 0, &timeout_alarm_handle, &timeout_alarm); - init = true; - } + CYG_ASSERT( 0 < delta, "delta is right now, or even sooner!" ); // Renormalize delta wrt the existing set alarm, if there is one if ( last_delta > 0 ) @@ -185,12 +270,13 @@ timeout(timeout_fun *fun, void *arg, cyg #ifdef CYGPKG_INFRA_DEBUG // Do some more checking akin to that in the alarm handler: if ( last_delta != -1 ) { // not a recursive call + cyg_tick_count_t now = cyg_current_time(); CYG_ASSERT( last_delta >= 0, "Bad last delta" ); delta = 0x7fffffff; for (e = timeouts, i = 0; i < NTIMEOUTS; i++, e++) { if (e->delta) { CYG_ASSERT( e->delta >= last_delta, "e->delta underflow" ); - CYG_ASSERT( last_set_time + e->delta > cyg_current_time(), + CYG_ASSERT( last_set_time + e->delta + 1000 > now, "Recorded alarm not in the future!" ); if ( e->delta < delta ) delta = e->delta; @@ -202,17 +288,21 @@ timeout(timeout_fun *fun, void *arg, cyg } #endif - cyg_scheduler_unlock(); - + cyg_splx(spl); return stamp; } +// ------------------------------------------------------------------------ +// EXPORTED API: CANCEL A TIMEOUT +// This can be called from anywhere, including recursively from the timeout +// functions themselves. void untimeout(timeout_fun *fun, void * arg) { int i; timeout_entry *e; - cyg_scheduler_lock(); + int spl = cyg_splinternal(); + for (e = timeouts, i = 0; i < NTIMEOUTS; i++, e++) { if (e->delta && (e->fun == fun) && (e->arg == arg)) { e->delta = 0; @@ -220,7 +310,9 @@ untimeout(timeout_fun *fun, void * arg) break; } } - cyg_scheduler_unlock(); + cyg_splx(spl); } +// ------------------------------------------------------------------------ + // EOF timeout.c diff --git a/packages/net/tcpip/current/src/lib/dhcp_support.c b/packages/net/tcpip/current/src/lib/dhcp_support.c --- a/packages/net/tcpip/current/src/lib/dhcp_support.c +++ b/packages/net/tcpip/current/src/lib/dhcp_support.c @@ -213,7 +213,7 @@ void dhcp_start_dhcp_mgt_thread( void ) { if ( ! dhcp_mgt_thread_h ) { cyg_thread_create( - CYGPKG_NET_THREAD_PRIORITY+1, /* scheduling info (eg pri) */ + CYGPKG_NET_DHCP_THREAD_PRIORITY, /* scheduling info (eg pri) */ dhcp_mgt_entry, /* entry point function */ CYGOPT_NET_DHCP_DHCP_THREAD_PARAM, /* entry data */ "DHCP lease mgt", /* optional thread name */ diff --git a/packages/redboot/current/ChangeLog b/packages/redboot/current/ChangeLog --- a/packages/redboot/current/ChangeLog +++ b/packages/redboot/current/ChangeLog @@ -1,3 +1,14 @@ +2000-09-04 Jonathan Larmour + + * include/flash_config.h (struct config_option): Apply + CYG_HAL_TABLE_TYPE + * include/redboot.h: Ditto for struct cmd and void_fun_ptr + +2000-09-01 Hugo Tyson + + * src/flash.c: CYGHWR_IO_FLASH_BLOCK_LOCKING is an interface, so + it's always defined; look for > 0 instead. + 2000-08-28 Gary Thomas * src/flash.c: Support block locking if available. diff --git a/packages/redboot/current/include/flash_config.h b/packages/redboot/current/include/flash_config.h --- a/packages/redboot/current/include/flash_config.h +++ b/packages/redboot/current/include/flash_config.h @@ -63,7 +63,7 @@ struct config_option { char *enable; bool enable_sense; int type; -}; +} CYG_HAL_TABLE_TYPE; #define ALWAYS_ENABLED (char *)0 diff --git a/packages/redboot/current/include/redboot.h b/packages/redboot/current/include/redboot.h --- a/packages/redboot/current/include/redboot.h +++ b/packages/redboot/current/include/redboot.h @@ -117,7 +117,7 @@ struct cmd { char *help; char *usage; cmd_fun *fun; -}; +} CYG_HAL_TABLE_TYPE; extern struct cmd *cmd_search(struct cmd *tab, struct cmd *tabend, char *arg); extern void cmd_usage(struct cmd *tab, struct cmd *tabend, char *prefix); #define RedBoot_cmd(_s_,_h_,_u_,_f_) cmd_entry(_s_,_h_,_u_,_f_,RedBoot_commands) @@ -134,7 +134,7 @@ static _cmd_entry(_s_,_h_,_u_,_f_,_n_) #define RedBoot_INIT_PRIO(_n_) 1000+_n_ #define RedBoot_INIT_LAST 9999 typedef void void_fun(void); -typedef void_fun *void_fun_ptr; +typedef void_fun *void_fun_ptr CYG_HAL_TABLE_TYPE; #define _RedBoot_init(_f_,_p_) \ void_fun_ptr _init_tab_##_p_##_f_ CYG_HAL_TABLE_QUALIFIED_ENTRY(RedBoot_inits,_f_) = _f_; #define RedBoot_init(_f_,_p_) _RedBoot_init(_f_,_p_) diff --git a/packages/redboot/current/src/flash.c b/packages/redboot/current/src/flash.c --- a/packages/redboot/current/src/flash.c +++ b/packages/redboot/current/src/flash.c @@ -96,7 +96,7 @@ local_cmd_entry("erase", fis_erase, FIS_cmds ); -#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING +#if 0 < CYGHWR_IO_FLASH_BLOCK_LOCKING // This is an *interface* local_cmd_entry("lock", "LOCK FLASH contents", "-f -l ", @@ -483,7 +483,7 @@ fis_erase(int argc, char *argv[]) } } -#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING +#if 0 < CYGHWR_IO_FLASH_BLOCK_LOCKING // This is an *interface* static void fis_lock(int argc, char *argv[])