changeset 88:afdeb44241de ecos-sw-2000-05-12

Merge from eCos master repository on 2000-05-12-07:47:04-BST
author jlarmour
date Fri, 12 May 2000 17:53:32 +0000
parents 008177d90c43
children fb6e7cf186a5
files host/tools/ecostest/common/eCosTestDownloadFilter.cpp host/tools/ecostest/common/eCosTestMonitorFilter.cpp host/tools/ecostest/common/eCosTestSerialFilter.cpp packages/compat/uitron/current/ChangeLog packages/compat/uitron/current/tests/testintr.cxx packages/devs/eth/arm/ebsa285/current/ChangeLog packages/devs/eth/arm/ebsa285/current/cdl/ebsa285_eth_drivers.cdl packages/devs/eth/arm/ebsa285/current/src/if_ebsa285.c packages/devs/eth/arm/ebsa285/current/tests/test_net_realtime.h packages/ecos.db packages/hal/mips/arch/current/ChangeLog packages/hal/mips/arch/current/include/arch.inc packages/hal/mips/arch/current/include/basetype.h packages/hal/mips/jmr3904/current/ChangeLog packages/hal/mips/jmr3904/current/include/pkgconf/mlt_mips_tx39_jmr3904_rom.ldi packages/hal/mips/jmr3904/current/include/pkgconf/mlt_mips_tx39_jmr3904_rom.mlt packages/hal/sh/arch/current/ChangeLog packages/hal/sh/arch/current/cdl/hal_sh.cdl packages/io/serial/current/ChangeLog packages/io/serial/current/cdl/io_serial.cdl packages/io/serial/current/src/common/serial.c packages/language/c/libc/current/tests/signal/signal2.c
diffstat 22 files changed, 746 insertions(+), 216 deletions(-) [+]
line wrap: on
line diff
--- a/host/tools/ecostest/common/eCosTestDownloadFilter.cpp
+++ b/host/tools/ecostest/common/eCosTestDownloadFilter.cpp
@@ -53,7 +53,7 @@
 #include "eCosStd.h"
 #include "eCosTrace.h"
 
-#define DL_FILTER_VER "$Id: eCosTestDownloadFilter.cpp,v 1.6 2000/05/05 17:31:08 jlarmour Exp $"
+#define DL_FILTER_VER "$Id: eCosTestDownloadFilter.cpp,v 1.7 2000/05/12 17:53:32 jlarmour Exp $"
 #include "eCosTestDownloadFilter.h"
 
 CeCosTestDownloadFilter::CeCosTestDownloadFilter():
--- a/host/tools/ecostest/common/eCosTestMonitorFilter.cpp
+++ b/host/tools/ecostest/common/eCosTestMonitorFilter.cpp
@@ -45,7 +45,7 @@
 
 #include "eCosStd.h"
 
-#define SER_FILTER_VER "$Id: eCosTestMonitorFilter.cpp,v 1.5 2000/05/05 17:31:08 jlarmour Exp $"
+#define SER_FILTER_VER "$Id: eCosTestMonitorFilter.cpp,v 1.6 2000/05/12 17:53:32 jlarmour Exp $"
 #include "eCosTestMonitorFilter.h"
 
 CeCosTestMonitorFilter::CeCosTestMonitorFilter():
--- a/host/tools/ecostest/common/eCosTestSerialFilter.cpp
+++ b/host/tools/ecostest/common/eCosTestSerialFilter.cpp
@@ -51,7 +51,7 @@
 
 #include "eCosStd.h"
 
-#define SER_FILTER_VER "$Id: eCosTestSerialFilter.cpp,v 1.6 2000/05/05 17:31:08 jlarmour Exp $"
+#define SER_FILTER_VER "$Id: eCosTestSerialFilter.cpp,v 1.7 2000/05/12 17:53:32 jlarmour Exp $"
 #include "eCosTestSerialFilter.h"
 #include "eCosThreadUtils.h"
 
--- a/packages/compat/uitron/current/ChangeLog
+++ b/packages/compat/uitron/current/ChangeLog
@@ -1,3 +1,8 @@
+2000-05-08  Jesper Skov  <jskov@redhat.com>
+
+	* tests/testintr.cxx (attach_isr, detach_isr): Don't check for
+	clean vector after a detach when chaining is enabled.
+
 2000-03-28  Jesper Skov  <jskov@redhat.com>
 
 	* tests/testintr.cxx: Synchronize with clock before making timer
--- a/packages/compat/uitron/current/tests/testintr.cxx
+++ b/packages/compat/uitron/current/tests/testintr.cxx
@@ -785,8 +785,14 @@ attach_isr( unsigned int (*isr)(unsigned
     HAL_INTERRUPT_MASK( CYGNUM_HAL_INTERRUPT_RTC );
     HAL_DISABLE_INTERRUPTS(old_ints);
     prtc->interrupt.detach();
+#ifndef CYGIMP_KERNEL_INTERRUPTS_CHAIN
+    // Only check that the vector was cleared when there's a specific
+    // vector for the RTC.  In chain mode, other interrupt handlers
+    // may prevent the shared vector from being cleared when detaching
+    // the RTC ISR, and this assertion fails.
     HAL_INTERRUPT_IN_USE( CYGNUM_HAL_INTERRUPT_RTC, inuse );
     CYG_TEST_CHECK( !inuse, "Failed to detach clock ISR" );
+#endif
     uit_intr = Cyg_Interrupt( 
         CYGNUM_HAL_INTERRUPT_RTC,       // Vector to attach to
         1,                              // Queue priority
@@ -811,8 +817,11 @@ detach_isr( unsigned int (*isr)(unsigned
     HAL_INTERRUPT_MASK( CYGNUM_HAL_INTERRUPT_RTC );
     HAL_DISABLE_INTERRUPTS(old_ints);
     uit_intr.detach();
+#ifndef CYGIMP_KERNEL_INTERRUPTS_CHAIN
+    // See comment above in attach_isr.
     HAL_INTERRUPT_IN_USE( CYGNUM_HAL_INTERRUPT_RTC, inuse );
     CYG_TEST_CHECK( !inuse, "Failed to detach my ISR" );
+#endif
     prtc->interrupt.attach();
     HAL_INTERRUPT_IN_USE( CYGNUM_HAL_INTERRUPT_RTC, inuse );
     CYG_TEST_CHECK( inuse, "Failed to attach clock ISR" );
--- a/packages/devs/eth/arm/ebsa285/current/ChangeLog
+++ b/packages/devs/eth/arm/ebsa285/current/ChangeLog
@@ -1,3 +1,20 @@
+2000-05-11  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* cdl/ebsa285_eth_drivers.cdl: Added export of the test header
+	below, and config opts for controlling EEPROM writing and all the
+	status chatter as the device starts up.
+
+	* src/if_ebsa285.c: Reworked the code for reading and setting the
+	EEPROM that holds the MAC address.  This is very ugly, but now
+	more reliable.  Also tidied up printing cruft with neater
+	configury, and made it an option (for safety) whether it's
+	possible to write the EEPROM at all.
+
+	* tests/test_net_realtime.h: New file - it is intended to be used
+	by networking tests to verify that latency is not compromised by
+	the stack and driver.  It's very platform specific, hence the
+	location in here.  This is a preliminary version only.
+
 2000-04-27  Hugo Tyson  <hmt@cygnus.co.uk>
 
 	* src/if_ebsa285.c: A serious re-write.  This cuts out a lot of
--- a/packages/devs/eth/arm/ebsa285/current/cdl/ebsa285_eth_drivers.cdl
+++ b/packages/devs/eth/arm/ebsa285/current/cdl/ebsa285_eth_drivers.cdl
@@ -53,11 +53,44 @@ cdl_package CYGPKG_DEVS_ETH_ARM_EBSA285 
     # yes, there should be two of these "implement"s
     implements    CYGHWR_NET_DRIVERS
     implements    CYGHWR_NET_DRIVERS
-    include_dir   .
-#    include_files ; # none _exported_ whatsoever
+    include_dir   cyg/devs/eth
+
+    # none exported about the *device* but this one is used by other tests:
+    include_files tests/test_net_realtime.h
+    # and tell them that it is available
+    define_proc {
+        puts $::cdl_header \
+       "#define CYGTST_DEVS_ETH_TEST_NET_REALTIME <cyg/devs/eth/tests/test_net_realtime.h>"
+	puts $::cdl_system_header \
+       "#define CYGBLD_DEVS_ETH_DEVICE_H <pkgconf/devs_eth_arm_ebsa285.h>"
+    }
+
     description   "Ethernet driver for Intel EBSA285 with PRO/100+ boards."
     compile       -library=libextras.a if_ebsa285.c
 
+    cdl_option CYGDBG_DEVS_ETH_ARM_EBSA285_CHATTER {
+	display "Prints ethernet device status info during startup"
+	default_value 0
+	description   "
+	    The ethernet device initialization code can print lots of info
+	    to confirm that it has found the devices on the PCI bus, read
+	    the MAC address from EEPROM correctly, and so on, and also
+	    displays the mode (10/100MHz, half/full duplex) of the
+	    connection."
+    }
+
+    cdl_component CYGPKG_DEVS_ETH_ARM_EBSA285_WRITE_EEPROM {
+	display "SIOCSIFHWADDR records MAC address in EEPROM"
+	default_value 0
+	description   "
+	    The ioctl() socket call with operand SIOCSIFHWADDR sets the
+	    interface hardware address - the MAC address or ethernet
+	    address.  This option causes the new MAC address to be written
+	    into the EEPROM associated with the interface, so that the new
+	    MAC address is permanently recorded.  Doing this should be a
+	    carefully chosen decision, hence this option."
+    }
+
     cdl_component CYGPKG_DEVS_ETH_ARM_EBSA285_OPTIONS {
         display "Intel EBSA285 with PRO/100+ ethernet driver build options"
         flavor  none
@@ -75,6 +108,7 @@ cdl_package CYGPKG_DEVS_ETH_ARM_EBSA285 
                 global flags."
         }
     }
+
 }
 
 # EOF ebsa285_eth_drivers.cdl
--- a/packages/devs/eth/arm/ebsa285/current/src/if_ebsa285.c
+++ b/packages/devs/eth/arm/ebsa285/current/src/if_ebsa285.c
@@ -55,6 +55,7 @@
 //==========================================================================
 
 #include <pkgconf/system.h>
+#include <pkgconf/devs_eth_arm_ebsa285.h>
 #include <cyg/infra/cyg_type.h>
 #include <cyg/infra/cyg_ass.h>
 #include <cyg/hal/hal_arch.h>
@@ -71,8 +72,11 @@
 
 // ------------------------------------------------------------------------
 
-#define nDEBUG_82559
-#define DEBUG
+#ifdef CYGDBG_DEVS_ETH_ARM_EBSA285_CHATTER
+#define notDEBUG_82559 // This one prints stuff as packets come and go
+#define DEBUG          // Startup printing mainly
+#define DEBUG_EE       // Some EEPROM specific retries &c
+#endif
 
 #define nKEEP_STATISTICS
 #define nDISPLAY_STATISTICS
@@ -86,22 +90,22 @@
 // I/O access macros as inlines for type safety
 
 static inline void OUTB(cyg_uint8 value, cyg_uint32 io_address)
-{   *((cyg_uint8 *)io_address) = value;    }
+{   *((volatile cyg_uint8 *)io_address) = value;    }
 
 static inline void OUTW(cyg_uint16 value, cyg_uint32 io_address)
-{   *((cyg_uint16 *)io_address) = value;   }
+{   *((volatile cyg_uint16 *)io_address) = value;   }
 
 static inline void OUTL(cyg_uint32 value, cyg_uint32 io_address)
-{   *((cyg_uint32 *)io_address) = value;   }
+{   *((volatile cyg_uint32 *)io_address) = value;   }
 
 static inline cyg_uint8 INB(cyg_uint32 io_address)
-{   return *((cyg_uint8 *)io_address);     }
+{   return *((volatile cyg_uint8 *)io_address);     }
 
 static inline cyg_uint16 INW(cyg_uint32 io_address)
-{   return *((cyg_uint16 *)io_address);    }
+{   return *((volatile cyg_uint16 *)io_address);    }
 
 static inline cyg_uint32 INL(cyg_uint32 io_address)
-{   return *((cyg_uint32 *)io_address);    }
+{   return *((volatile cyg_uint32 *)io_address);    }
 
 #define VIRT_TO_BUS( _x_ ) virt_to_bus((cyg_uint32)(_x_))
 static inline cyg_uint32 virt_to_bus(cyg_uint32 p_memory)
@@ -179,8 +183,6 @@ static inline cyg_uint32 bus_to_virt(cyg
 #define EE_SHIFT_CLK	0x01            // EEPROM shift clock.
 #define EE_CS		0x02            // EEPROM chip select.
 #define EE_DATA_WRITE	0x04            // EEPROM chip data in.
-#define EE_WRITE_0	0x01
-#define EE_WRITE_1	0x05
 #define EE_DATA_READ	0x08            // EEPROM chip data out.
 #define EE_ENB		(0x4800 | EE_CS)
 
@@ -188,11 +190,21 @@ static inline cyg_uint32 bus_to_virt(cyg
 #define eeprom_delay(usec)		udelay(usec);
 
 // The EEPROM commands include the always-set leading bit.
-// (and require the local variable "addr_len", usually 6 or 8)
-#define EE_WRITE_CMD	(5 << addr_len)
-#define EE_READ_CMD	(6 << addr_len)
-#define EE_ERASE_CMD	(7 << addr_len)
-#define EE_WRITE_EN_CMD (19 << (addr_len-2))
+#define EE_WRITE_CMD(a)     (5 << (a))
+#define EE_READ_CMD(a)	    (6 << (a))
+#define EE_ERASE_CMD(a)	    (7 << (a))
+#define EE_WRITE_EN_CMD(a)  (19 << ((a)-2))
+#define EE_WRITE_DIS_CMD(a) (16 << ((a)-2))
+#define EE_ERASE_ALL_CMD(a) (18 << ((a)-2))
+
+#define EE_TOP_CMD_BIT(a)      ((a)+2) // Counts down to zero
+#define EE_TOP_DATA_BIT        (15)    // Counts down to zero
+
+#define EEPROM_ENABLE_DELAY (10) // Delay at chip select
+
+#define EEPROM_SK_DELAY  (2) // Delay between clock edges *and* data
+                             // read or transition; 3 of these per bit.
+#define EEPROM_DONE_DELAY (100) // Delay when all done
 
 
 // ------------------------------------------------------------------------
@@ -532,9 +544,9 @@ static void ResetRxRing(struct i82559* p
 static void InitTxRing(struct i82559* p_i82559);
 static void ResetTxRing(struct i82559* p_i82559);
 
-static int write_enable_eeprom(long ,  int );
+#ifdef CYGPKG_DEVS_ETH_ARM_EBSA285_WRITE_EEPROM
 static void program_eeprom(cyg_uint32 , cyg_uint32 , cyg_uint8 * );
-
+#endif
 static int eth_set_promiscuous_mode(struct i82559* p_i82559);
 
 // debugging/logging only:
@@ -548,7 +560,8 @@ void dump_packet(cyg_uint8 *p_buffer, in
 // utilities
 // ------------------------------------------------------------------------
 
-static inline void wait_for_cmd_done(long scb_ioaddr)
+static // inline
+void wait_for_cmd_done(long scb_ioaddr)
 {
     register int CSRstatus;
     register int wait = 0x100000;
@@ -654,6 +667,86 @@ static void *pciwindow_mem_alloc(int siz
 
 // ------------------------------------------------------------------------
 //
+//                       GET EEPROM SIZE
+//
+// ------------------------------------------------------------------------
+static int get_eeprom_size(long ioaddr)
+{
+    unsigned short retval = 0;
+    int ee_addr = ioaddr + SCBeeprom;
+    int i, addrbits;
+
+    // Should already be not-selected, but anyway:
+    OUTW(EE_ENB & ~EE_CS, ee_addr);
+    eeprom_delay(EEPROM_ENABLE_DELAY);
+    OUTW(EE_ENB, ee_addr);
+    eeprom_delay(EEPROM_ENABLE_DELAY);
+    
+    // Shift the read command bits out.
+    for (i = 2; i >= 0; i--) {
+        short dataval = (6 & (1 << i)) ? EE_DATA_WRITE : 0;
+        OUTW(EE_ENB | dataval               , ee_addr);
+        eeprom_delay(EEPROM_SK_DELAY);
+        OUTW(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+        eeprom_delay(EEPROM_SK_DELAY);
+        OUTW(EE_ENB | dataval               , ee_addr);
+        eeprom_delay(EEPROM_SK_DELAY);
+    }
+    // Now clock out address zero, looking for the dummy 0 data bit
+    for ( i = 1; i <= 12; i++ ) {
+        OUTW(EE_ENB               , ee_addr);
+        eeprom_delay(EEPROM_SK_DELAY);
+        OUTW(EE_ENB | EE_SHIFT_CLK, ee_addr);
+        eeprom_delay(EEPROM_SK_DELAY);
+        OUTW(EE_ENB               , ee_addr);
+        eeprom_delay(EEPROM_SK_DELAY);
+        retval = INW(ee_addr) & EE_DATA_READ;
+        if ( 0 == retval )
+            break; // The dummy zero est arrive'
+    }
+
+#ifdef DEBUG_EE
+    os_printf( "eeprom data bits %d (ioaddr %x)\n", i, ee_addr );
+#endif
+    if ( 6 != i && 8 != i ) {
+#ifdef DEBUG_EE
+        os_printf( "*****EEPROM data bits not 6 or 8*****\n" );
+#endif
+        i = 6;
+    }
+    addrbits = i;
+
+    // clear the dataval, leave the clock low to read in the data regardless
+    OUTW(EE_ENB, ee_addr);
+    eeprom_delay(1);
+    
+    retval = INW(ee_addr);
+    if ( (EE_DATA_READ & retval) != 0 ) {
+#ifdef DEBUG_EE
+        os_printf( "Size EEPROM: Dummy data bit not 0, reg %x\n" , retval );
+#endif
+    }
+    eeprom_delay(1);
+    
+    for (i = EE_TOP_DATA_BIT; i >= 0; i--) {
+        OUTW(EE_ENB | EE_SHIFT_CLK, ee_addr);
+        eeprom_delay(EEPROM_SK_DELAY);
+        retval = INW(ee_addr);
+        eeprom_delay(EEPROM_SK_DELAY);
+        OUTW(EE_ENB, ee_addr);
+        eeprom_delay(EEPROM_SK_DELAY);
+    }
+    
+    // Terminate the EEPROM access.
+    OUTW(EE_ENB & ~EE_CS, ee_addr);
+    eeprom_delay(EEPROM_DONE_DELAY);
+    
+    return addrbits;
+}
+
+
+// ------------------------------------------------------------------------
+//
 //                       READ EEPROM
 //
 // ------------------------------------------------------------------------
@@ -661,35 +754,69 @@ static int read_eeprom(long ioaddr, int 
 {
     unsigned short retval = 0;
     int ee_addr = ioaddr + SCBeeprom;
-    int read_cmd = location | EE_READ_CMD;
-    int i;
+    int read_cmd = location | EE_READ_CMD(addr_len);
+    int i, tries = 10;
+
+ try_again:
+    // Should already be not-selected, but anyway:
+    OUTW(EE_ENB & ~EE_CS, ee_addr);
+    eeprom_delay(EEPROM_ENABLE_DELAY);
+    OUTW(EE_ENB, ee_addr);
+    eeprom_delay(EEPROM_ENABLE_DELAY);
     
-    OUTW(EE_ENB & ~EE_CS, ee_addr);
-    eeprom_delay(1);
+    // Shift the read command bits out, changing only one bit per time.
+    for (i = EE_TOP_CMD_BIT(addr_len); i >= 0; i--) {
+        short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+        OUTW(EE_ENB | dataval               , ee_addr);
+        eeprom_delay(EEPROM_SK_DELAY);
+        OUTW(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+        eeprom_delay(EEPROM_SK_DELAY);
+        OUTW(EE_ENB | dataval               , ee_addr);
+        eeprom_delay(EEPROM_SK_DELAY);
+    }
+
+    // clear the dataval, leave the clock low
     OUTW(EE_ENB, ee_addr);
     eeprom_delay(1);
     
-    // Shift the read command bits out.
-    for (i = 12; i >= 0; i--) {
-        short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
-        OUTW(EE_ENB | dataval, ee_addr);
-        eeprom_delay(1);
-        OUTW(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
-        eeprom_delay(1);
+    retval = INW(ee_addr);
+    // This should show a zero in the data read bit to confirm that the
+    // address transfer is compelete.  If not, go to the start and try
+    // again!
+    if ( (0 != (retval & EE_DATA_READ)) && (tries-- > 0) ) {
+    // Terminate the EEPROM access.
+        OUTW(EE_ENB & ~EE_CS, ee_addr);
+        eeprom_delay(EEPROM_DONE_DELAY);
+#ifdef DEBUG_EE
+        os_printf( "Warning: Retrying EEPROM read word %d, address %x, try %d\n",
+                   location,  ee_addr, tries+1 );
+#endif
+        goto try_again;
     }
-    OUTW(EE_ENB, ee_addr);
+
+    // This fires with one device on one of the customer boards!
+    // (but is OK on all other h/w.  Worrying huh.)
+    if ( (EE_DATA_READ & retval) != 0 ) {
+#ifdef DEBUG_EE
+        os_printf( "Read EEPROM: Dummy data bit not 0, reg %x\n" , retval );
+#endif
+    }
     eeprom_delay(1);
-    
-    for (i = 15; i >= 0; i--) {
+    retval = 0;
+
+    for (i = EE_TOP_DATA_BIT; i >= 0; i--) {
         OUTW(EE_ENB | EE_SHIFT_CLK, ee_addr);
-        eeprom_delay(1);
+        eeprom_delay(EEPROM_SK_DELAY);
         retval = (retval << 1) | ((INW(ee_addr) & EE_DATA_READ) ? 1 : 0);
+        eeprom_delay(EEPROM_SK_DELAY);
         OUTW(EE_ENB, ee_addr);
-        eeprom_delay(1);
+        eeprom_delay(EEPROM_SK_DELAY);
     }
     
     // Terminate the EEPROM access.
     OUTW(EE_ENB & ~EE_CS, ee_addr);
+    eeprom_delay(EEPROM_DONE_DELAY);
+    
     return retval;
 }
 
@@ -730,7 +857,9 @@ ebsa285_i82559_init(struct cyg_netdevtab
     p_i82559 = (struct i82559 *)(sc->driver_private);
 
     IF_BAD_82559( p_i82559 ) {
+#ifdef DEBUG
         os_printf( "Bad device private pointer %x\n", sc->driver_private );
+#endif
         return 0;
     }
 
@@ -739,7 +868,9 @@ ebsa285_i82559_init(struct cyg_netdevtab
     if ( 0 == initialized++ ) {
         // then this is the first time ever:
         if ( ! pci_init_find_82559s() ) {
+#ifdef DEBUG
             os_printf( "pci_init_find_82559s failed" );
+#endif
             return 0;
         }
     }
@@ -777,7 +908,9 @@ ebsa285_i82559_init(struct cyg_netdevtab
     
     if (count < 0) {
         // Test timed out.
+#ifdef DEBUG
         os_printf("Self test failed\n");
+#endif
         return (0);
     }
 #ifdef DEBUG
@@ -793,13 +926,16 @@ ebsa285_i82559_init(struct cyg_netdevtab
 #endif
 
     // read eeprom and get 82559's mac address
-    addr_length = (read_eeprom(ioaddr, 0, 6) == 0xffff) ? 8 : 6;
+    addr_length = get_eeprom_size(ioaddr);
     // (this is the length of the *EEPROM*s address, not MAC address)
 
     for (checksum = 0, i = 0, count = 0; count < 64; count++) {
         cyg_uint16 value;
         // read word from eeprom
         value = read_eeprom(ioaddr, count, addr_length);
+#ifdef DEBUG_EE
+        // os_printf( "%2d: %04x\n", count, value );
+#endif
         checksum += value;
         if (count < 3) {
             mac_address[i++] = value & 0xFF;
@@ -816,13 +952,17 @@ ebsa285_i82559_init(struct cyg_netdevtab
 
     if ((checksum & 0xFFFF) != 0xBABA)  {
         // selftest verified checksum, verify again
+#ifdef DEBUG_EE
         os_printf( "Warning: Invalid EEPROM checksum %04X for device %d\n",
                    checksum, p_i82559->index);
+#endif
     } else {
         p_i82559->mac_addr_ok = 1;
+#ifdef DEBUG_EE
+        os_printf("Valid EEPROM checksum\n");
+#endif
     }
 #ifdef DEBUG
-    os_printf("Valid EEPROM checksum\n");
     os_printf("MAC Address = %02X %02X %02X %02X %02X %02X\n",
               mac_address[0], mac_address[1], mac_address[2], mac_address[3],
               mac_address[4], mac_address[5]);
@@ -851,8 +991,6 @@ ebsa285_i82559_init(struct cyg_netdevtab
     return (1);
 }
 
-
-
 // ------------------------------------------------------------------------
 //
 //  Function : i82559_start
@@ -872,14 +1010,18 @@ static void i82559_start( struct eth_drv
     p_i82559 = (struct i82559 *)sc->driver_private;
     
     IF_BAD_82559( p_i82559 ) {
+#ifdef DEBUG
         os_printf( "i82559_start: Bad device pointer %x\n", p_i82559 );
+#endif
         return;
     }
 
     if ( ! p_i82559->mac_addr_ok ) {
+#ifdef DEBUG
         os_printf("i82559_start %d: invalid MAC address, "
                   "can't bring up interface\n",
                   p_i82559->index );
+#endif
         return;
     }
 
@@ -934,7 +1076,6 @@ static void i82559_start( struct eth_drv
 #endif
 }
 
-
 // ------------------------------------------------------------------------
 //
 //  Function : BringDown82559
@@ -948,7 +1089,9 @@ static void i82559_stop( struct eth_drv_
     p_i82559 = (struct i82559 *)sc->driver_private;
 
     IF_BAD_82559( p_i82559 ) {
+#ifdef DEBUG
         os_printf( "i82559_stop: Bad device pointer %x\n", p_i82559 );
+#endif
         return;
     }
    
@@ -1117,7 +1260,9 @@ static void i82559_recv( struct eth_drv_
     p_i82559 = (struct i82559 *)sc->driver_private;
     
     IF_BAD_82559( p_i82559 ) {
+#ifdef DEBUG
         os_printf( "i82559_recv: Bad device pointer %x\n", p_i82559 );
+#endif
         return;
     }
 
@@ -1349,7 +1494,9 @@ i82559_can_send(struct eth_drv_sc *sc)
     p_i82559 = (struct i82559 *)sc->driver_private;
 
     IF_BAD_82559( p_i82559 ) {
+#ifdef DEBUG
         os_printf( "i82559_send: Bad device pointer %x\n", p_i82559 );
+#endif
         return 0;
     }
     
@@ -1381,7 +1528,9 @@ i82559_send(struct eth_drv_sc *sc,
     p_i82559 = (struct i82559 *)sc->driver_private;
 
     IF_BAD_82559( p_i82559 ) {
+#ifdef DEBUG
         os_printf( "i82559_send: Bad device pointer %x\n", p_i82559 );
+#endif
         return;
     }
 
@@ -1401,8 +1550,10 @@ i82559_send(struct eth_drv_sc *sc,
 #ifdef KEEP_STATISTICS
         statistics[p_i82559->index].tx_dropped++;
 #endif
+#ifdef DEBUG_82559
         os_printf( "i82559_send: Queue full, device %x, key %x\n",
                    p_i82559, key );
+#endif
     }
     else {
         struct eth_drv_sg *last_sg;
@@ -1527,7 +1678,9 @@ static cyg_uint32 eth_isr(cyg_vector_t v
     cyg_uint32 ioaddr;
 
     IF_BAD_82559( p_i82559 ) {
+#ifdef DEBUG
         os_printf( "i82559_isr: Bad device pointer %x\n", p_i82559 );
+#endif
         return 0;
     }
 
@@ -1642,7 +1795,9 @@ pci_init_find_82559s( void )
 
     // allocate memory to be used in ioctls later
     if (mem_reserved_ioctl != (void*)0) {
+#ifdef DEBUG
         db_printf("pci_init_find_82559s() called > once\n");
+#endif
         return 0;
     }
 
@@ -1657,6 +1812,7 @@ pci_init_find_82559s( void )
 #ifdef DEBUG
     db_printf("Finished cyg_pci_init();\n");
 #endif
+
     devid = CYG_PCI_NULL_DEVID;
 
     for (device_index = 0; device_index < MAX_82559; device_index++) {
@@ -1779,13 +1935,17 @@ pci_init_find_82559s( void )
             else {
                 p_i82559->found = 0;
                 p_i82559->active = 0;
+#ifdef DEBUG
                 db_printf("Failed to configure device %d\n",device_index);
+#endif
             }
         }
         else {
             p_i82559->found = 0;
             p_i82559->active = 0;
+#ifdef DEBUG
             db_printf("eth%d not found\n", device_index);
+#endif
         }
     }
 
@@ -1795,32 +1955,14 @@ pci_init_find_82559s( void )
         cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_PCI_IRQ);
     }
 
+    // Now a delay to ensure the hardware has "come up" before you try to
+    // use it.  Yes, really, the full 2 seconds.  It's only really
+    // necessary if DEBUG is off - otherwise all that printout wastes
+    // enough time.  No kidding.
+    udelay( 2000000 );
     return 1;
 }
 
-
-// ------------------------------------------------------------------------
-// We use this as a templete when writing a new MAC address into the
-// eeproms. The MAC address in the first few bytes is over written
-// with the correct MAC address and then the whole lot is programmed
-// into the serial EEPROM. The checksum is calculated on the fly and
-// sent instead of the last two bytes.
-
-static char eeprom_burn[126] = { 
-  0x00, 0x90, 0x27, 0x8c, 0x57, 0x82, 0x03, 0x02, 0x00, 0x00, 0x01,
-  0x02, 0x01, 0x47, 0x00, 0x00, 0x13, 0x72, 0x06, 0x83, 0xa2, 0x40,
-  0x0c, 0x00, 0x86, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x01, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00 
-};
-
 // ------------------------------------------------------------------------
 //
 //  Function : eth_set_promiscuous_mode
@@ -1835,8 +1977,10 @@ static int eth_set_promiscuous_mode(stru
     volatile CONFIG_CMD_STRUCT *ccs;
 
     IF_BAD_82559( p_i82559 ) {
+#ifdef DEBUG
         os_printf( "eth_set_promiscuos_mode: Bad device pointer %x\n",
                    p_i82559 );
+#endif
         return -1;
     }
 
@@ -1903,6 +2047,42 @@ static int eth_set_promiscuous_mode(stru
 }
 
 // ------------------------------------------------------------------------
+// We use this as a templete when writing a new MAC address into the
+// eeproms. The MAC address in the first few bytes is over written
+// with the correct MAC address and then the whole lot is programmed
+// into the serial EEPROM. The checksum is calculated on the fly and
+// sent instead of the last two bytes.
+// The values are copied from the Intel EtherPro10/100+ &c devices
+// in the EBSA boards.
+
+#ifdef CYGPKG_DEVS_ETH_ARM_EBSA285_WRITE_EEPROM
+
+#define ee00 0x00, 0x00 // shorthand
+
+static char eeprom_burn[126] = { 
+/* halfword addresses! */
+/*  0: */  0x00, 0x90,   0x27, 0x8c,       0x57, 0x82,   0x03, 0x02,
+/*  4: */     ee00   ,   0x01, 0x02,       0x01, 0x47,      ee00   ,
+/*  8: */  0x13, 0x72,   0x06, 0x83,       0xa2, 0x40,   0x0c, 0x00,
+/*  C: */  0x86, 0x80,      ee00   ,          ee00   ,      ee00   ,
+/* 10: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
+/* 14: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
+/* 18: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
+/* 1C: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
+/* 20: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
+/* 24: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
+/* 28: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
+/* 2C: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
+/* 30: */  0x28, 0x01,      ee00   ,          ee00   ,      ee00   ,
+/* 34: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
+/* 38: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
+/* 3C: */     ee00   ,      ee00   ,          ee00   
+};
+#undef ee00
+
+#endif
+
+// ------------------------------------------------------------------------
 //
 //  Function : eth_set_mac_address
 //
@@ -1911,28 +2091,26 @@ static int eth_set_promiscuous_mode(stru
 // ------------------------------------------------------------------------
 static int eth_set_mac_address(struct i82559* p_i82559, char *addr)
 {
+#ifdef CYGPKG_DEVS_ETH_ARM_EBSA285_WRITE_EEPROM
+    int checksum, i, count;
+    // (this is the length of the *EEPROM*s address, not MAC address)
     int addr_length;
-  
+#endif
     cyg_uint32  ioaddr;
     volatile CONFIG_CMD_STRUCT *ccs;
   
     IF_BAD_82559( p_i82559 ) {
+#ifdef DEBUG
         os_printf( "eth_set_mac_address : Bad device pointer %x\n",
                    p_i82559 );
+#endif
         return -1;
     }
 
     ioaddr = p_i82559->io_address;      
     
     wait_for_cmd_done(ioaddr); 
-    // load cu base address = 0 */ 
-    OUTL(0, ioaddr + SCBPointer);       
-    // 32 bit linear addressing used
-                                        
-    OUTW(SCB_M | CU_ADDR_LOAD, ioaddr + SCBCmd);
-    // wait for SCB command complete
-    wait_for_cmd_done(ioaddr); 
-    
+
     ccs = (CONFIG_CMD_STRUCT *)mem_reserved_ioctl;
     if (ccs == (void*)0)
         return 2;
@@ -1956,140 +2134,181 @@ static int eth_set_mac_address(struct i8
     // Next delay seems to be required, otherwise,
     // cb_ok/cb_complete won't be set later.
 
-    udelay(100);
+    udelay(1000);
     wait_for_cmd_done(ioaddr);   
   
     // now check for result ...
     if ( (!ccs->cb_entry.cb_ok) || (!ccs->cb_entry.cb_complete) )
         return 3;
   
+#ifdef CYGPKG_DEVS_ETH_ARM_EBSA285_WRITE_EEPROM
+
+    addr_length = get_eeprom_size( ioaddr );
+
     // now set this address in the device eeprom ....
     (void)memcpy(eeprom_burn,addr,6);
-    eeprom_burn[20] &= 0xfe;   
-    eeprom_burn[20] |= p_i82559->index;   
 
-    addr_length=6; // eeprom address word length in bits ...
-    program_eeprom(ioaddr,addr_length,eeprom_burn);
+    // No idea what these were for...
+    // eeprom_burn[20] &= 0xfe;   
+    // eeprom_burn[20] |= p_i82559->index;   
+        
+    program_eeprom( ioaddr, addr_length, eeprom_burn );
    
-    // now update netword stack ...
-    // FIXME - no feedback to stack when MAC changes
+    // update 82559 driver data structure ...
+    udelay( 100000 );
+
+    // by reading EEPROM to get the mac address back
+    for (checksum = 0, i = 0, count = 0; count < 64; count++) {
+        cyg_uint16 value;
+        // read word from eeprom
+        value = read_eeprom(ioaddr, count, addr_length);
+        checksum += value;
+        if (count < 3) {
+            p_i82559->mac_address[i++] = value & 0xFF;
+            p_i82559->mac_address[i++] = (value >> 8) & 0xFF;
+        }
+    }
+    
+#ifdef DEBUG
+    os_printf("MAC Address = %02X %02X %02X %02X %02X %02X\n",
+              p_i82559->mac_address[0], p_i82559->mac_address[1],
+              p_i82559->mac_address[2], p_i82559->mac_address[3],
+              p_i82559->mac_address[4], p_i82559->mac_address[5]);
+#endif
+
+    p_i82559->mac_addr_ok = 1;
 
-    // update 82559 driver data structure ...
-    (void)memcpy((char *)(p_i82559->mac_address),addr,6);
+    for ( i = 0, count = 0; i < 6; i++ )
+        if ( p_i82559->mac_address[i] != addr[i] )
+            count++;
+
+    if ( count ) {
+#ifdef DEBUG
+        os_printf( "Warning: MAC Address read back wrong!  %d bytes differ.\n",
+                   count );
+#endif
+        p_i82559->mac_addr_ok = 0;
+    }
+
+    // If the EEPROM checksum is wrong, the MAC address read from the
+    // EEPROM is probably wrong as well. In that case, we don't set
+    // mac_addr_ok.
+    if ((checksum & 0xFFFF) != 0xBABA)  {
+#ifdef DEBUG
+        os_printf( "Warning: Invalid EEPROM checksum %04X for device %d\n",
+                   checksum, p_i82559->index);
+#endif
+        p_i82559->mac_addr_ok = 0;
+    }
+#else
     p_i82559->mac_addr_ok = 1;
-    return 0;
+#endif // ! CYGPKG_DEVS_ETH_ARM_EBSA285_WRITE_EEPROM
+
+    return p_i82559->mac_addr_ok ? 0 : 1;
 }
 
+#ifdef CYGPKG_DEVS_ETH_ARM_EBSA285_WRITE_EEPROM
 // ------------------------------------------------------------------------
-//
-//  Function : write_enable_eeprom
-//
+static void
+write_eeprom(long ioaddr, int location, int addr_len, unsigned short value)
+{
+    int ee_addr = ioaddr + SCBeeprom;
+    int write_cmd = location | EE_WRITE_CMD(addr_len); 
+    int i;
+    
+    OUTW(EE_ENB & ~EE_CS, ee_addr);
+    eeprom_delay( 100 );
+    OUTW(EE_ENB, ee_addr);
+    eeprom_delay( 100 );
+
+//    os_printf("\n write_eeprom : write_cmd : %x",write_cmd);  
+//    os_printf("\n addr_len : %x  value : %x ",addr_len,value);  
+
+    /* Shift the write command bits out. */
+    for (i = (addr_len+2); i >= 0; i--) {
+        short dataval = (write_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+        OUTW(EE_ENB | dataval, ee_addr);
+        eeprom_delay(100);
+        OUTW(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+        eeprom_delay(150);
+    }
+    OUTW(EE_ENB, ee_addr);
+        
+    for (i = 15; i >= 0; i--) {
+        short dataval = (value & (1 << i)) ? EE_DATA_WRITE : 0;
+        OUTW(EE_ENB | dataval, ee_addr);
+        eeprom_delay(100);
+        OUTW(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+        eeprom_delay(150);
+    }
+
+    /* Terminate the EEPROM access. */
+    OUTW(EE_ENB & ~EE_CS, ee_addr);
+    eeprom_delay(150000); // let the write take effect
+}
+
 // ------------------------------------------------------------------------
 static int write_enable_eeprom(long ioaddr,  int addr_len)
 {
     int ee_addr = ioaddr + SCBeeprom;
-    int write_en_cmd = EE_WRITE_EN_CMD; 
+    int write_en_cmd = EE_WRITE_EN_CMD(addr_len); 
     int i;
-  
+
     OUTW(EE_ENB & ~EE_CS, ee_addr);
-    eeprom_delay(1);
     OUTW(EE_ENB, ee_addr);
-    eeprom_delay(1);
 
-  
+#ifdef DEBUG_82559
+    os_printf("write_en_cmd : %x",write_en_cmd);
+#endif
+
     // Shift the wr/er enable command bits out.
     for (i = (addr_len+2); i >= 0; i--) {
-        short dataval = (write_en_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
-        OUTW(EE_ENB | dataval, ee_addr);
-        eeprom_delay(1);
-        OUTW(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
-        eeprom_delay(1);
+	short dataval = (write_en_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+	OUTW(EE_ENB | dataval, ee_addr);
+	eeprom_delay(100);
+	OUTW(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+	eeprom_delay(150);
     }
 
     // Terminate the EEPROM access.
     OUTW(EE_ENB & ~EE_CS, ee_addr);
-    eeprom_delay(1);
-    return 0;
+    eeprom_delay(EEPROM_DONE_DELAY);
+}
+
+
+// ------------------------------------------------------------------------
+static void
+program_eeprom(cyg_uint32 ioaddr, cyg_uint32 eeprom_size, cyg_uint8 *data)
+{
+  cyg_uint32 i;
+  cyg_uint16 checksum = 0;
+  cyg_uint16 value;
+
+  // First enable erase/write operations on the eeprom.
+  // This is done through the EWEN instruction.
+  write_enable_eeprom( ioaddr, eeprom_size );
+
+  for (i=0 ; i< 63 ; i++) {
+    value = ((unsigned short *)data)[i];
+    checksum += value;
+#ifdef DEBUG_82559
+    os_printf("\n i : %x ... value to be written : %x",i,value);
+#endif
+    write_eeprom( ioaddr, i, eeprom_size, value);
+#ifdef DEBUG_82559
+    os_printf("\n val read : %x ",read_eeprom(ioaddr,i,eeprom_size));
+#endif
+  }
+  value = 0xBABA - checksum;
+#ifdef DEBUG_82559
+  os_printf("\n i : %x ... checksum adjustment val to be written : %x",i,value);
+#endif
+  write_eeprom( ioaddr, i, eeprom_size, value );
 }
 
 // ------------------------------------------------------------------------
-//
-//  Function : write_eeprom
-//
-//  Return : 0 = It worked.
-//           1 = It failed.
-// ------------------------------------------------------------------------
-static int write_eeprom(long ioaddr, int location,
-                 int addr_len, unsigned short value)
-{
-    unsigned short retval = 0;
-    int ee_addr = ioaddr + SCBeeprom;
-    int write_cmd = location | EE_WRITE_CMD; 
-    int i;
-  
-    OUTW(EE_ENB & ~EE_CS, ee_addr);
-    eeprom_delay(1);
-    OUTW(EE_ENB, ee_addr);
-    eeprom_delay(1);
-
-    // Shift the write command bits out.
-    for (i = (addr_len+2); i >= 0; i--) {
-        short dataval = (write_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
-        OUTW(EE_ENB | dataval, ee_addr);
-        eeprom_delay(1);
-        OUTW(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
-        eeprom_delay(1);
-    }
-    OUTW(EE_ENB, ee_addr);
-    eeprom_delay(1);
-    
-    for (i = 15; i >= 0; i--) {
-        short dataval = (value & (1 << i)) ? EE_DATA_WRITE : 0;
-        OUTW(EE_ENB | dataval, ee_addr);
-        eeprom_delay(1);
-        OUTW(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
-        eeprom_delay(1);
-    }
+#endif // ! CYGPKG_DEVS_ETH_ARM_EBSA285_WRITE_EEPROM
 
-    // Terminate the EEPROM access.
-    OUTW(EE_ENB & ~EE_CS, ee_addr);
-    eeprom_delay(10000);
-    return retval;
-}
-
-// ------------------------------------------------------------------------
-//
-//  Function : Program EEPROM
-//  Parameters : ioaddr
-//               addr_length in bits (8 or 6)
-//               char[128] data to program
-//  Return : void
-// ------------------------------------------------------------------------
-static void program_eeprom(cyg_uint32 ioaddr,
-                    cyg_uint32 eeprom_size,
-                    cyg_uint8 * data)
-{
-    cyg_uint32 i;
-    cyg_uint16 checksum = 0;
-    cyg_uint16 value;
-    cyg_uint16 * cyg_uint16_data = (cyg_uint16 *) data;
-
-    // first enable erase/write operations on the eeprom ...
-    // this is done through the EWEN instruction ...
-
-    write_enable_eeprom(ioaddr,eeprom_size);
-  
-    // Now write the bytes, except the checksum
-    for (i=0 ; i< 63 ; i++) {
-        value = ((unsigned short*)cyg_uint16_data)[i];
-        checksum += value;
-        write_eeprom(ioaddr,i,eeprom_size,value);
-    }
-  
-    // Work out the checksum and program it
-    value = 0xBABA - checksum;
-    write_eeprom(ioaddr,i,eeprom_size,value);
-}
 
 // ------------------------------------------------------------------------
 //
@@ -2100,13 +2319,15 @@ static void program_eeprom(cyg_uint32 io
 static int eth_get_mac_address(struct i82559* p_i82559, char *addr)
 {
     IF_BAD_82559( p_i82559 ) {
+#ifdef DEBUG
         os_printf( "eth_get_mac_address : Bad device pointer %x\n",
                    p_i82559 );
+#endif
         return -1;
     }
 
     memcpy( addr, (char *)(&p_i82559->mac_address[0]), 6 );
-    return (0);
+    return 0;
 }
 #endif
 // ------------------------------------------------------------------------
@@ -2122,24 +2343,29 @@ static int i82559_ioctl(struct eth_drv_s
     p_i82559 = (struct i82559 *)sc->driver_private;
 
     IF_BAD_82559( p_i82559 ) {
+#ifdef DEBUG
         os_printf( "i82559_ioctl/control: Bad device pointer %x\n", p_i82559 );
+#endif
         return -1;
     }
 
+#ifdef DEBUG
+    db_printf( "i82559_ioctl: device eth%d at %x; key is 0x%x, data at %x[%d]\n",
+               p_i82559->index, p_i82559, key, data, data_length );
+#endif
+
     switch ( key ) {
 
 #ifdef ETH_DRV_SET_MAC_ADDRESS
     case ETH_DRV_SET_MAC_ADDRESS:
         if ( 6 != data_length )
             return -2;
-        eth_set_mac_address( p_i82559, data );
-        return 0;
+        return eth_set_mac_address( p_i82559, data );
 #endif
 
 #ifdef ETH_DRV_GET_MAC_ADDRESS
     case ETH_DRV_GET_MAC_ADDRESS:
-        eth_get_mac_address( p_i82559, data );
-        return 0;
+        return eth_get_mac_address( p_i82559, data );
 #endif
 
     default:
@@ -2168,7 +2394,6 @@ void dump_txcb(TxCB *p_txcb)
     os_printf("tbd number = %d\n", p_txcb->tbd_number);
 }
 
-
 // This is intended to be the body of a THREAD that prints stuff every 10
 // seconds or so:
 #ifdef KEEP_STATISTICS
new file mode 100644
--- /dev/null
+++ b/packages/devs/eth/arm/ebsa285/current/tests/test_net_realtime.h
@@ -0,0 +1,229 @@
+#ifndef CYGONCE_DEVS_ETH_ARM_EBSA285_TESTS_TEST_NET_REALTIME_H
+#define CYGONCE_DEVS_ETH_ARM_EBSA285_TESTS_TEST_NET_REALTIME_H
+
+/*==========================================================================
+//
+//        test_net_realtime.h
+//
+//        Auxiliary test header file
+//        Provide a thread that runs on EBSA only, which verifies that
+//        realtime characteristics are preserved.
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     hmt
+// Contributors:  hmt
+// Date:          2000-05-03
+// Description:
+//
+//####DESCRIPTIONEND####
+*/
+
+// This file rather assumes that the network is in use, and that therefore
+// there is also a kernel, and so on....
+
+#include <cyg/kernel/kapi.h>            // Thread API
+
+#include <cyg/hal/hal_arch.h>           // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/hal/hal_intr.h>           // Interrupt names
+#include <cyg/hal/hal_ebsa285.h>        // Hardware definitions
+
+// The EBSA has 4 hardware timers; timer 3 is the kernel's realtime clock
+// because it is connected to a separate, indepenent 3.68MHz signal; timer
+// 4 can be used as a watchdog.  So we have timers 1 and 2 to use.
+// Timers 1 and 2 have an input clock of 50MHz on fclk_in.
+// Timer 2 should be initialized for periodic interrupts per 500uS.
+// Timer 1 should be initialized for a one-shot interrupt after 1mS (1000uS).
+//
+// Timer 2's ISR examines the state of timer 1; if it has expired, the test
+// has failed.  7 out of 8 hits, timer 1 is reinitialized for the 1mS; on
+// the 8th event, timer1 is set for 2mS.  The next timer 2 event calls its
+// DSR, which in turn signals a semaphore which awakens a real task, which
+// again checks and re-initializes timer1 in the same way.
+//
+// All this ensures that interrupts are never delayed by more than 500uS,
+// and that signalling a real task always takes less than 1500uS.
+//
+// This system, once activated, will run non-intrusively along with all
+// networking tests.
+//
+// Special care (aka a hack) may be needed to make it work with the
+// diagnostic channel; that disables interrupts typically for
+//   100[characters] * 8[bits/byte] / 38400[Baud]  [Seconds] = 20mS.
+
+// Use the fclk_in divided-by 256 mode:
+#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)
+
+#define TNR_TIMER1_INIT   (0x88)  // Enabled, free running, fclk_in/256
+#define TNR_TIMER2_INIT   (0xc8)  // Enabled, periodic, fclk_in/256
+
+// This way, if timer1 is > TNR_TIMER1_PERIOD_2mS, then we know it has
+// wrapped; its full range is 85 seconds, one would hope to get back in
+// that time!
+
+static volatile int tnr_active = 0;
+static volatile int tnr_t2_counter = 0;
+
+static  cyg_sem_t tnr_sema;
+
+static char tnr_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+static cyg_thread tnr_thread_data;
+static cyg_handle_t tnr_thread_handle;
+
+static cyg_interrupt tnr_t1_intr, tnr_t2_intr;
+static cyg_handle_t tnr_t1_inth, tnr_t2_inth;
+
+
+
+static cyg_uint32 tnr_timer1_isr(cyg_vector_t vector, cyg_addrword_t data)
+{
+    if ( tnr_active )
+        CYG_TEST_FAIL( "test_net_realtime: Timer1 fired" );
+
+    *SA110_TIMER1_CLEAR = 0; // Clear any pending interrupt (Data: don't care)
+    HAL_INTERRUPT_ACKNOWLEDGE( CYGNUM_HAL_INTERRUPT_TIMER_1 );
+
+    return CYG_ISR_HANDLED;
+}
+
+static cyg_uint32 tnr_timer2_isr(cyg_vector_t vector, cyg_addrword_t data)
+{
+    *SA110_TIMER2_CLEAR = 0; // Clear any pending interrupt (Data: don't care)
+    HAL_INTERRUPT_ACKNOWLEDGE( CYGNUM_HAL_INTERRUPT_TIMER_2 );
+
+    if ( tnr_active ) {
+        if ( (*SA110_TIMER1_VALUE) > (4 * TNR_TIMER1_PERIOD_1mS) ) {
+            // Then it has wrapped around, bad bad bad
+            CYG_TEST_FAIL( "tnr_timer2_isr: Timer1 wrapped" );
+        }
+    }
+    tnr_t2_counter++;
+    // We go though each of the following states in turn:
+    switch ( tnr_t2_counter & 7 ) {
+    case 0:
+        // Then this is an 8th event:
+        *SA110_TIMER1_LOAD = TNR_TIMER1_PERIOD_2mS;
+        return CYG_ISR_HANDLED;
+    case 1:
+        return CYG_ISR_CALL_DSR; // See how long to call a DSR &c..
+        // without resetting timer1: 1500uS left now
+    default:
+        // Reset timer1 again.  By doing this in time every time it should
+        // never fire.
+        *SA110_TIMER1_LOAD = TNR_TIMER1_PERIOD_1mS;
+    }
+    return CYG_ISR_HANDLED;
+}
+    
+static void tnr_timer2_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+    if ( CYGNUM_HAL_INTERRUPT_TIMER_2 != vector )
+        CYG_TEST_FAIL( "tnr_timer2_dsr: Bad vector" );
+
+    cyg_semaphore_post( &tnr_sema );
+}
+
+static void tnr_timer2_service_thread( cyg_addrword_t param )
+{
+    while (1) {
+        cyg_semaphore_wait( &tnr_sema );
+        if ( tnr_active ) {
+            if ( (*SA110_TIMER1_VALUE) > (4 * TNR_TIMER1_PERIOD_1mS) ) {
+                // Then it has wrapped around, bad bad bad
+                CYG_TEST_FAIL( "tnr_timer2_service_thread: Timer1 wrapped" );
+            }
+        }
+        // Reset timer1 again.  By doing this in time every time it should
+        // never fire.
+        *SA110_TIMER1_LOAD = TNR_TIMER1_PERIOD_1mS;
+    }
+}
+
+
+static void tnr_init( void )
+{
+    // init the semaphore
+    cyg_semaphore_init( &tnr_sema, 0 );
+
+    // create and start the thread
+    cyg_thread_create(2,                  // Priority - just a number
+                      tnr_timer2_service_thread,
+                      0,                  // entry parameter
+                      "Test Net Realtime tnr_timer2_service_thread",
+                     &tnr_stack[0],       // Stack
+                      sizeof(tnr_stack),  // Size
+                      &tnr_thread_handle, // Handle
+                      &tnr_thread_data    // Thread data structure
+        );
+    cyg_thread_resume( tnr_thread_handle );
+
+    // set up and attach the interrupts et al...
+    cyg_interrupt_create(
+        CYGNUM_HAL_INTERRUPT_TIMER_2,   /* Vector to attach to       */
+        0,                              /* Queue priority            */
+        0,                              /* Data pointer              */
+        tnr_timer2_isr,                 /* Interrupt Service Routine */
+        tnr_timer2_dsr,                 /* Deferred Service Routine  */
+        &tnr_t2_inth,                   /* returned handle           */
+        &tnr_t2_intr                    /* put interrupt here        */
+        );
+    
+    cyg_interrupt_create(
+        CYGNUM_HAL_INTERRUPT_TIMER_1,   /* Vector to attach to       */
+        0,                              /* Queue priority            */
+        0,                              /* Data pointer              */
+        tnr_timer1_isr,                 /* Interrupt Service Routine */
+        tnr_timer2_dsr, /* re-use! */   /* Deferred Service Routine  */
+        &tnr_t1_inth,                   /* returned handle           */
+        &tnr_t1_intr                    /* put interrupt here        */
+        );
+    
+    cyg_interrupt_attach( tnr_t1_inth );
+    cyg_interrupt_attach( tnr_t2_inth );
+
+    *SA110_TIMER1_CONTROL = 0;          // Disable while we are setting up
+    *SA110_TIMER1_LOAD = TNR_TIMER1_PERIOD_2mS;
+    *SA110_TIMER1_CLEAR = 0;            // Clear any pending interrupt
+    *SA110_TIMER1_CONTROL = TNR_TIMER1_INIT;
+    *SA110_TIMER1_CLEAR = 0;            // Clear any pending interrupt again
+
+    *SA110_TIMER2_CONTROL = 0;          // Disable while we are setting up
+    *SA110_TIMER2_LOAD = TNR_TIMER2_PERIOD_500uS;
+    *SA110_TIMER2_CLEAR = 0;            // Clear any pending interrupt
+    *SA110_TIMER2_CONTROL = TNR_TIMER2_INIT;
+    *SA110_TIMER2_CLEAR = 0;            // Clear any pending interrupt again
+
+    cyg_interrupt_unmask( CYGNUM_HAL_INTERRUPT_TIMER_2 );
+    cyg_interrupt_unmask( CYGNUM_HAL_INTERRUPT_TIMER_1 );
+}
+
+#endif /* ifndef CYGONCE_DEVS_ETH_ARM_EBSA285_TESTS_TEST_NET_REALTIME_H */
+
+/* EOF test_net_realtime.h */
--- a/packages/ecos.db
+++ b/packages/ecos.db
@@ -86,7 +86,6 @@ package CYGPKG_IO_SERIAL {
            This package contains drivers for basic I/O services on
            serial devices."
 }
-
 package CYGPKG_IO_SERIAL_ARM_EBSA285 {
     alias 	      { "Intel EBSA285 serial driver"
                         devs_serial_arm_ebsa285 ebsa285_serial_driver }
@@ -293,8 +292,6 @@ eCos supports a uITRON Compatibility Lay
 many Level E (Extended) features. uITRON is the premier Japanese
 embedded RTOS standard."
 }
-
-
 package CYGPKG_LIBC {
 	alias		{ "C library" libc clib clibrary }
 	directory	language/c/libc
@@ -328,7 +325,6 @@ on the POSIX style naming e.g. EINVAL et
 the standard strerror() function to convert error codes to textual
 representation."
 }
-
 package CYGPKG_CYGMON {
     alias           { "CygMon support via eCos" cygmon }
     directory       cygmon
@@ -370,7 +366,6 @@ package CYGPKG_HAL_ARM_AEB {
 The aeb HAL package provides the support needed to run eCos on a ARM
 AEB-1 eval board."
 }
-
 package CYGPKG_HAL_ARM_EBSA285 {
 	alias		{ "Intel EBSA285 StrongARM board" hal_arm_ebsa285 arm_ebsa285_hal }
 	directory	hal/arm/ebsa285
@@ -424,7 +419,6 @@ package CYGPKG_HAL_SH_EDK7708 {
            eCos on a Hitachi SH3 EDK7708 board."
 }
 
-
 # --------------------------------------------------------------------------
 # i386 packages
 package CYGPKG_HAL_I386 {
@@ -449,7 +443,6 @@ package CYGPKG_HAL_I386_LINUX {
     	    support needed to run eCos binaries on top of the i386
     	    Linux kernel."
 }
-
 package CYGPKG_HAL_I386_PC {
 	alias		{ "i386 PC target" hal_i386_pc }
 	directory	hal/i386/pc
@@ -529,7 +522,6 @@ package CYGPKG_HAL_POWERPC_PPC60x {
            for this processor variant. It is also necessary to
            select a specific target platform HAL package."
 }
-
 package CYGPKG_HAL_POWERPC_COGENT {
 	alias		{ "Cogent CMA286/287 board" hal_powerpc_cogent powerpc_cogent_hal }
 	directory	hal/powerpc/cogent
@@ -549,7 +541,6 @@ package CYGPKG_HAL_POWERPC_FADS {
             The FADS HAL package provides the support needed to run
             eCos on a Motorola FADS board equipped with a PowerPC processor."
 }
-
 package CYGPKG_HAL_POWERPC_MBX {
 	alias		{ "Motorola MBX860/821 board" hal_powerpc_mbx powerpc_mbx_hal }
 	directory	hal/powerpc/mbx
@@ -651,7 +642,6 @@ package CYGPKG_HAL_MIPS_VR4300 {
            for this processor architecture. It is also necessary to
            select a specific target platform HAL package."
 }
-
 package CYGPKG_HAL_MIPS_VR4300_VRC4373 {
 	alias		{ "NEC VRC4373 board" hal_vrc4373 vrc4373_hal }
 	directory	hal/mips/vrc4373
@@ -714,7 +704,6 @@ package CYGPKG_HAL_MN10300_AM31_STDEVAL1
            an accurate simulation of the full hardware including I/O
            devices."
 }
-
 package CYGPKG_HAL_MN10300_AM33 {
 	alias		{ "MN10300 AM33 variant HAL" hal_mn10300_am33 mn10300_am33_hal }
 	directory	hal/mn10300/am33
@@ -738,7 +727,6 @@ package CYGPKG_HAL_MN10300_AM33_STB {
 }
 
 # ==========================================================================
-
 # --------------------------------------------------------------------------
 # ARM targets
 
@@ -763,7 +751,6 @@ target aeb {
 The aeb target provides the packages needed to run eCos on an ARM
 evaluation board (AEB-1)."
 }
-
 target ebsa285 {
 	alias { "Intel EBSA285 StrongARM board" ebsa }
 	packages { CYGPKG_HAL_ARM
@@ -798,7 +785,6 @@ target cma230 {
 The cma230 target provides the packages needed to run eCos on a Cogent 
 CMA230 (ARM7TDMI) or CMA222 (ARM710T) board."
     }
-
 # --------------------------------------------------------------------------
 # SH targets
 
@@ -815,8 +801,6 @@ target sh7708 {
            eCos on a Hitachi EDK/SH7708 board."
 }
 
-
-
 # --------------------------------------------------------------------------
 # i386 targets
 target linux {
@@ -829,7 +813,6 @@ target linux {
     	    packages needed to run eCos binaries on top of the i386
     	    Linux kernel."
 }
-
 target pc {
         alias		{ "i386 PC target" }
 	packages        { CYGPKG_HAL_I386
@@ -868,7 +851,6 @@ target sparclite_sim {
 
 # --------------------------------------------------------------------------
 # PowerPC targets
-
 target cma28x {
         alias		{ "Cogent CMA286/287 board" cma286 cma287 }
 	packages        { CYGPKG_HAL_POWERPC
@@ -891,7 +873,6 @@ target fads {
             The fads target provides the packages needed to run
             eCos on a Motorola MPC8xxFADS board."
 }
-
 target mbx {
         alias		{ "Motorola MBX860/821 board" mbx860 mbx821 }
 	packages        { CYGPKG_HAL_POWERPC
@@ -992,7 +973,6 @@ target stdeval1 {
            be used when running in the full simulator, since the simulator provides an
            accurate simulation of the hardware including I/O devices."
 }
-
 target stb {
         alias		{ "Matsushita STB board" }
 	packages        { CYGPKG_HAL_MN10300
--- a/packages/hal/mips/arch/current/ChangeLog
+++ b/packages/hal/mips/arch/current/ChangeLog
@@ -1,3 +1,10 @@
+2000-05-10  Jesper Skov  <jskov@redhat.com>
+
+	* include/arch.inc: Force assembler into MIPS3 mode before using
+	eret.
+
+	* include/basetype.h: Fix comments.
+
 2000-03-20  Jonathan Larmour  <jlarmour@redhat.co.uk>
 
 	* include/mips-stub.h: Make C++ safe
--- a/packages/hal/mips/arch/current/include/arch.inc
+++ b/packages/hal/mips/arch/current/include/arch.inc
@@ -251,6 +251,7 @@
 	.endm
 #else
 	.macro	hal_cpu_eret pc,sr
+        .set mips3
 	mtc0	\pc,epc				# put PC in EPC
 	nop
 	nop
@@ -262,6 +263,7 @@
 	sync					# settle things down
 	eret					# return
 	nop					# just to be safe
+        .set mips0
 	.endm
 #endif	
 	
--- a/packages/hal/mips/arch/current/include/basetype.h
+++ b/packages/hal/mips/arch/current/include/basetype.h
@@ -49,9 +49,9 @@
 // Characterize the architecture
 
 #if defined(CYGPKG_HAL_MIPS_MSBFIRST)
-# define CYG_BYTEORDER           CYG_MSBFIRST    // Little endian
+# define CYG_BYTEORDER           CYG_MSBFIRST    // Big endian
 #elif defined(CYGPKG_HAL_MIPS_LSBFIRST)
-# define CYG_BYTEORDER           CYG_LSBFIRST    // Big endian
+# define CYG_BYTEORDER           CYG_LSBFIRST    // Little endian
 #else
 # error MIPS endianess not defined by configuration
 #endif
--- a/packages/hal/mips/jmr3904/current/ChangeLog
+++ b/packages/hal/mips/jmr3904/current/ChangeLog
@@ -1,3 +1,9 @@
+2000-05-10  Jonathan Larmour  <jlarmour@redhat.co.uk>
+
+	* include/pkgconf/mlt_mips_tx39_jmr3904_rom.mlt: Fix mistake in last
+	change: bss/sbss shouldn't be relocated
+	* include/pkgconf/mlt_mips_tx39_jmr3904_rom.ldi: Regenerate
+
 2000-04-04  Jonathan Larmour  <jlarmour@redhat.co.uk>
 
 	* include/pkgconf/mlt_mips_tx39_jmr3904_rom.ldi: 
--- a/packages/hal/mips/jmr3904/current/include/pkgconf/mlt_mips_tx39_jmr3904_rom.ldi
+++ b/packages/hal/mips/jmr3904/current/include/pkgconf/mlt_mips_tx39_jmr3904_rom.ldi
@@ -1,4 +1,4 @@
-// eCos memory layout - Mon Apr 03 20:58:39 2000
+// eCos memory layout - Wed May 10 18:37:59 2000
 
 // This is a generated file - do not edit
 
@@ -31,7 +31,7 @@ SECTIONS
     SECTION_sdata (ram, ALIGN (0x8), FOLLOWING (.dynamic))
     SECTION_lit8 (ram, ALIGN (0x8), FOLLOWING (.sdata))
     SECTION_lit4 (ram, ALIGN (0x8), FOLLOWING (.lit8))
-    SECTION_sbss (ram, ALIGN (0x8), FOLLOWING (.lit4))
-    SECTION_bss (ram, ALIGN (0x8), FOLLOWING (.sbss))
+    SECTION_sbss (ram, ALIGN (0x8), LMA_EQ_VMA)
+    SECTION_bss (ram, ALIGN (0x8), LMA_EQ_VMA)
     SECTIONS_END
 }
--- a/packages/hal/mips/jmr3904/current/include/pkgconf/mlt_mips_tx39_jmr3904_rom.mlt
+++ b/packages/hal/mips/jmr3904/current/include/pkgconf/mlt_mips_tx39_jmr3904_rom.mlt
@@ -12,9 +12,9 @@ section got 0 8 1 1 0 1 0 1 dynamic dyna
 section dynamic 0 8 1 1 0 1 0 1 sdata sdata !
 section sdata 0 8 1 1 0 1 0 1 lit8 lit8 !
 section lit8 0 8 1 1 0 1 0 1 lit4 lit4 !
-section lit4 0 8 1 1 0 1 0 1 sbss sbss !
-section sbss 0 8 1 1 0 1 0 1 bss bss !
-section bss 0 8 1 1 0 0 0 0 !
+section lit4 0 8 1 1 0 1 0 0 sbss !
+section sbss 0 8 0 1 0 1 0 1 bss bss !
+section bss 0 8 0 1 0 0 0 0 !
 section rom_vectors 0 1 0 1 1 1 1 1 bfc00000 bfc00000 ROMISC ROMISC !
 section ROMISC 0 8 0 1 0 1 0 1 RELOCS RELOCS !
 section RELOCS 0 8 0 1 0 1 0 1 init init !
--- a/packages/hal/sh/arch/current/ChangeLog
+++ b/packages/hal/sh/arch/current/ChangeLog
@@ -1,3 +1,8 @@
+2000-05-08  Jesper Skov  <jskov@redhat.com>
+
+	* cdl/hal_sh.cdl: Make sure CPU variant definition ends up in
+	system.h
+
 2000-04-26  Jesper Skov  <jskov@redhat.com>
 
 	* src/hal_mk_defs.c: Added some caching data.
--- a/packages/hal/sh/arch/current/cdl/hal_sh.cdl
+++ b/packages/hal/sh/arch/current/cdl/hal_sh.cdl
@@ -95,6 +95,8 @@ cdl_package CYGPKG_HAL_SH {
         display       "SH 7708 microprocessor"
         implements    CYGINT_HAL_SH_VARIANT
         default_value 0
+        no_define
+        define        -file=system.h CYGPKG_HAL_SH_7708
         description "
             The SH3 7708 microprocessor. This is an embedded part that in
             addition to the SH3 processor core has built in peripherals
--- a/packages/io/serial/current/ChangeLog
+++ b/packages/io/serial/current/ChangeLog
@@ -1,3 +1,11 @@
+2000-05-08  Jesper Skov  <jskov@redhat.com>
+
+    	* cdl/io_serial.cdl: active_if CYGPKG_IO
+
+2000-05-05  Jonathan Larmour  <jlarmour@redhat.co.uk>
+
+	* src/common/serial.c (serial_get_config): Tidy below change a little
+
 2000-05-05  Grant Edwards  <grante@visi.com>
 
 	* src/common/serial.c (serial_get_config): Support
--- a/packages/io/serial/current/cdl/io_serial.cdl
+++ b/packages/io/serial/current/cdl/io_serial.cdl
@@ -42,6 +42,7 @@
 
 cdl_package CYGPKG_IO_SERIAL {
     display       "Serial device drivers"
+    active_if     CYGPKG_IO
     requires      CYGPKG_ERROR
     include_dir   cyg/io
     description   "
--- a/packages/io/serial/current/src/common/serial.c
+++ b/packages/io/serial/current/src/common/serial.c
@@ -297,18 +297,18 @@ serial_get_config(cyg_io_handle_t handle
             *len = sizeof(cyg_serial_buf_info_t);
             p = (cyg_serial_buf_info_t *)xbuf;
             
-            p->rx_bufsize = chan->in_cbuf.len;
+            p->rx_bufsize = in_cbuf->len;
             if (p->rx_bufsize) {
-                p->rx_count = chan->in_cbuf.put - chan->in_cbuf.get;
+                p->rx_count = in_cbuf->put - in_cbuf->get;
                 if (p->rx_count < 0) 
                     p->rx_count += p->rx_bufsize;
             }
             else
                 p->rx_count = 0;
             
-            p->tx_bufsize = chan->out_cbuf.len;
+            p->tx_bufsize = out_cbuf->len;
             if (p->tx_bufsize) {
-                p->tx_count = chan->out_cbuf.put - chan->out_cbuf.get;
+                p->tx_count = out_cbuf->put - out_cbuf->get;
                 if (p->tx_count < 0) 
                     p->tx_count += p->tx_bufsize;
             }
--- a/packages/language/c/libc/current/tests/signal/signal2.c
+++ b/packages/language/c/libc/current/tests/signal/signal2.c
@@ -244,7 +244,7 @@ main( int argc, char *argv[] )
     state = 3;
 
 #if 0
-#elif defined(CYGPKG_HAL_SH_EDK7708)
+#elif defined(CYGPKG_HAL_SH_7708)
     CYG_TEST_PASS("Test 3 not applicable to sh 7708");
 #elif defined(CYGPKG_HAL_MN10300)
     CYG_TEST_PASS("Test 3 not applicable to mn10300");