changeset 121:6bd9d475ed4b ecos-sw-2000-09-04

Merge from eCos master repository on 2000-09-04-20:50:20-BST
author jlarmour
date Mon, 04 Sep 2000 20:24:12 +0000
parents 0e17207f29f3
children 51271dc28cd2
files packages/NEWS packages/compat/posix/current/ChangeLog packages/compat/posix/current/src/misc.cxx packages/compat/posix/current/tests/pthread2.c packages/compat/posix/current/tests/pthread3.c packages/devs/eth/arm/ebsa285/current/ChangeLog packages/devs/eth/arm/ebsa285/current/src/if_ebsa285.c packages/devs/eth/arm/ebsa285/current/tests/test_net_realtime.h packages/devs/eth/arm/edb7xxx/current/ChangeLog packages/devs/eth/arm/edb7xxx/current/src/if_edb7xxx.c packages/devs/eth/cf/current/ChangeLog packages/devs/eth/cf/current/src/if_sc_lpe.c packages/devs/eth/powerpc/quicc/current/ChangeLog packages/devs/eth/powerpc/quicc/current/src/if_quicc.c packages/devs/flash/arm/assabet/current/src/assabet_flash.c packages/devs/flash/arm/assabet/current/src/flash.h packages/devs/flash/arm/assabet/current/src/flash_erase_block.c packages/devs/flash/arm/assabet/current/src/flash_program_buf.c packages/devs/flash/arm/assabet/current/src/flash_query.c packages/ecos.db packages/hal/common/current/ChangeLog packages/hal/common/current/include/hal_if.h packages/hal/common/current/include/hal_tables.h packages/hal/common/current/src/generic-stub.c packages/hal/common/current/src/hal_stub.c packages/hal/mips/arch/current/ChangeLog packages/hal/mips/arch/current/include/hal_cache.h packages/hal/mips/arch/current/include/mips-stub.h packages/hal/mips/vr4300/current/ChangeLog packages/hal/mips/vr4300/current/include/var_arch.h packages/hal/mn10300/arch/current/ChangeLog packages/hal/mn10300/arch/current/include/basetype.h packages/hal/powerpc/quicc/current/ChangeLog packages/hal/powerpc/quicc/current/src/quicc_smc1.c packages/hal/sh/arch/current/ChangeLog packages/hal/sh/arch/current/include/mod_7707a.h packages/hal/sh/arch/current/include/mod_7708.h packages/hal/sh/arch/current/include/mod_7709a.h packages/hal/sh/arch/current/include/sh_regs.h packages/hal/sh/arch/current/src/sh_stub.c packages/infra/current/ChangeLog packages/infra/current/include/cyg_type.h packages/infra/current/include/cyg_type.inc packages/io/common/current/ChangeLog packages/io/common/current/include/devtab.h packages/io/eth/current/ChangeLog packages/io/eth/current/include/eth_drv.h packages/io/eth/current/src/net/eth_drv.c packages/io/eth/current/src/stand_alone/eth_drv.c packages/io/fileio/current/ChangeLog packages/io/fileio/current/include/fileio.h packages/io/fileio/current/include/sockio.h packages/io/flash/current/ChangeLog packages/io/flash/current/include/flash.h packages/io/flash/current/src/flash.c packages/language/c/libm/current/ChangeLog packages/language/c/libm/current/src/misc/infconst.c packages/net/tcpip/current/ChangeLog packages/net/tcpip/current/cdl/net.cdl packages/net/tcpip/current/src/ecos/support.c packages/net/tcpip/current/src/ecos/synch.c packages/net/tcpip/current/src/ecos/timeout.c packages/net/tcpip/current/src/lib/dhcp_support.c packages/redboot/current/ChangeLog packages/redboot/current/include/flash_config.h packages/redboot/current/include/redboot.h packages/redboot/current/src/flash.c
diffstat 67 files changed, 1715 insertions(+), 575 deletions(-) [+]
line wrap: on
line diff
--- 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
--- a/packages/compat/posix/current/ChangeLog
+++ b/packages/compat/posix/current/ChangeLog
@@ -1,3 +1,12 @@
+2000-09-04  Nick Garnett  <nickg@cygnus.co.uk>
+
+	* 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  <jlarmour@redhat.co.uk>
 
 	* include/limits.h: Don't define SSIZE_MAX here, leave it to the
--- 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
                                                                                 
 
--- 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],
--- 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],
--- 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  <hmt@cygnus.co.uk>
+
+	* 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  <hmt@cygnus.co.uk>
+
+	* 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  <hmt@cygnus.co.uk>
 
 	* src/if_ebsa285.c (i82559_ioctl): A little further diddling; have
--- 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 );
                     
--- 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
--- 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  <hmt@cygnus.co.uk>
+
+	* 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  <gthomas@redhat.com>
 
 	* src/if_edb7xxx.c: Add new function which returns the interrupt
--- 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);
--- a/packages/devs/eth/cf/current/ChangeLog
+++ b/packages/devs/eth/cf/current/ChangeLog
@@ -1,3 +1,13 @@
+2000-09-01  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* 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  <gthomas@redhat.com>
 
 	* src/if_sc_lpe.c (sc_lpe_recv): Better handling if upper layer
--- 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
--- 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  <hmt@cygnus.co.uk>
+
+	* 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  <gthomas@redhat.com>
 
 	* src/if_quicc.c: Add function to return interrupt vector used
--- 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);
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 <pkgconf/hal.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_cache.h>
+
+#define  _FLASH_PRIVATE_
+#include <cyg/io/flash.h>
+
+#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)));
+}
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_
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 <pkgconf/hal.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_cache.h>
+
+//
+// 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;
+}
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 <pkgconf/hal.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_cache.h>
+
+//
+// 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;
+}
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 <pkgconf/hal.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_cache.h>
+#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;
+}
--- 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
--- a/packages/hal/common/current/ChangeLog
+++ b/packages/hal/common/current/ChangeLog
@@ -1,3 +1,21 @@
+2000-09-04  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* include/hal_tables.h (CYG_HAL_TABLE_END): Use CYGARC_P2ALIGNMENT
+	to align label
+	(CYG_HAL_TABLE_TYPE): Define
+
+2000-09-01  Jonathan Larmour  <jlarmour@redhat.com>
+
+        * 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  <gthomas@redhat.com>
 
 	* src/hal_if.c: 
--- 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_)
 
--- 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 <cyg/kernel/kapi.h>
+// Usage:       #include <cyg/hal/hal_tables.h>
 //
 //####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
 
 /*------------------------------------------------------------------------*/
--- 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));
--- 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;
--- a/packages/hal/mips/arch/current/ChangeLog
+++ b/packages/hal/mips/arch/current/ChangeLog
@@ -1,7 +1,19 @@
+2000-09-01  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* 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  <dmoseley@redhat.com>
 
-	* 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  <dmoseley@redhat.com>
 
--- 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_) )
 
 
 //=============================================================================
--- 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;
--- a/packages/hal/mips/vr4300/current/ChangeLog
+++ b/packages/hal/mips/vr4300/current/ChangeLog
@@ -1,3 +1,8 @@
+2000-09-01  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* include/var_arch.h (CYG_HAL_GDB_REG): vr4300 GDB stubs now use 
+	32-bits internally to represent registers
+
 2000-06-21  Nick Garnett  <nickg@cygnus.co.uk>
 
 	* src/mips_vr4300.ld:
--- 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 <cyg/infra/cyg_type.h>
 
 // -------------------------------------------------------------------------
-// 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
--- a/packages/hal/mn10300/arch/current/ChangeLog
+++ b/packages/hal/mn10300/arch/current/ChangeLog
@@ -1,3 +1,8 @@
+2000-09-04  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* include/basetype.h (CYGARC_ALIGNMENT): mn10300 has 4 byte alignment
+	(CYGARC_P2ALIGNMENT): Likewise
+
 2000-08-29  Jonathan Larmour  <jlarmour@redhat.co.uk>
 
 	* src/vectors.S (__default_nmi_vsr): Fix quoting in comment problem
--- 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,
--- a/packages/hal/powerpc/quicc/current/ChangeLog
+++ b/packages/hal/powerpc/quicc/current/ChangeLog
@@ -1,3 +1,8 @@
+2000-08-30  Jesper Skov  <jskov@redhat.com>
+
+	* src/quicc_smc1.c (cyg_hal_plf_serial_init_channel): Move all
+	init code to init_channel.
+
 2000-06-30  Jesper Skov  <jskov@redhat.com>
 
 	* src/quicc_smc1.c: calling i/f macro changes.
--- 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
--- a/packages/hal/sh/arch/current/ChangeLog
+++ b/packages/hal/sh/arch/current/ChangeLog
@@ -1,3 +1,12 @@
+2000-08-31  Jesper Skov  <jskov@redhat.com>
+
+	* 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  <jskov@redhat.com>
 
 	* src/sh_stub.c (__single_step): Skip trap instructions.
--- 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)
--- 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
 
 
 //-----------------------------------------------------------------------------
--- 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)
--- 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 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
--- 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)
 {
--- a/packages/infra/current/ChangeLog
+++ b/packages/infra/current/ChangeLog
@@ -1,3 +1,11 @@
+2000-09-04  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* 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  <jlarmour@redhat.co.uk>
 
 	* include/cyg_type.inc: Create. Used for the equivalent stuff of
--- 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
--- a/packages/infra/current/include/cyg_type.inc
+++ b/packages/infra/current/include/cyg_type.inc
@@ -47,10 +47,32 @@
 
 #include <cyg/hal/basetype.h>
 
+// -------------------------------------------------------------------------
+// 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
--- a/packages/io/common/current/ChangeLog
+++ b/packages/io/common/current/ChangeLog
@@ -1,3 +1,7 @@
+2000-09-04  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* include/devtab.h (cyg_devtab_entry_t): Apply CYG_HAL_TABLE_TYPE	
+
 2000-08-01  Jonathan Larmour  <jlarmour@redhat.co.uk>
 
 	* include/config_keys.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
--- a/packages/io/eth/current/ChangeLog
+++ b/packages/io/eth/current/ChangeLog
@@ -1,3 +1,40 @@
+2000-09-01  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* 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  <hmt@cygnus.co.uk>
+
+	* 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  <gthomas@redhat.com>
 
 	* src/stand_alone/eth_drv.c: Use null buffer, (char *)0,
--- 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,                                 \
     &eth_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;
 
--- 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 <pkgconf/hal.h>
 #include <cyg/hal/hal_if.h>
 #include <eth_drv.h>
+#include <netdev.h>
 
 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 * 
--- 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
--- a/packages/io/fileio/current/ChangeLog
+++ b/packages/io/fileio/current/ChangeLog
@@ -1,3 +1,9 @@
+2000-09-04  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* 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  <nickg@cygnus.co.uk>
 
 	* src/select.cxx (select): Added scheduler unlock in timeout
--- 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
--- 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) =                          \
--- a/packages/io/flash/current/ChangeLog
+++ b/packages/io/flash/current/ChangeLog
@@ -1,3 +1,9 @@
+2000-09-01  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* 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  <gthomas@redhat.com>
 
 	* src/flash.c: 
--- 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
--- 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)
--- a/packages/language/c/libm/current/ChangeLog
+++ b/packages/language/c/libm/current/ChangeLog
@@ -1,3 +1,7 @@
+2000-09-01  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* src/misc/infconst.c: Silence warning about number of brackets
+
 2000-08-31  Jonathan Larmour  <jlarmour@redhat.com>
 
 	* include/math.h: Declare cyg_libm_infinity as an array type for correct
--- 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
 
--- a/packages/net/tcpip/current/ChangeLog
+++ b/packages/net/tcpip/current/ChangeLog
@@ -1,3 +1,54 @@
+2000-09-01  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* 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  <hmt@cygnus.co.uk>
+
+	* 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  <hmt@cygnus.co.uk>
 
 	* tests/tcp_echo.c: Change the priorities of the main and loading
--- 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 == "<sys/bsdtypes.h>" }
     
     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
--- 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
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 <sys/param.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/domain.h>
+#include <sys/protosw.h>
+#include <sys/sockio.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <net/netisr.h>
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#include <arpa/inet.h>
+
+#include <machine/cpu.h>
+
+#include <pkgconf/net.h>
+
+#include <cyg/infra/diag.h>
+#include <cyg/hal/hal_intr.h>
+#include <cyg/kernel/kapi.h>
+
+#include <cyg/infra/cyg_ass.h>
+
+#include <netdev.h>
+
+//---------------------------- 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
--- 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
--- 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 */
--- a/packages/redboot/current/ChangeLog
+++ b/packages/redboot/current/ChangeLog
@@ -1,3 +1,14 @@
+2000-09-04  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* 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  <hmt@cygnus.co.uk>
+
+	* 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  <gthomas@redhat.com>
 
 	* src/flash.c: Support block locking if available.
--- 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
 
--- 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_)
--- 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 <flash_addr> -l <length>",
@@ -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[])