changeset 84:489eb5632bc3 ecos-sw-2000-04-28

Merge from eCos master repository on 2000-04-28-18:44:39-BST
author jlarmour
date Fri, 28 Apr 2000 18:18:36 +0000
parents 1094d5fdd3e0
children 142b52c7e568
files host/libcdl/ChangeLog host/libcdl/infer.cxx host/tools/Utils/ChangeLog host/tools/Utils/common/Subprocess.cpp host/tools/Utils/common/Subprocess.h host/tools/configtool/ChangeLog host/tools/configtool/standalone/common/cdl_exec.cxx host/tools/ecostest/ChangeLog host/tools/ecostest/common/ResetAttributes.cpp host/tools/ecostest/common/eCosTest.cpp host/tools/ecostest/common/eCosTestDownloadFilter.cpp host/tools/ecostest/common/eCosTestMonitorFilter.cpp host/tools/ecostest/common/eCosTestSerialFilter.cpp packages/compat/uitron/current/tests/testintr.cxx packages/devs/eth/arm/ebsa285/current/ChangeLog packages/devs/eth/arm/ebsa285/current/src/if_ebsa285.c packages/ecos.db packages/hal/sh/arch/current/ChangeLog packages/hal/sh/arch/current/include/hal_cache.h packages/hal/sh/arch/current/include/hal_intr.h packages/hal/sh/arch/current/src/hal_mk_defs.c packages/hal/sh/arch/current/src/vectors.S packages/io/serial/current/ChangeLog packages/io/wallclock/current/ChangeLog packages/io/wallclock/current/src/wallclock.cxx packages/kernel/current/ChangeLog packages/kernel/current/include/kapi.h packages/kernel/current/src/common/kapi.cxx packages/kernel/current/tests/clockcnv.cxx packages/kernel/current/tests/kcache1.c
diffstat 30 files changed, 1134 insertions(+), 861 deletions(-) [+]
line wrap: on
line diff
--- a/host/libcdl/ChangeLog
+++ b/host/libcdl/ChangeLog
@@ -1,3 +1,9 @@
+2000-04-14  Bart Veer  <bartv@redhat.com>
+
+	* infer.cxx (infer_set_valuable_value):
+	Extend the == operator inference support to cope with bool and
+	booldata options.
+
 2000-04-11  Bart Veer  <bartv@redhat.com>
 
 	* infer.cxx (infer_make_active):
--- a/host/libcdl/infer.cxx
+++ b/host/libcdl/infer.cxx
@@ -328,15 +328,55 @@ infer_set_valuable_value(CdlTransaction 
 
     const CdlValue& current_value = transaction->get_whole_value(valuable);
     CdlValueFlavor  flavor        = current_value.get_flavor();
+    bool bool_goal                = goal.get_bool_value();
 
-    // For now only deal with data items. Interpreter a simple value
-    // so that it is relevant for booleans etc. can come later.
-    if (CdlValueFlavor_Data == flavor) {
+    switch(flavor) {
+      default                  :
+      case CdlValueFlavor_None :
+          break;
+
+      case CdlValueFlavor_Bool :
+          if (bool_goal == current_value.is_enabled()) {
+              result = true;
+          } else {
+              if (valuable->is_modifiable() &&
+                  (0 == dynamic_cast<CdlLoadable>(valuable)) &&
+                  !transaction->changed_by_user(valuable)) {
+
+                  valuable->set_enabled(transaction, bool_goal, CdlValueSource_Inferred);
+                  valuable->set_source(transaction, CdlValueSource_Inferred);
+                  result = transaction->resolve_recursion(level);
+              }
+
+          }
+          break;
+
+      case CdlValueFlavor_BoolData :
+          if (!bool_goal && !current_value.is_enabled()) {
+              result = true;
+          } else if (bool_goal && current_value.is_enabled() && (goal == current_value.get_simple_value())) {
+              result = true;
+          } else {
+              if (valuable->is_modifiable() &&
+                  (0 == dynamic_cast<CdlLoadable>(valuable)) &&
+                  !transaction->changed_by_user(valuable)) {
+                  
+                  if (!bool_goal) {
+                      valuable->disable(transaction, CdlValueSource_Inferred);
+                  } else {
+                      valuable->enable_and_set_value(transaction, goal, CdlValueSource_Inferred);
+                  }
+                  valuable->set_source(transaction, CdlValueSource_Inferred);
+                  result = transaction->resolve_recursion(level);
+              }
+          }
+          break;
+
+      case CdlValueFlavor_Data:
         // Now check whether or not the valuable already has the desired value
         if (goal == current_value.get_simple_value()) {
             result = true;
         } else {
-
             if (valuable->is_modifiable() &&
                 (0 == dynamic_cast<CdlLoadable>(valuable)) &&
                 !transaction->changed_by_user(valuable)) {
@@ -347,6 +387,7 @@ infer_set_valuable_value(CdlTransaction 
                 result = transaction->resolve_recursion(level);
             }
         }
+        break;
     }
     
     CYG_REPORT_RETVAL(result);
--- a/host/tools/Utils/ChangeLog
+++ b/host/tools/Utils/ChangeLog
@@ -1,3 +1,9 @@
+2000-04-14 Simon FitzMaurice <sdf@redhat.co.uk>
+  * common\Subprocess.cpp
+    common\Subprocess.h
+
+  Always attempt to kill a process explicitly (don't let Cygwin processes linger)
+
 2000-04-13 Simon FitzMaurice <sdf@redhat.co.uk>
   * common\eCosSerial.cpp
     common\eCosSocket.cpp
--- a/host/tools/Utils/common/Subprocess.cpp
+++ b/host/tools/Utils/common/Subprocess.cpp
@@ -68,9 +68,9 @@ CSubprocess::CSubprocess(bool bAutoDelet
   m_pfnLogfunc(0),
   m_bKillThread(false)
 {
-  #ifdef _WIN32
-  InitializeCriticalSection(&m_cs);
-  #endif
+#ifdef _WIN32
+  m_hProcess=0;
+#endif
 }
 
 CSubprocess::~CSubprocess()
@@ -80,9 +80,11 @@ CSubprocess::~CSubprocess()
     m_bKillThread=true;
     CeCosThreadUtils::WaitFor(m_bThreadTerminated);  
   }
-  #ifdef _WIN32
-  DeleteCriticalSection(&m_cs);
-  #endif
+#ifdef _WIN32
+  if(m_hProcess){
+    CloseHandle(m_hProcess);
+  }
+#endif
 }
 
 bool CSubprocess::Run(LogFunc *pfnLog,void * pLogparam, LPCTSTR pszCmd,bool bBlock/*=true*/)
@@ -96,6 +98,10 @@ bool CSubprocess::Run(LogFunc *pfnLog,vo
 #ifdef _WIN32 
     // UNIX does it from the thread func.  WIN32 could too, but it's nice to know at the time 
     // of calling run whether the process is successfully created.
+    if(m_hProcess){
+      // Normally done in the dtor
+      CloseHandle(m_hProcess);
+    }
     rc=CreateProcess(pszCmd);
 #else 
     m_strCmd=pszCmd;
@@ -224,7 +230,7 @@ bool CSubprocess::CreateProcess(LPCTSTR 
     if(m_bVerbose){
       Output(String::SFormat(_T("*** Process %d created \"%s\"\n"),m_idProcess,pszCmdline));
     }
-    TRACE(String::SFormat(_T("*** Process %d created \"%s\"\n"),m_idProcess,pszCmdline));
+    TRACE(String::SFormat(_T("Process %d created \"%s\"\n"),m_idProcess,pszCmdline));
     m_nExitCode=STILL_ACTIVE;
     CloseHandle(pi.hThread);
   } else {
@@ -232,7 +238,7 @@ bool CSubprocess::CreateProcess(LPCTSTR 
     if(m_bVerbose){
       Output(String::SFormat(_T("*** Failed to create process \"%s\" %s\n"),pszCmdline,(LPCTSTR)ErrorString()));
     }
-    TRACE(String::SFormat(_T("*** Failed to create process \"%s\" %s\n"),pszCmdline,(LPCTSTR)ErrorString()));
+    TRACE(String::SFormat(_T("Failed to create process \"%s\" %s\n"),pszCmdline,(LPCTSTR)ErrorString()));
     m_nExitCode=GetLastError();
     CloseHandle(m_hrPipe);m_hrPipe=INVALID_HANDLE_VALUE;
     CloseHandle(m_hwPipe);m_hwPipe=INVALID_HANDLE_VALUE;
@@ -301,10 +307,6 @@ void CSubprocess::ThreadFunc()
 
   CloseHandle(m_hrPipe);m_hrPipe=INVALID_HANDLE_VALUE;
   CloseHandle(m_hwPipe);m_hwPipe=INVALID_HANDLE_VALUE;
-  EnterCriticalSection(&m_cs);
-  CloseHandle(m_hProcess);
-  m_hProcess=0; // Do not use INVALID_HANDLE_VALUE, which is also the pseudo-handle returned by GetCurrentProcess()
-  LeaveCriticalSection(&m_cs);
   
   if(m_bAutoDelete){
     m_bThreadTerminated=true; // or else the dtor will block
@@ -496,13 +498,12 @@ TRACE(_T("CSubprocess::Kill pid %d recur
     
 #ifdef _WIN32
 
-    EnterCriticalSection(&m_cs); // because the thread func may be closing it
     if(m_hProcess){
-      TRACE(_T("Terminate m_idProcess %d [%s]\n"),m_idProcess,(LPCTSTR)Name(m_idProcess));
+      TRACE(_T("Terminate process %s\n"),(LPCTSTR)Name(m_idProcess));
       rc=(TRUE==::TerminateProcess(m_hProcess,PROCESS_KILL_EXIT_CODE));
-      // Threadfunc's responsibility alone to close the handle
+      // dtor's (or subsequent Run's) responsibility to close the handle
     }
-    LeaveCriticalSection(&m_cs);
+
 #else
     rc=(0==kill(m_idProcess,SIGTERM));
     int status;
@@ -524,8 +525,7 @@ TRACE(_T("CSubprocess::Kill pid %d recur
           // end hack
           HANDLE hProcess=::OpenProcess(PROCESS_TERMINATE,false,arPinfo[i].PID);
           if(hProcess){
-            TRACE(_T("Terminate m_idProcess %d [%s]\n"),arPinfo[i].PID,(LPCTSTR)Name(arPinfo[i].PID));
-          
+            TRACE(_T("Terminate process %s\n"),(LPCTSTR)Name(arPinfo[i].PID));
             rc&=(TRUE==::TerminateProcess(hProcess,PROCESS_KILL_EXIT_CODE));
             CloseHandle(hProcess);
           } else {
@@ -550,12 +550,10 @@ Time CSubprocess::CpuTime(bool bRecurse)
   // FIXME: needs to be top-down
   
 #ifdef _WIN32
-  EnterCriticalSection(&m_cs); // because the thread func may be closing it
   __int64 ftCreation,ftExit,ftKernel,ftUser;
   if(m_hProcess && ::GetProcessTimes (m_hProcess,(FILETIME *)&ftCreation,(FILETIME *)&ftExit,(FILETIME *)&ftKernel,(FILETIME *)&ftUser)){
     t+=Time((ftKernel+ftUser)/10000);
   }
-  LeaveCriticalSection(&m_cs);
 
   if(bRecurse){
     PInfoArray arPinfo;
@@ -689,12 +687,6 @@ bool CSubprocess::PSExtract(CSubprocess:
 
   SetParents(arPinfo);
 
-/*
-for(int k=0;k<(signed)arPinfo.size();k++){
-  const PInfo &p=arPinfo[k];
-  TRACE(_T("%d%c pid=%4d ppid=%4d t=%I64d [%s]\n"),k,p.IsChildOf(GetCurrentProcessId())?_TCHAR('*'):_TCHAR(':'),p.PID,p.PPID,p.t,(LPCTSTR)Name(p.PID));
-}
-*/
   if(!rc){
     ERROR(_T("Couldn't get process information!\n"));
   }
@@ -780,7 +772,7 @@ void CSubprocess::SetParents(CSubprocess
     ERROR(_T("!!! Circularly linked process list at index %d\n"),i);
     for(int k=0;k<(signed)arPinfo.size();k++){
       const PInfo &p=arPinfo[k];
-      ERROR(_T("%d: pid=%4d ppid=%4d [%s]\n"),k,p.PID,p.PPID,(LPCTSTR)Name(p.PID));
+      ERROR(_T("%d: %s ppid=%4d\n"),k,(LPCTSTR)Name(p.PID),p.PPID);
     }
   }
 }
@@ -797,7 +789,7 @@ bool CSubprocess::PInfo::IsChildOf(int p
 
 const String CSubprocess::Name(int pid)
 {
-  String str;
+  String str(String::SFormat(_T("id=%d"),pid));
 #ifdef _DEBUG
 #ifdef _WIN32
   if(VER_PLATFORM_WIN32_NT==GetPlatform() && hInstLib1){
@@ -812,9 +804,10 @@ const String CSubprocess::Name(int pid)
         DWORD dwSize;
         if(lpfEnumProcessModules( hProcess, &hMod, sizeof(HMODULE), &dwSize ) ){
           // Get Full pathname:
-          LPTSTR buf=str.GetBuffer(MAX_PATH);
+          TCHAR buf[1+MAX_PATH];
           lpfGetModuleFileNameEx( hProcess, hMod, buf, MAX_PATH);
-          str.ReleaseBuffer();
+          str+=_TCHAR(' ');
+          str+=buf;
         }
         CloseHandle(hProcess);
       }
--- a/host/tools/Utils/common/Subprocess.h
+++ b/host/tools/Utils/common/Subprocess.h
@@ -146,7 +146,6 @@ protected:
 	HANDLE m_hrPipe;
 	HANDLE m_hwPipe;
   HANDLE m_hProcess;     // This handle is "owned" by the ThreadFunc
-  mutable CRITICAL_SECTION m_cs; // protects m_hProcess
   static HINSTANCE hInstLib1, hInstLib2;
 	int m_nErr;
 #else
--- a/host/tools/configtool/ChangeLog
+++ b/host/tools/configtool/ChangeLog
@@ -1,3 +1,17 @@
+2000-04-17  John Dallaway  <jld@cygnus.co.uk>
+
+	* standalone/common/cdl_exec.cxx:
+
+	Use PATH_MAX rather than _MAX_PATH in the Cygwin-hosted
+	build.
+
+2000-04-17  John Dallaway  <jld@cygnus.co.uk>
+
+	* standalone/common/cdl_exec.cxx:
+
+	Modify cmd_tree() to avoid non-standard use of
+	getcwd().
+
 2000-04-11  John Dallaway  <jld@cygnus.co.uk>
 
 	* common/win32/CTCommonDoc.cpp:
--- a/host/tools/configtool/standalone/common/cdl_exec.cxx
+++ b/host/tools/configtool/standalone/common/cdl_exec.cxx
@@ -244,7 +244,12 @@ bool cdl_exec::cmd_tree () {
 		pkgdata = CdlPackagesDatabaseBody::make (repository, &diagnostic_handler, &diagnostic_handler);
 		interp = CdlInterpreterBody::make ();
 		config = CdlConfigurationBody::load (savefile, pkgdata, interp, &diagnostic_handler, &diagnostic_handler);
-		char * cwd = getcwd (NULL, 0);
+#ifdef _MSC_VER
+		char cwd [_MAX_PATH + 1];
+#else
+		char cwd [PATH_MAX + 1];
+#endif
+		getcwd (cwd, sizeof cwd);
 #ifdef __CYGWIN__
 		char cwd_win32 [MAXPATHLEN + 1];
 		cygwin_conv_to_win32_path (cwd, cwd_win32);
@@ -252,7 +257,6 @@ bool cdl_exec::cmd_tree () {
 #else
 		generate_build_tree (config, cwd, install_prefix);
 #endif
-		free (cwd);
 		config->generate_config_headers (install_prefix.empty () ? "install/include/pkgconf" : install_prefix + "/include/pkgconf");
 		status = true;
 	} catch (CdlStringException exception) {
--- a/host/tools/ecostest/ChangeLog
+++ b/host/tools/ecostest/ChangeLog
@@ -1,3 +1,7 @@
+2000-04-14 Simon FitzMaurice <sdf@redhat.co.uk>
+  * common\ResetAttributes.cpp : do not carry forward values for skipped fields in reset strings
+  * common\eCosTest.cpp : Avoid overflow in socket timeouts
+    
 2000-04-13  Jesper Skov  <jskov@redhat.com>
 
 	* unix/Makefile: add randfile
--- a/host/tools/ecostest/common/ResetAttributes.cpp
+++ b/host/tools/ecostest/common/ResetAttributes.cpp
@@ -340,13 +340,13 @@ CResetAttributes::ResetResult CResetAttr
       //   2. Read timeout
       StringArray ar;
       int nArgs=strArg.Chop(ar,ARGSEP,true);
-      if(nArgs>0 && ar[0].size()){
+      if(nArgs>0){
         m_strAuxPort=ar[0];
       }
-      if(nArgs>1 && ar[1].size()){
+      if(nArgs>1){
         m_nBaud=_ttoi(ar[1]);
       }
-      if(nArgs>2 && ar[2].size()){
+      if(nArgs>2){
         m_nReadTimeout=_ttoi(ar[2]);
       }
     } else if (_T("off")==strID || _T("on")==strID || _T("on_off")==strID || _T("off_on")==strID) {
@@ -360,22 +360,22 @@ CResetAttributes::ResetResult CResetAttr
       //   5. Delay
       StringArray ar;
       int nArgs=strArg.Chop(ar,ARGSEP,true);
-      if(nArgs>0 && ar[0].size()){
+      if(nArgs>0){
         m_strHostPort=ar[0];  
       }
-      if(nArgs>1 && ar[1].size()){
+      if(nArgs>1){
         m_strControl=ar[1];
       }
-      if(nArgs>2 && ar[2].size()){
+      if(nArgs>2){
         m_strAuxPort=ar[2];
       }
-      if(nArgs>3 && ar[3].size()){
+      if(nArgs>3){
         m_nBaud=_ttoi(ar[3]);
       }
-      if(nArgs>4 && ar[4].size()){
+      if(nArgs>4){
         m_nReadTimeout=_ttoi(ar[4]);
       }
-      if(nArgs>5 && ar[5].size()){
+      if(nArgs>5){
         m_nDelay=_ttoi(ar[5]);
       }
 
--- a/host/tools/ecostest/common/eCosTest.cpp
+++ b/host/tools/ecostest/common/eCosTest.cpp
@@ -926,6 +926,7 @@ void CeCosTest::AcceptThreadFunc()
     sendResult();
     m_pSock->recvInteger(n); // receive an ack
   } else {
+    // Client-side GDB
     bool bTargetReady;
     if(_TCHAR('\0')==*(m_pResource->ResetString())){
       bTargetReady=true;
@@ -938,12 +939,11 @@ void CeCosTest::AcceptThreadFunc()
     m_pSock->sendInteger(bTargetReady,_T("target ready indicator"));
     
     int nAck=-1;
-    int dTimeout=m_ep.DownloadTimeout()+MAX(3*m_ep.ActiveTimeout(),15*60*1000);
     
     if(bTargetReady){
       if(CeCosSocket::IsLegalHostPort(m_pResource->Serial())){
         TRACE(_T("Sending %s\n"),(LPCTSTR)m_pResource->Serial());
-        if(m_pSock->sendString(m_pResource->Serial(),_T("Serial name")) && m_pSock->recvInteger(nAck,_T("Terminating ack"),dTimeout)){
+        if(m_pSock->sendString(m_pResource->Serial(),_T("Serial name")) && m_pSock->recvInteger(nAck,_T("Terminating ack"),CeCosSocket::NOTIMEOUT)){
           TRACE(_T("Terminating ack=%d\n"),nAck);
         }
       } else {
@@ -963,7 +963,7 @@ void CeCosTest::AcceptThreadFunc()
           CeCosThreadUtils::RunThread(SConnectSocketToSerialThreadFunc,this,&bConnectSocketToSerialThreadDone,_T("SConnectSocketToSerialThreadFunc")); 
           
           // Wait for either client or the ConnectSocketToSerial thread to finish.
-          if(m_pSock->recv(&nAck,sizeof(int),_T("Terminating ack"),dTimeout,DerefBool,&bConnectSocketToSerialThreadDone)){
+          if(m_pSock->recv(&nAck,sizeof(int),_T("Terminating ack"),CeCosSocket::NOTIMEOUT,DerefBool,&bConnectSocketToSerialThreadDone)){
             TRACE(_T("Session terminated by request of client (%s)\n"),(LPCTSTR)Image((StatusType)nAck));
           } else if(0!=m_pSock->SocketError()){
             TRACE(_T("Session terminated by socket error - %s\n"),(LPCTSTR)m_pSock->SocketErrString());
--- 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.4 2000/04/18 21:51:58 jlarmour Exp $"
+#define DL_FILTER_VER "$Id: eCosTestDownloadFilter.cpp,v 1.5 2000/04/28 18:18:41 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.3 2000/04/18 21:51:58 jlarmour Exp $"
+#define SER_FILTER_VER "$Id: eCosTestMonitorFilter.cpp,v 1.4 2000/04/28 18:18:41 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.4 2000/04/18 21:51:58 jlarmour Exp $"
+#define SER_FILTER_VER "$Id: eCosTestSerialFilter.cpp,v 1.5 2000/04/28 18:18:41 jlarmour Exp $"
 #include "eCosTestSerialFilter.h"
 #include "eCosThreadUtils.h"
 
--- a/packages/compat/uitron/current/tests/testintr.cxx
+++ b/packages/compat/uitron/current/tests/testintr.cxx
@@ -316,6 +316,7 @@ void task1( unsigned int arg )
 #endif
     }
 
+
     // First test that dis_int() and ena_int() work for the clock interrupt
 #ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS
     ercd = ena_int( 123456789 ); // Hope this is large enough to error
--- a/packages/devs/eth/arm/ebsa285/current/ChangeLog
+++ b/packages/devs/eth/arm/ebsa285/current/ChangeLog
@@ -1,3 +1,38 @@
+2000-04-27  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* src/if_ebsa285.c: A serious re-write.  This cuts out a lot of
+	code from the old version and improves the performance greatly.
+
+	The cruft was mainly doing lots of explicit event communication
+	between the ISR and DSR, when in fact all the state needed is
+	present in the tx/rx rings.  So both ISRs and DSRs regard their
+	call as an opportunity to progress everything they can, rather
+	than only dealing with one interrupt cause at a time; the
+	connection between them is now rather looser.
+
+	Interrups can now be re-enabled after the ISR (in other words they
+	are not masked in the ISR), no need to wait for the DSR, but in
+	consequence some DSR code must mask/unmask intrs as it works.
+
+	The 82559 appears to be a little slow in reacting to commands and
+	state changes, so some interrupts were being lost - or persisting
+	beyond their desired life - so there's some kinda polling code to
+	deal with that also.  We also rely on the foreground to kind of
+	poll in the same way, in the send/can_send calls - we know the
+	stack will re-try if necessary, though this is rare.
+
+	The driver now works (albeit at much reduced performance) with as
+	few as 6 rx and tx buffers - in other words the "queue full/out of
+	rx buffers" states have been tested and all is well.  It works
+	generally fine with 8 buffers of each kind.
+
+	The mux ISR and DSR are now rather more polled than the old
+	versions; we just try to do things with both devices (if active)
+	by simply calling each unitary ISR/DSR respectively.
+
+	I also re-ordered some of the code, moving utilities to the end of
+	the file and grouping together Tx and Rx machines a bit better.
+
 2000-04-13  Hugo Tyson  <hmt@cygnus.co.uk>
 
 	* src/if_ebsa285.c: Attribution to Ron Spence, Pacific Softworks
--- a/packages/devs/eth/arm/ebsa285/current/src/if_ebsa285.c
+++ b/packages/devs/eth/arm/ebsa285/current/src/if_ebsa285.c
@@ -142,6 +142,10 @@ static inline cyg_uint32 bus_to_virt(cyg
 #define SCB_STATUS_SWI  0x0400          // software generated interrupt
 #define SCB_STATUS_FCP  0x0100          // flow control pause interrupt
 
+#define SCB_INTACK_MASK 0xFD00          // all the above
+
+#define SCB_INTACK_TX (SCB_STATUS_CX | SCB_STATUS_CNA)
+#define SCB_INTACK_RX (SCB_STATUS_FR | SCB_STATUS_RNR)
 
 // ------------------------------------------------------------------------
 //
@@ -202,7 +206,7 @@ static inline cyg_uint32 bus_to_virt(cyg
 #define	CU_RESUME       0x0020
 #define	CU_STATSADDR    0x0040          // Load Dump Statistics ctrs addr
 #define	CU_SHOWSTATS    0x0050          // Dump statistics counters.
-#define	CU_CMD_BASE     0x0060          // Base address to add to CU commands
+#define	CU_ADDR_LOAD    0x0060          // Base address to add to CU commands
 #define	CU_DUMPSTATS    0x0070          // Dump then reset stats counters.
 
 // RUC COMMANDS
@@ -210,7 +214,7 @@ static inline cyg_uint32 bus_to_virt(cyg
 #define	RUC_START       0x0001
 #define	RUC_RESUME      0x0002
 #define RUC_ABORT       0x0004
-#define	RUC_ADDR_LOAD   0x0006
+#define	RUC_ADDR_LOAD   0x0006          // (seems not to clear on acceptance)
 #define RUC_RESUMENR    0x0007
 
 #define SCB_M	        0x0100          // 0 = enable interrupt, 1 = disable
@@ -219,33 +223,17 @@ static inline cyg_uint32 bus_to_virt(cyg
 #define CU_STATUS_MASK  0x00C0
 #define RU_STATUS_MASK  0x003C
 
-#define CUC_ADDR_LOAD  0x0060
-#define CUC_START      0x0010      
- 
-#define MAX_MEM_RESERVED_IOCTL 1000
-
-// 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.
+#define RU_STATUS_IDLE  (0<<2)
+#define RU_STATUS_SUS   (1<<2)
+#define RU_STATUS_NORES (2<<2)
+#define RU_STATUS_READY (4<<2)
+#define RU_STATUS_NO_RBDS_SUS   ((1<<2)|(8<<2))
+#define RU_STATUS_NO_RBDS_NORES ((2<<2)|(8<<2))
+#define RU_STATUS_NO_RBDS_READY ((4<<2)|(8<<2))
 
-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 
-};
+
 
- 
+#define MAX_MEM_RESERVED_IOCTL 1000
 
 // ------------------------------------------------------------------------
 //
@@ -371,6 +359,7 @@ typedef struct {
 
 
 typedef struct {
+    cyg_uint32 interrupts;
     cyg_uint32 rx_count;
     cyg_uint32 rx_deliver;
     cyg_uint32 rx_resource;
@@ -391,6 +380,14 @@ I82559_COUNTERS i82559_counters[2];
 #define MAX_RX_PACKET_SIZE  1536        // maximum Rx packet size
 #define MAX_TX_PACKET_SIZE  1536        // maximum Tx packet size
 
+// The system seems to work OK with as few as 8 of RX and TX descriptors.
+// It limps very painfully with only 4.
+// Performance is better with more than 8.
+// But the size of non-cached (so useless for anything else)
+// memory window is 1Mb, so we might as well use it all.
+//
+// 128 for these uses the whole 1Mb, near enough.
+
 #ifndef MAX_RX_DESCRIPTORS
 #define MAX_RX_DESCRIPTORS	128     // number of Rx descriptors
 #endif
@@ -407,8 +404,7 @@ typedef struct i82559 {
         active:1,                       // has this if been brung up?
         spare1:5; 
     cyg_uint8
-        out_of_resources:1,             // need to restart rx engine.
-        spare2:7; 
+        spare2:8; 
     cyg_uint8
         tx_in_progress:1,               // transmit in progress flag
         tx_queue_full:1,                // all Tx descriptors used flag
@@ -424,7 +420,9 @@ typedef struct i82559 {
     RFD *rx_ring[MAX_RX_DESCRIPTORS];   // location of Rx descriptors
 
     int tx_descriptor_add;              // descriptor index for additions
-    int tx_descriptor_remove;           // descriptor index for removals
+    int tx_descriptor_active;           // descriptor index for active tx
+    int tx_descriptor_remove;           // descriptor index for remove
+
     TxCB *tx_ring[MAX_TX_DESCRIPTORS];  // location of Tx descriptors
     unsigned long tx_keys[MAX_TX_DESCRIPTORS];
                                         // keys for tx q management
@@ -508,31 +506,6 @@ CYG_MACRO_END
 
 // ------------------------------------------------------------------------
 //
-// Communications from ISR to DSR
-//
-// ------------------------------------------------------------------------
-
-#define PACKET_RX   1
-#define PACKET_TX   2
-
-typedef struct {
-    cyg_uint32 request;
-    void *p;
-    unsigned long key;
-} I82559_QUEUE;
-
-// 82559 thread request queue
-#define I82559_QUEUE_SIZE \
-   ((MAX_RX_DESCRIPTORS + MAX_TX_DESCRIPTORS) * MAX_82559)
-
-I82559_QUEUE i82559_queue[I82559_QUEUE_SIZE];
-int i82559_q_in;                        // queue insertion index
-int i82559_q_out;                       // queue removal index
-int i82559_q_full;                      // queue full flag
-
-
-// ------------------------------------------------------------------------
-//
 // Managing the memory that is windowed onto the PCI bus
 //
 // ------------------------------------------------------------------------
@@ -556,7 +529,6 @@ static void i82559_reset(struct i82559* 
 
 static void InitRxRing(struct i82559* p_i82559);
 static void ResetRxRing(struct i82559* p_i82559);
-static void PacketRxReady(struct i82559* p_i82559);
 static void InitTxRing(struct i82559* p_i82559);
 static void ResetTxRing(struct i82559* p_i82559);
 
@@ -565,14 +537,24 @@ static void program_eeprom(cyg_uint32 , 
 
 static int eth_set_promiscuous_mode(struct i82559* p_i82559);
 
+// debugging/logging only:
+void dump_txcb(TxCB *p_txcb);
+void DisplayStatistics(void);
+void dump_rfd(RFD *p_rfd, int anyway );
+void dump_all_rfds( int intf );
+void dump_packet(cyg_uint8 *p_buffer, int length);
+
 // ------------------------------------------------------------------------
-// utility that is used in statistics routine
+// utilities
 // ------------------------------------------------------------------------
+
 static inline void wait_for_cmd_done(long scb_ioaddr)
 {
-    int wait = 10000;
-    do /* nothing */ ;
-    while( INB(scb_ioaddr) && --wait >= 0);
+    register int CSRstatus;
+    register int wait = 0x100000;
+    do CSRstatus = INB(scb_ioaddr + SCBCmd) ;
+    while( CSRstatus && --wait >= 0);
+    CYG_ASSERT( wait > 0, "wait_for_cmd_done" );
 }
 
 static inline void Mask82559Interrupt(struct i82559* p_i82559)
@@ -587,6 +569,41 @@ static inline void UnMask82559Interrupt(
     cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_PCI_IRQ);
 }
 
+#ifdef CYGDBG_USE_ASSERTS // an indication of a debug build
+static int acknowledge82559interrupt_compensating = 0;
+#endif
+
+static void Acknowledge82559Interrupt(struct i82559* p_i82559)
+{
+    int sources, mask;
+    cyg_uint32 ioaddr;
+    cyg_uint16 status;
+    int loops = 64;
+
+    cyg_drv_interrupt_acknowledge(p_i82559->vector);
+    cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_PCI_IRQ);
+
+    // It appears that some time can be taken before the interrupt source
+    // *really* quietens down... this is ugly, but effective.
+    // Without it, we get "Spurious Interrupt!" failures.
+    ioaddr = p_i82559->io_address; // get I/O address for 82559
+    mask = (1 << p_i82559->vector); // Do not include the MUX vector or we
+    sources = *SA110_IRQCONT_IRQSTATUS; //...get hung on the other 82559
+    status = INW(ioaddr + SCBStatus);
+    while ( ((0 != (sources & mask)) || (0 != (status & SCB_INTACK_MASK)))
+            && --loops >= 0) {
+        OUTW( status & SCB_INTACK_MASK, ioaddr + SCBStatus);
+        cyg_drv_interrupt_acknowledge(p_i82559->vector);
+        cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_PCI_IRQ);
+#ifdef CYGDBG_USE_ASSERTS
+        acknowledge82559interrupt_compensating++; // verify this is executed
+#endif
+        sources = *SA110_IRQCONT_IRQSTATUS;
+        status = INW(ioaddr + SCBStatus);
+    }
+    CYG_ASSERT( loops >= 0, "Acknowledge82559Interrupt" );
+}
+
 
 static void udelay(int delay)
 {
@@ -599,204 +616,6 @@ static void udelay(int delay)
 }
 
 // ------------------------------------------------------------------------
-//
-//
-//           CODE FOR DEBUGGING PURPOSES ONLY
-//
-//
-// ------------------------------------------------------------------------
-void dump_txcb(TxCB *p_txcb)
-{
-    os_printf("TxCB @ %x\n", (int)p_txcb);
-    os_printf("status = %04X ", p_txcb->status);
-    os_printf("command = %04X ", p_txcb->command);
-    os_printf("link = %08X ", p_txcb->link);
-    os_printf("tbd = %08X ", p_txcb->tbd_address);
-    os_printf("count = %d ", p_txcb->count);
-    os_printf("eof = %x ", p_txcb->eof);
-    os_printf("threshold = %d ", p_txcb->tx_threshold);
-    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
-#ifdef DISPLAY_STATISTICS
-void DisplayStatistics(void)
-{
-    int i;
-    I82559_COUNTERS *p_statistics;
-    cyg_uint32 *p_counter;
-    cyg_uint32 *p_register;
-    int reg_count;
-    int status;
-    
-    while ( 1 ) {
-#ifdef DISPLAY_82559_STATISTICS
-        for ( i = 0; i < 2; i ++ ) {
-            p_statistics = (I82559_COUNTERS *)i82559[i].p_statistics;
-            if ( (p_statistics->done & 0xFFFF) == 0xA007 ) {
-                p_counter = (cyg_uint32 *)&i82559_counters[i];
-                p_register = (cyg_uint32 *)&p_statistics->tx_good;
-                for ( reg_count = 20; reg_count != 0; reg_count--) {
-                    *p_counter += *p_register;
-                    p_counter++;
-                    p_register++;
-                }
-                p_statistics->done = 0;
-                // make sure no command operating
-            	wait_for_cmd_done(i82559[i].io_address + SCBCmd);
-                // start register dump
-                OUTW(CU_DUMPSTATS, i82559[i].io_address + SCBCmd);
-            }
-        }
-#endif
-        os_printf("\nRx\nPackets = %d  %d\n",
-        statistics[0].rx_count, statistics[1].rx_count);
-        os_printf("Deliver   %d  %d\n",
-        statistics[0].rx_deliver, statistics[1].rx_deliver);
-        os_printf("Resource  %d  %d\n",
-        statistics[0].rx_resource, statistics[1].rx_resource);
-        os_printf("Restart   %d  %d\n",
-        statistics[0].rx_restart, statistics[1].rx_restart);
-
-#ifdef DISPLAY_82559_STATISTICS
-        os_printf("Count     %d  %d\n",
-        i82559_counters[0].rx_good, i82559_counters[1].rx_good);
-        os_printf("CRC       %d  %d\n",
-        i82559_counters[0].rx_crc_errors, i82559_counters[1].rx_crc_errors);
-        os_printf("Align     %d  %d\n",
-        i82559_counters[0].rx_align_errors, i82559_counters[1].rx_align_errors);
-        os_printf("Resource  %d  %d\n",
-        i82559_counters[0].rx_resource_errors, i82559_counters[1].rx_resource_errors);
-        os_printf("Overrun   %d  %d\n",
-        i82559_counters[0].rx_overrun_errors, i82559_counters[1].rx_overrun_errors);
-        os_printf("Collision %d  %d\n",
-        i82559_counters[0].rx_collisions, i82559_counters[1].rx_collisions);
-        os_printf("Short     %d  %d\n",
-        i82559_counters[0].rx_short_frames, i82559_counters[1].rx_short_frames);
-#endif
-        os_printf("\nTx\nPackets = %d  %d\n",
-        statistics[0].tx_count, statistics[1].tx_count);
-        os_printf("Complete  %d  %d\n",
-        statistics[0].tx_complete, statistics[1].tx_complete);
-        os_printf("Dropped   %d  %d\n",
-        statistics[0].tx_dropped, statistics[1].tx_dropped);
-        os_printf("Count     %d  %d\n",
-        i82559_counters[0].tx_good, i82559_counters[1].tx_good);
-#ifdef DISPLAY_82559_STATISTICS
-        os_printf("Collision %d  %d\n",
-        i82559_counters[0].tx_max_collisions,i82559_counters[1].tx_max_collisions);
-        os_printf("Late Col. %d  %d\n",
-        i82559_counters[0].tx_late_collisions,i82559_counters[1].tx_late_collisions);
-        os_printf("Underrun  %d  %d\n",
-        i82559_counters[0].tx_underrun,i82559_counters[1].tx_underrun);
-        os_printf("Carrier   %d  %d\n",
-        i82559_counters[0].tx_carrier_loss,i82559_counters[1].tx_carrier_loss);
-        os_printf("Deferred  %d  %d\n",
-        i82559_counters[0].tx_deferred, i82559_counters[1].tx_deferred);
-        os_printf("1 Col     %d  %d\n",
-        i82559_counters[0].tx_single_collisions, i82559_counters[0].tx_single_collisions);
-        os_printf("Mult. Col %d  %d\n",
-        i82559_counters[0].tx_mult_collisions, i82559_counters[0].tx_mult_collisions);
-        os_printf("Total Col %d  %d\n",
-        i82559_counters[0].tx_total_collisions, i82559_counters[0].tx_total_collisions);
-#endif
-        status = INB(i82559[0].io_address + SCBGenStatus);
-        os_printf("Interface 0 Link = %s, %s Mbps, %s Duplex\n",
-            status & GEN_STATUS_LINK ? "Up" : "Down",
-            status & GEN_STATUS_100MBPS ?  "100" : "10",
-            status & GEN_STATUS_FDX ? "Full" : "Half");
-
-        status = INB(i82559[1].io_address + SCBGenStatus);
-        os_printf("Interface 1 Link = %s, %s Mbps, %s Duplex\n",
-            status & GEN_STATUS_LINK ? "Up" : "Down",
-            status & GEN_STATUS_100MBPS ?  "100" : "10",
-            status & GEN_STATUS_FDX ? "Full" : "Half");
-
-        cyg_thread_delay(1000);
-    }
-}
-#endif // DISPLAY_STATISTICS
-#endif // KEEP_STATISTICS
-
-void dump_rfd(RFD *p_rfd, int anyway )
-{
-    if ( (0 != p_rfd->status) || anyway ) {
-        os_printf("RFD @ %x = ", (int)p_rfd);
-        os_printf("status = %x ", p_rfd->status);
-        os_printf("link = %x ", p_rfd->link);
-//        os_printf("rdb_address = %x ", p_rfd->rdb_address);
-        os_printf("count = %x ", p_rfd->count);
-        os_printf("f = %x ", p_rfd->f);
-        os_printf("eof = %x ", p_rfd->eof);
-        os_printf("size = %x\n", p_rfd->size);
-        os_printf("[%04x %04x %04x] ",
-                  *((cyg_uint16 *)(&(p_rfd->buffer[0]))),
-                  *((cyg_uint16 *)(&(p_rfd->buffer[2]))),
-                  *((cyg_uint16 *)(&(p_rfd->buffer[4]))) );
-        os_printf("[%04x %04x %04x] %04x : ",          
-                  *((cyg_uint16 *)(&(p_rfd->buffer[6]))),
-                  *((cyg_uint16 *)(&(p_rfd->buffer[8]))),
-                  *((cyg_uint16 *)(&(p_rfd->buffer[10]))),
-                  *((cyg_uint16 *)(&(p_rfd->buffer[12]))) );
-        os_printf("(%04x %04x %04x %04x) ",            
-                  *((cyg_uint16 *)(&(p_rfd->buffer[14]))),
-                  *((cyg_uint16 *)(&(p_rfd->buffer[16]))),
-                  *((cyg_uint16 *)(&(p_rfd->buffer[18]))),
-                  *((cyg_uint16 *)(&(p_rfd->buffer[20]))) );
-        os_printf("[%04x %04x %04x] ",                 
-                  *((cyg_uint16 *)(&(p_rfd->buffer[22]))),
-                  *((cyg_uint16 *)(&(p_rfd->buffer[24]))),
-                  *((cyg_uint16 *)(&(p_rfd->buffer[26]))) );
-        os_printf("%d.%d.%d.%d ",
-                  *((cyg_uint8  *)(&(p_rfd->buffer[28]))),
-                  *((cyg_uint8  *)(&(p_rfd->buffer[29]))),
-                  *((cyg_uint8  *)(&(p_rfd->buffer[30]))),
-                  *((cyg_uint8  *)(&(p_rfd->buffer[31]))) );
-        os_printf("[%04x %04x %04x] ",                 
-                  *((cyg_uint16 *)(&(p_rfd->buffer[32]))),
-                  *((cyg_uint16 *)(&(p_rfd->buffer[34]))),
-                  *((cyg_uint16 *)(&(p_rfd->buffer[36]))) );
-        os_printf("%d.%d.%d.%d ...\n",
-                  *((cyg_uint8  *)(&(p_rfd->buffer[38]))),
-                  *((cyg_uint8  *)(&(p_rfd->buffer[39]))),
-                  *((cyg_uint8  *)(&(p_rfd->buffer[40]))),
-                  *((cyg_uint8  *)(&(p_rfd->buffer[41]))) );
-    }
-}
-
-void dump_all_rfds( int intf )
-{
-    struct i82559* p_i82559 = &i82559[intf];
-    int i, j;
-    j = p_i82559->next_rx_descriptor;
-    os_printf("rx descriptors for interface %d (eth%d):\n", intf, intf );
-    for ( i = 0; i < MAX_RX_DESCRIPTORS; i++ )
-        dump_rfd( p_i82559->rx_ring[i], (i > (j-3) && (i <= j)) );
-    os_printf("next rx descriptor = %x\n\n", j);
-}
-
-
-void dump_packet(cyg_uint8 *p_buffer, int length)
-{
-    int count;
-
-    count = 0;
-    while ( length > 0 ) {
-        if ( count == 0 )
-            os_printf("\n");
-        count = (count + 1) & 0x0F;
-        os_printf("%02X ", *p_buffer++);
-        length--;
-    }
-    os_printf("\n");
-}
-
-
-
-// ------------------------------------------------------------------------
 // Memory management
 //
 // Simply carve off from the front of the PCI mapped window into real memory
@@ -937,7 +756,7 @@ ebsa285_i82559_init(struct cyg_netdevtab
 
     Mask82559Interrupt(p_i82559);
 
-    wait_for_cmd_done(ioaddr + SCBCmd); // make sure no command operating
+    wait_for_cmd_done(ioaddr); // make sure no command operating
 
     i82559_reset(p_i82559);
 
@@ -953,6 +772,7 @@ ebsa285_i82559_init(struct cyg_netdevtab
         udelay(10);
     } while ( (p_selftest[1] == -1)  &&  (--count >= 0) );
 
+    Acknowledge82559Interrupt(p_i82559);
     UnMask82559Interrupt(p_i82559);
     
     if (count < 0) {
@@ -1044,8 +864,10 @@ static void i82559_start( struct eth_drv
     struct i82559 *p_i82559;
     cyg_uint32 ioaddr;
 #ifdef KEEP_STATISTICS
+#ifdef DISPLAY_82559_STATISTICS
     void *p_statistics;
 #endif
+#endif
 
     p_i82559 = (struct i82559 *)sc->driver_private;
     
@@ -1071,27 +893,24 @@ static void i82559_start( struct eth_drv
     p_i82559->p_statistics =
         p_statistics = pciwindow_mem_alloc(sizeof(I82559_COUNTERS));
     memset(p_statistics, 0xFFFFFFFF, sizeof(I82559_COUNTERS));
-    wait_for_cmd_done(ioaddr + SCBCmd); // make sure no command operating
+    wait_for_cmd_done(ioaddr); // make sure no command operating
                                         // set statistics dump address
     OUTL(VIRT_TO_BUS(p_statistics), ioaddr + SCBPointer);
     OUTW(SCB_M | CU_STATSADDR, ioaddr + SCBCmd);
 
-    wait_for_cmd_done(ioaddr + SCBCmd); // make sure no command operating
+    wait_for_cmd_done(ioaddr); // make sure no command operating
     OUTW(SCB_M | CU_DUMPSTATS, ioaddr + SCBCmd); // start register dump
 #endif
 #endif
 
-    wait_for_cmd_done(ioaddr + SCBCmd); // make sure no command operating
-
+    // Set the base address
+    wait_for_cmd_done(ioaddr);
     OUTL(0, ioaddr + SCBPointer);       // load ru base address = 0
     OUTW(SCB_M | RUC_ADDR_LOAD, ioaddr + SCBCmd);
-
-    wait_for_cmd_done(ioaddr + SCBCmd); // wait for SCB command complete
-                                        // load pointer to Rx Ring
+    udelay( 1000 );                     // load pointer to Rx Ring
     OUTL(VIRT_TO_BUS(p_i82559->rx_ring[0]), ioaddr + SCBPointer);
     OUTW(RUC_START, ioaddr + SCBCmd);
     
-    p_i82559->out_of_resources = 0;
     p_i82559->active = 1;
 
     if ( 0
@@ -1137,8 +956,8 @@ static void i82559_stop( struct eth_drv_
     os_printf("i82559_stop %d flg %x\n", p_i82559->index, *(int *)p_i82559 );
 #endif
 
+    p_i82559->active = 0;               // stop people tormenting it
     i82559_reset(p_i82559);             // that should stop it
-    p_i82559->active = 0;               // and stop people tormenting it
 
     ResetRxRing( p_i82559 );
     ResetTxRing( p_i82559 );
@@ -1202,22 +1021,26 @@ static void ResetRxRing(struct i82559* p
 
 // ------------------------------------------------------------------------
 //
-//  Function : PacketRx
+//  Function : PacketRxReady        (Called from DSR)
 //
 // ------------------------------------------------------------------------
 static void PacketRxReady(struct i82559* p_i82559)
 {
-    struct cyg_netdevtab_entry *ndp;
-    struct eth_drv_sc *sc;
     RFD *p_rfd;
     int next_descriptor;
     int length;
+    struct cyg_netdevtab_entry *ndp;
+    struct eth_drv_sc *sc;
+    cyg_uint32 ioaddr;
+    cyg_uint16 status;
 
     ndp = (struct cyg_netdevtab_entry *)(p_i82559->ndp);
     sc = (struct eth_drv_sc *)(ndp->device_instance);
 
     CHECK_NDP_SC_LINK();
 
+    ioaddr = p_i82559->io_address;
+
     next_descriptor = p_i82559->next_rx_descriptor;
     p_rfd = p_i82559->rx_ring[next_descriptor];
 
@@ -1253,35 +1076,29 @@ static void PacketRxReady(struct i82559*
         CYG_ASSERT( (cyg_uint8 *)p_rfd <  i82559_heap_free, "rfd over" );
     }
 
-    if ( p_i82559->out_of_resources ) { // out of Rx resources ?
-        if ( ! (p_rfd->status & RFD_STATUS_C) ) { // all buffers processed ?
-            cyg_uint32 ioaddr;
-            // yes, restart RU
-#ifdef KEEP_STATISTICS
-            statistics[p_i82559->index].rx_restart++;
-#endif
-            next_descriptor = 0;        // re-initialize next desc.
-            p_i82559->out_of_resources = 0; // clear out of resource flag
-            ioaddr = p_i82559->io_address; // get I/O address
+    // See if the RU has gone idle (usually because of out of resource
+    // condition) and restart it if needs be.
+    Mask82559Interrupt(p_i82559);
+    status = INW(ioaddr + SCBStatus);
+    if ( RU_STATUS_READY != (status & RU_STATUS_MASK) ) {
+        // Acknowledge the RX INT sources
+        OUTW( SCB_INTACK_RX, ioaddr + SCBStatus);
+        // (see pages 6-10 & 6-90)
 
-            // wait for SCB command complete
-            wait_for_cmd_done(ioaddr + SCBCmd);
-            OUTW(RUC_ABORT, ioaddr + SCBCmd);
-            
-            // make sure no command operating
-            wait_for_cmd_done(ioaddr + SCBCmd);
+#ifdef KEEP_STATISTICS
+        statistics[p_i82559->index].rx_restart++;
+#endif
+        next_descriptor = 0;        // re-initialize next desc.
+        // wait for SCB command complete
+        wait_for_cmd_done(ioaddr);
+        // load pointer to Rx Ring
+        OUTL(VIRT_TO_BUS(p_i82559->rx_ring[0]),
+             ioaddr + SCBPointer);
+        OUTW(RUC_START, ioaddr + SCBCmd);
+        Acknowledge82559Interrupt(p_i82559);
+    }
+    UnMask82559Interrupt(p_i82559);
 
-            OUTL(0, ioaddr + SCBPointer); // load ru base address = 0
-            OUTW(SCB_M | RUC_ADDR_LOAD, ioaddr + SCBCmd);
-
-            // wait for SCB command complete
-            wait_for_cmd_done(ioaddr + SCBCmd);
-            // load pointer to Rx Ring
-            OUTL(VIRT_TO_BUS(p_i82559->rx_ring[0]),
-                 ioaddr + SCBPointer);
-            OUTW(RUC_START, ioaddr + SCBCmd);
-        }
-    }
     p_i82559->next_rx_descriptor = next_descriptor;
 }
 
@@ -1320,7 +1137,7 @@ static void i82559_recv( struct eth_drv_
     
 #ifdef DEBUG_82559
     os_printf("Rx %d %x (status %x): %d sg's, %d bytes\n",
-              p_i82559->index, (int)priv, p_rfd->status, sg_len, total_len);
+              p_i82559->index, (int)p_i82559, p_rfd->status, sg_len, total_len);
 #endif
 
     // Copy the data to the network stack
@@ -1377,7 +1194,6 @@ static void InitTxRing(struct i82559* p_
     for ( i = 0; i < MAX_TX_DESCRIPTORS; i++) {
         p_i82559->tx_ring[i] = (TxCB *)pciwindow_mem_alloc(
             sizeof(TxCB) + MAX_TX_PACKET_SIZE);
-        p_i82559->tx_keys[i] = 0;
     }
 
     ResetTxRing(p_i82559);
@@ -1398,6 +1214,7 @@ static void ResetTxRing(struct i82559* p
 #endif
     ioaddr = p_i82559->io_address;
     p_i82559->tx_descriptor_add =
+        p_i82559->tx_descriptor_active = 
         p_i82559->tx_descriptor_remove = 0;
     p_i82559->tx_in_progress =
         p_i82559->tx_queue_full = 0;
@@ -1418,11 +1235,102 @@ static void ResetTxRing(struct i82559* p
         p_i82559->tx_keys[i] = 0;
     }
     
-    wait_for_cmd_done(ioaddr + SCBCmd);
+    wait_for_cmd_done(ioaddr);
     OUTL(0, ioaddr + SCBPointer);
-    OUTW(CU_CMD_BASE, ioaddr + SCBCmd);
+    OUTW(SCB_M | CU_ADDR_LOAD, ioaddr + SCBCmd);
 }
 
+// ------------------------------------------------------------------------
+//
+//  Function : TxMachine          (Called from FG & ISR)
+//
+// This steps the Tx Machine onto the next record if necessary - allowing
+// for missed interrupts, and so on.
+// ------------------------------------------------------------------------
+
+static void TxMachine(struct i82559* p_i82559)
+{
+    int tx_descriptor_active;
+    cyg_uint32 ioaddr;
+
+    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)
+    if ( p_i82559->tx_in_progress ) {
+        cyg_uint16 status;
+        status = INW(ioaddr + SCBStatus);
+        if ( 0 == (status & CU_STATUS_MASK) ) {
+            // It is idle.  So ack the TX interrupts
+            OUTW( SCB_INTACK_TX, ioaddr + SCBStatus);
+            // (see pages 6-10 & 6-90)
+
+            // and step on to the next queued tx.
+            p_i82559->tx_in_progress = 0;
+            if ( ++tx_descriptor_active >= MAX_TX_DESCRIPTORS )
+                tx_descriptor_active = 0;
+            p_i82559->tx_descriptor_active = tx_descriptor_active;
+        }
+    }
+
+    // is the CU idle, and there a next tx to set going?
+    if ( ( ! p_i82559->tx_in_progress )
+         && p_i82559->tx_descriptor_add != tx_descriptor_active ) {
+        TxCB *p_txcb;
+        p_txcb = p_i82559->tx_ring[tx_descriptor_active];
+        CYG_ASSERT( (cyg_uint8 *)p_txcb >= i82559_heap_base, "txcb under" );
+        CYG_ASSERT( (cyg_uint8 *)p_txcb <  i82559_heap_free, "txcb over" );
+#ifdef DEBUG_82559
+        os_printf("Tx %d %x: Starting Engines, KEY %x\n",
+                  p_i82559->index, (int)p_i82559, key );
+#endif
+        // make sure no command operating
+        wait_for_cmd_done(ioaddr); 
+        // start Tx operation
+        OUTL(VIRT_TO_BUS(p_txcb), ioaddr + SCBPointer);
+        OUTW(CU_START, ioaddr + SCBCmd);
+        p_i82559->tx_in_progress = 1;
+    }
+}
+
+// ------------------------------------------------------------------------
+//
+//  Function : TxDone          (Called from DSR)
+//
+// This returns Tx's from the Tx Machine to the stack (ie. reports
+// completion) - allowing for missed interrupts, and so on.
+// ------------------------------------------------------------------------
+
+static void TxDone(struct i82559* p_i82559)
+{
+    struct cyg_netdevtab_entry *ndp;
+    struct eth_drv_sc *sc;
+    int tx_descriptor_remove = p_i82559->tx_descriptor_remove;
+
+    ndp = (struct cyg_netdevtab_entry *)(p_i82559->ndp);
+    sc = (struct eth_drv_sc *)(ndp->device_instance);
+
+    CHECK_NDP_SC_LINK();
+    
+    // "Done" txen are from here to active, OR 
+    // the remove one if the queue is full AND its status is nonzero:
+    while (  (tx_descriptor_remove != p_i82559->tx_descriptor_active) ||
+             ( p_i82559->tx_queue_full &&
+              (0 != p_i82559->tx_ring[ tx_descriptor_remove ]->status) ) ) {
+        unsigned long key = p_i82559->tx_keys[ tx_descriptor_remove ];
+#ifdef DEBUG_82559
+        os_printf("TxDone %d %x: KEY %x\n",
+                  p_i82559->index, (int)p_i82559, key );
+#endif
+        eth_drv_tx_done( sc, key, 1 /* status */ );
+        
+        if ( ++tx_descriptor_remove >= MAX_TX_DESCRIPTORS )
+            tx_descriptor_remove = 0;
+        p_i82559->tx_descriptor_remove = tx_descriptor_remove;
+        p_i82559->tx_queue_full = 0;
+    }
+}
 
 
 // ------------------------------------------------------------------------
@@ -1444,6 +1352,12 @@ i82559_can_send(struct eth_drv_sc *sc)
         os_printf( "i82559_send: Bad device pointer %x\n", p_i82559 );
         return 0;
     }
+    
+    // Advance TxMachine atomically
+    Mask82559Interrupt(p_i82559);
+    TxMachine(p_i82559);
+    Acknowledge82559Interrupt(p_i82559);
+    UnMask82559Interrupt(p_i82559);
 
     return ! p_i82559->tx_queue_full;
 }
@@ -1473,7 +1387,7 @@ i82559_send(struct eth_drv_sc *sc,
 
 #ifdef DEBUG_82559
     os_printf("Tx %d %x: %d sg's, %d bytes, KEY %x\n",
-              p_i82559->index, (int)priv, sg_len, total_len, key );
+              p_i82559->index, (int)p_i82559, sg_len, total_len, key );
 #endif
 
     if ( ! p_i82559->active )
@@ -1485,7 +1399,7 @@ i82559_send(struct eth_drv_sc *sc,
 
     if ( p_i82559->tx_queue_full ) {
 #ifdef KEEP_STATISTICS
-        statistics[p_i82559->index].tx_dropped++
+        statistics[p_i82559->index].tx_dropped++;
 #endif
         os_printf( "i82559_send: Queue full, device %x, key %x\n",
                    p_i82559, key );
@@ -1543,209 +1457,33 @@ i82559_send(struct eth_drv_sc *sc,
         CYG_ASSERT( &p_txcb->buffer[0] + MAX_TX_PACKET_SIZE >= to_p,
                     "to_p overflow in tx" );
   
+        // Next descriptor
         if ( ++tx_descriptor_add >= MAX_TX_DESCRIPTORS)
             tx_descriptor_add = 0;
+        p_i82559->tx_descriptor_add = tx_descriptor_add;
 
-        // no more interrupts until started
-        Mask82559Interrupt(p_i82559);
-
-        p_i82559->tx_descriptor_add = tx_descriptor_add;
-        
         if ( p_i82559->tx_descriptor_remove == tx_descriptor_add )
             p_i82559->tx_queue_full = 1;
-
-        if ( ! p_i82559->tx_in_progress ) { // if no Tx operation running
-#ifdef DEBUG_82559
-            os_printf("Tx %d %x: Starting Engines, KEY %x\n",
-                      p_i82559->index, (int)priv, key );
-#endif
-            // flag start of Tx operation
-            p_i82559->tx_in_progress = 1; 
-            // make sure no command operating
-    	    wait_for_cmd_done(ioaddr + SCBCmd); 
-            // start Tx operation
-            OUTL(VIRT_TO_BUS(p_txcb), ioaddr + SCBPointer);
-            OUTW(CU_START, ioaddr + SCBCmd);
-        }
-        UnMask82559Interrupt(p_i82559);     // Allow this device to interrupt
     }
 
-}
-
-
-
-// ------------------------------------------------------------------------
-//
-//  Function : TxComplete
-//
-// ------------------------------------------------------------------------
-static unsigned long TxComplete(struct i82559* p_i82559)
-{
-    int tx_descriptor_remove;
-    cyg_uint32 ioaddr;
-    TxCB *p_txcb;
-    unsigned long key;
-
-    tx_descriptor_remove = p_i82559->tx_descriptor_remove;
-    
-    CYG_ASSERT( p_i82559->tx_in_progress, "Tx not in progress but Tx intr" );
-
-    key = p_i82559->tx_keys[tx_descriptor_remove];
-    if ( ++tx_descriptor_remove >= MAX_TX_DESCRIPTORS )
-        tx_descriptor_remove = 0;
-    p_i82559->tx_descriptor_remove = tx_descriptor_remove;
-    p_i82559->tx_queue_full = 0;
-    if ( p_i82559->tx_descriptor_add != tx_descriptor_remove ) {
-        // get device I/O address
-        ioaddr = p_i82559->io_address;  
-        p_txcb = p_i82559->tx_ring[tx_descriptor_remove];
-        CYG_ASSERT( (cyg_uint8 *)p_txcb >= i82559_heap_base, "txcb under" );
-        CYG_ASSERT( (cyg_uint8 *)p_txcb <  i82559_heap_free, "txcb over" );
-        // make sure no command operating
-        wait_for_cmd_done(ioaddr + SCBCmd); 
-        // start Tx operation
-        OUTL(VIRT_TO_BUS(p_txcb), ioaddr + SCBPointer);
-        OUTW(CU_START, ioaddr + SCBCmd);
-    }
-    else
-        p_i82559->tx_in_progress = 0;
+    // Try advancing the Tx Machine regardless
 
-    return key;
-}
-
-// ------------------------------------------------------------------------
-
-static void
-PacketTxDone(struct i82559* p_i82559, unsigned long key)
-{
-    struct cyg_netdevtab_entry *ndp;
-    struct eth_drv_sc *sc;
-
-    // Just tell the stack that this device has done a Tx.
-    ndp = (struct cyg_netdevtab_entry *)(p_i82559->ndp);
-    sc = (struct eth_drv_sc *)(ndp->device_instance);
-
-    CHECK_NDP_SC_LINK();
-
-#ifdef DEBUG_82559
-    os_printf("TxDone %d %x: KEY %x\n",
-              p_i82559->index, (int)p_i82559, key );
-#endif
-
-    eth_drv_tx_done( sc, key, 1 /* status */ );
-}
-
-
-// ------------------------------------------------------------------------
-//
-//  Function : QueueThreadRequest
-//
-// ------------------------------------------------------------------------
-static void QueueThreadRequest(int type,
-                               struct i82559* p_i82559,
-                               unsigned long key)
-{
-    if ( ! i82559_q_full ) {
-
-        i82559_queue[i82559_q_in].request = type;
-        i82559_queue[i82559_q_in].p = p_i82559;
-        i82559_queue[i82559_q_in].key = key;
-
-        if ( ++i82559_q_in >= I82559_QUEUE_SIZE )
-            i82559_q_in = 0;
+    // no more interrupts until started
+    Mask82559Interrupt(p_i82559);
 
-        if ( i82559_q_in == i82559_q_out )
-            i82559_q_full = 1;
-    }
-}
-
-
-
-// ------------------------------------------------------------------------
-//
-//  Function : i82559_isr
-//
-// ------------------------------------------------------------------------
-int last_status[16] = { 0 };
-int last_index = 0;
-
-static int i82559_isr(struct i82559* p_i82559)
-{
-    cyg_uint16 status;
-    cyg_uint32 io_address;
-    int return_value;
-
-    IF_BAD_82559( p_i82559 ) {
-        os_printf( "i82559_isr: Bad device pointer %x\n", p_i82559 );
-        return 0;
-    }
-
-    io_address = p_i82559->io_address;
-    status = INW(io_address + SCBStatus);
-    OUTW(status & 0xFC00, io_address + SCBStatus);
-
-    return_value = 0;
-
-    last_status[last_index++] = status;
-    last_status[last_index &= 15] = -1;
-
-    // receiver left ready state ?
-    if ( status & SCB_STATUS_RNR ) {    
-#ifdef KEEP_STATISTICS
-        statistics[p_i82559->index].rx_resource++;
-#endif
-        // flag out of resources
-        p_i82559->out_of_resources = 1; 
-    }
+    // 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)),
+                "Active/add mismatch" );
 
-    // frame receive interrupt ?
-    if ( status & SCB_STATUS_FR ) {     
-#ifdef KEEP_STATISTICS
-        statistics[p_i82559->index].rx_count++;
-#endif
-        QueueThreadRequest(PACKET_RX, p_i82559, 0);
-        return_value = 1;
-    }
-
-    // transmit interrupt ?
-    if ( status & SCB_STATUS_CX ) {
-        unsigned long key;
-#ifdef KEEP_STATISTICS
-        statistics[p_i82559->index].tx_complete++;
-#endif
-        key = TxComplete(p_i82559);
-        QueueThreadRequest(PACKET_TX, p_i82559, key);
-        return_value = 1;
-    }
-
-    return return_value;
-}
-
-// ------------------------------------------------------------------------
-//
-//  Function : i82559_mux_isr
-//
-// ------------------------------------------------------------------------
-static int i82559_mux_isr(void)
-{
-    int return_value = 0;
-
-    static int mux_device_index = 0;
-
-    int device_index = mux_device_index;
-
-    return_value = i82559_isr( &i82559[device_index] );
-
-    mux_device_index ^= 1;              // look at the other one first next time.
-    
-    if ( return_value )
-        return return_value;
-
-    device_index = mux_device_index;
-
-    return_value = i82559_isr( &i82559[device_index] );
-
-    return return_value;
+    // Advance TxMachine atomically
+    TxMachine(p_i82559);
+    Acknowledge82559Interrupt(p_i82559);
+    UnMask82559Interrupt(p_i82559);
 }
 
 // ------------------------------------------------------------------------
@@ -1760,7 +1498,7 @@ static void i82559_reset(struct i82559* 
 
     ioaddr = p_i82559->io_address;
     // make sure no command operating
-    wait_for_cmd_done(ioaddr + SCBCmd);   
+    wait_for_cmd_done(ioaddr);   
  
     OUTL(I82559_SELECTIVE_RESET, ioaddr + SCBPort);
   
@@ -1778,6 +1516,313 @@ static void i82559_reset(struct i82559* 
 
 // ------------------------------------------------------------------------
 //
+//                       INTERRUPT HANDLERS
+//
+// ------------------------------------------------------------------------
+
+static cyg_uint32 eth_isr(cyg_vector_t vector, cyg_addrword_t data)
+{
+    struct i82559* p_i82559 = (struct i82559 *)data;
+    cyg_uint16 status;
+    cyg_uint32 ioaddr;
+
+    IF_BAD_82559( p_i82559 ) {
+        os_printf( "i82559_isr: Bad device pointer %x\n", p_i82559 );
+        return 0;
+    }
+
+    ioaddr = p_i82559->io_address;
+    status = INW(ioaddr + SCBStatus);
+    // Acknowledge all INT sources that were active
+    OUTW( status & SCB_INTACK_MASK, ioaddr + SCBStatus);
+    // (see pages 6-10 & 6-90)
+
+#ifdef KEEP_STATISTICS
+    statistics[p_i82559->index].interrupts++;
+
+    // receiver left ready state ?
+    if ( status & SCB_STATUS_RNR )
+        statistics[p_i82559->index].rx_resource++;
+
+    // frame receive interrupt ?
+    if ( status & SCB_STATUS_FR )
+        statistics[p_i82559->index].rx_count++;
+
+    // transmit interrupt ?
+    if ( status & SCB_STATUS_CX )
+        statistics[p_i82559->index].tx_complete++;
+#endif
+
+    // Advance the Tx Machine regardless
+    TxMachine(p_i82559);
+
+    // it should have settled down now...
+    Acknowledge82559Interrupt(p_i82559);
+
+    return CYG_ISR_CALL_DSR;        // schedule DSR
+}
+
+
+// ------------------------------------------------------------------------
+static int mux_device_index = 0;
+
+static cyg_uint32 eth_mux_isr(cyg_vector_t vector, cyg_addrword_t data)
+{
+    int device_index = mux_device_index;
+    struct i82559* p_i82559;
+
+    mux_device_index ^= 1; // look at the other one first next time.
+
+    do {
+        p_i82559 = &i82559[device_index];
+        if ( p_i82559->active )
+            (void)eth_isr( vector, (cyg_addrword_t)p_i82559 );
+        device_index ^= 1;
+    } while ( device_index == mux_device_index );
+
+    return CYG_ISR_CALL_DSR;
+}
+
+// ------------------------------------------------------------------------
+
+void eth_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+    struct i82559* p_i82559 = (struct i82559 *)data;
+
+    // First pass any rx data up the stack
+    PacketRxReady(p_i82559);
+
+    // Then scan for completed Txen and inform the stack
+    TxDone(p_i82559);
+}
+
+
+// ------------------------------------------------------------------------
+void eth_mux_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+    int device_index = mux_device_index;
+    struct i82559* p_i82559;
+
+    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 );
+        device_index ^= 1;
+    } while ( device_index == mux_device_index );
+}
+
+// ------------------------------------------------------------------------
+//
+//  Function : pci_init_find_82559s
+//
+// This is called exactly once at the start of time to:
+//  o scan the PCI bus for objects
+//  o record them in the device table
+//  o acquire all the info needed for the driver to access them
+//  o instantiate interrupts for them
+//  o attach those interrupts appropriately
+// ------------------------------------------------------------------------
+static int
+pci_init_find_82559s( void )
+{
+    cyg_pci_device_id devid;
+    cyg_pci_device dev_info;
+    cyg_uint16 cmd;
+    int device_index;
+
+    // MUX interrupt - special case when 2 cards share one intr.
+    static cyg_handle_t mux_interrupt_handle = 0;
+    static cyg_interrupt mux_interrupt_object;
+
+#ifdef DEBUG
+    db_printf("pci_init_find_82559s()\n");
+#endif
+
+    // allocate memory to be used in ioctls later
+    if (mem_reserved_ioctl != (void*)0) {
+        db_printf("pci_init_find_82559s() called > once\n");
+        return 0;
+    }
+
+    // First initialize the heap in PCI window'd memory
+    i82559_heap_size = CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_SIZE;
+    i82559_heap_base = (cyg_uint8 *)CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_BASE;
+    i82559_heap_free = i82559_heap_base;
+
+    mem_reserved_ioctl = pciwindow_mem_alloc(MAX_MEM_RESERVED_IOCTL);     
+
+    cyg_pci_init();
+#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++) {
+        struct i82559 *p_i82559 = &i82559[device_index];
+        p_i82559->index = device_index;
+
+        if (cyg_pci_find_device(0x8086, 0x1229, &devid) ) {
+#ifdef DEBUG
+            db_printf("eth%d = 82559\n", device_index);
+#endif
+            cyg_pci_get_device_info(devid, &dev_info);
+
+            if (cyg_pci_translate_interrupt(&dev_info, &p_i82559->vector)) {
+#ifdef DEBUG
+                db_printf(" Wired to HAL vector %d\n", p_i82559->vector);
+#endif
+                cyg_drv_interrupt_create(
+                    p_i82559->vector,
+                    0,                  // Priority - unused
+                    (CYG_ADDRWORD)p_i82559, // Data item passed to ISR & DSR
+                    eth_isr,            // ISR
+                    eth_dsr,            // DSR
+                    &p_i82559->interrupt_handle, // handle to intr obj
+                    &p_i82559->interrupt_object ); // space for int obj
+
+                cyg_drv_interrupt_attach(p_i82559->interrupt_handle);
+
+                // Don't unmask the interrupt yet, that could get us into a
+                // race.
+
+                // ALSO attach it to interrupt #18 for multiplexed
+                // interrupts.  This is for certain boards where the
+                // PCI backplane is wired "straight through" instead of
+                // with a rotation of interrupt lines in the different
+                // slots.
+                if ( ! mux_interrupt_handle ) {
+#ifdef DEBUG
+                    db_printf(" Also attaching to HAL vector %d\n", 
+                              CYGNUM_HAL_INTERRUPT_PCI_IRQ);
+#endif
+                    cyg_drv_interrupt_create(
+                        CYGNUM_HAL_INTERRUPT_PCI_IRQ,
+                        0,              // Priority - unused
+                        0,              // Data item passed to ISR (not used)
+                        eth_mux_isr,    // ISR
+                        eth_mux_dsr,    // DSR
+                        &mux_interrupt_handle,
+                        &mux_interrupt_object );
+                    
+                    cyg_drv_interrupt_attach(mux_interrupt_handle);
+                }
+            }
+            else {
+                p_i82559->vector=0;
+#ifdef DEBUG
+                db_printf(" Does not generate interrupts.\n");
+#endif
+            }
+
+            if (cyg_pci_configure_device(&dev_info)) {
+#ifdef DEBUG
+                int i;
+                db_printf("Found device on bus %d, devfn 0x%02x:\n",
+                          CYG_PCI_DEV_GET_BUS(devid),
+                          CYG_PCI_DEV_GET_DEVFN(devid));
+
+                if (dev_info.command & CYG_PCI_CFG_COMMAND_ACTIVE) {
+                    db_printf(" Note that board is active. Probed"
+                              " sizes and CPU addresses invalid!\n");
+                }
+                db_printf(" Vendor    0x%04x", dev_info.vendor);
+                db_printf("\n Device    0x%04x", dev_info.device);
+                db_printf("\n Command   0x%04x, Status 0x%04x\n",
+                          dev_info.command, dev_info.status);
+                
+                db_printf(" Class/Rev 0x%08x", dev_info.class_rev);
+                db_printf("\n Header 0x%02x\n", dev_info.header_type);
+
+                db_printf(" SubVendor 0x%04x, Sub ID 0x%04x\n",
+                          dev_info.header.normal.sub_vendor, 
+                          dev_info.header.normal.sub_id);
+
+                for(i = 0; i < CYG_PCI_MAX_BAR; i++) {
+                    db_printf(" BAR[%d]    0x%08x /", i, dev_info.base_address[i]);
+                    db_printf(" probed size 0x%08x / CPU addr 0x%08x\n",
+                              dev_info.base_size[i], dev_info.base_map[i]);
+                }
+                db_printf(" eth%d configured\n", device_index);
+#endif
+                p_i82559->found = 1;
+                p_i82559->active = 0;
+                p_i82559->devid = devid;
+                p_i82559->memory_address = dev_info.base_map[0];
+                p_i82559->io_address = dev_info.base_map[1];
+#ifdef DEBUG
+                db_printf(" memory address = 0x%08x\n", dev_info.base_map[0]);
+                db_printf(" I/O address = 0x%08x\n", dev_info.base_map[1]);
+#endif
+
+                // Don't use cyg_pci_set_device_info since it clears
+                // some of the fields we want to print out below.
+                cyg_pci_read_config_uint16(dev_info.devid, CYG_PCI_CFG_COMMAND, &cmd);
+                cmd |= CYG_PCI_CFG_COMMAND_IO // enable I/O space
+                    | CYG_PCI_CFG_COMMAND_MEMORY // enable memory space
+                    | CYG_PCI_CFG_COMMAND_MASTER; // enable bus master
+                cyg_pci_write_config_uint16(dev_info.devid, CYG_PCI_CFG_COMMAND, cmd);
+
+                // Now the PCI part of the device is configured, reset it. This 
+                // should make it safe to enable the interrupt
+                i82559_reset(p_i82559);
+
+                if (p_i82559->vector != 0) {
+                    cyg_interrupt_acknowledge(p_i82559->vector);
+                    cyg_drv_interrupt_unmask(p_i82559->vector);
+                }
+#ifdef DEBUG
+                db_printf(" **** Device enabled for I/O and Memory and Bus Master\n");
+#endif
+            }
+            else {
+                p_i82559->found = 0;
+                p_i82559->active = 0;
+                db_printf("Failed to configure device %d\n",device_index);
+            }
+        }
+        else {
+            p_i82559->found = 0;
+            p_i82559->active = 0;
+            db_printf("eth%d not found\n", device_index);
+        }
+    }
+
+    // Now enable the mux shared interrupt if it is in use
+    if (mux_interrupt_handle) {
+        cyg_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_PCI_IRQ);
+        cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_PCI_IRQ);
+    }
+
+    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
 //
 //  Return : 0 = It worked.
@@ -1796,14 +1841,14 @@ static int eth_set_promiscuous_mode(stru
     }
 
     ioaddr = p_i82559->io_address;  
-    wait_for_cmd_done(ioaddr + SCBCmd); 
+    wait_for_cmd_done(ioaddr); 
     // load cu base address = 0 */ 
     OUTL(0, ioaddr + SCBPointer);         
     // 32 bit linear addressing used
                                         
-    OUTW(SCB_M | CUC_ADDR_LOAD, ioaddr + SCBCmd);
+    OUTW(SCB_M | CU_ADDR_LOAD, ioaddr + SCBCmd);
     // wait for SCB command complete
-    wait_for_cmd_done(ioaddr + SCBCmd);   
+    wait_for_cmd_done(ioaddr);   
   
     ccs = (CONFIG_CMD_STRUCT *)mem_reserved_ioctl;
   
@@ -1844,13 +1889,13 @@ static int eth_set_promiscuous_mode(stru
     ccs->config_bytes[18]=0x70;
     
     // wait for SCB command complete
-    wait_for_cmd_done(ioaddr + SCBCmd);   
+    wait_for_cmd_done(ioaddr);   
     
     OUTL(VIRT_TO_BUS(ccs), ioaddr + SCBPointer); 
-    OUTW(SCB_M | CUC_START, ioaddr + SCBCmd);    
+    OUTW(SCB_M | CU_START, ioaddr + SCBCmd);    
   
     // now check for result ...
-    wait_for_cmd_done(ioaddr + SCBCmd);   
+    wait_for_cmd_done(ioaddr);   
   
     if ( (!ccs->cb_entry.cb_ok) || (!ccs->cb_entry.cb_complete) )
         return 1; // Failed
@@ -1879,14 +1924,14 @@ static int eth_set_mac_address(struct i8
 
     ioaddr = p_i82559->io_address;      
     
-    wait_for_cmd_done(ioaddr + SCBCmd); 
+    wait_for_cmd_done(ioaddr); 
     // load cu base address = 0 */ 
     OUTL(0, ioaddr + SCBPointer);       
     // 32 bit linear addressing used
                                         
-    OUTW(SCB_M | CUC_ADDR_LOAD, ioaddr + SCBCmd);
+    OUTW(SCB_M | CU_ADDR_LOAD, ioaddr + SCBCmd);
     // wait for SCB command complete
-    wait_for_cmd_done(ioaddr + SCBCmd); 
+    wait_for_cmd_done(ioaddr); 
     
     ccs = (CONFIG_CMD_STRUCT *)mem_reserved_ioctl;
     if (ccs == (void*)0)
@@ -1907,12 +1952,12 @@ static int eth_set_mac_address(struct i8
     ioaddr = p_i82559->io_address;  
   
     OUTL(VIRT_TO_BUS(ccs), ioaddr + SCBPointer); 
-    OUTW(SCB_M | CUC_START, ioaddr + SCBCmd);    
+    OUTW(SCB_M | CU_START, ioaddr + SCBCmd);    
     // Next delay seems to be required, otherwise,
     // cb_ok/cb_complete won't be set later.
 
     udelay(100);
-    wait_for_cmd_done(ioaddr + SCBCmd);   
+    wait_for_cmd_done(ioaddr);   
   
     // now check for result ...
     if ( (!ccs->cb_entry.cb_ok) || (!ccs->cb_entry.cb_complete) )
@@ -2105,266 +2150,200 @@ static int i82559_ioctl(struct eth_drv_s
 
 // ------------------------------------------------------------------------
 //
-//                       INTERRUPT HANDLERS
+//
+//           CODE FOR DEBUGGING PURPOSES ONLY
+//
 //
 // ------------------------------------------------------------------------
-
-static cyg_uint32 eth_isr(cyg_vector_t vector, cyg_addrword_t data)
+void dump_txcb(TxCB *p_txcb)
 {
-    int schedule_dsr;
-
-    cyg_drv_interrupt_mask(vector);     // mask this interrupt
-
-    schedule_dsr = i82559_isr( (struct i82559 *)data ); // process interrupt
-
-    cyg_drv_interrupt_acknowledge(vector); // acknowledge interrupt
-
-    // schedule further processing ?
-    if ( schedule_dsr )
-        return CYG_ISR_CALL_DSR;        // yes, schedule DSR
-
-    // else...
-    cyg_drv_interrupt_unmask(vector);   // allow more of these interrupts
-    return CYG_ISR_HANDLED;
+    os_printf("TxCB @ %x\n", (int)p_txcb);
+    os_printf("status = %04X ", p_txcb->status);
+    os_printf("command = %04X ", p_txcb->command);
+    os_printf("link = %08X ", p_txcb->link);
+    os_printf("tbd = %08X ", p_txcb->tbd_address);
+    os_printf("count = %d ", p_txcb->count);
+    os_printf("eof = %x ", p_txcb->eof);
+    os_printf("threshold = %d ", p_txcb->tx_threshold);
+    os_printf("tbd number = %d\n", p_txcb->tbd_number);
 }
 
 
-
-static cyg_uint32 eth_mux_isr(cyg_vector_t vector, cyg_addrword_t data)
+// This is intended to be the body of a THREAD that prints stuff every 10
+// seconds or so:
+#ifdef KEEP_STATISTICS
+#ifdef DISPLAY_STATISTICS
+void DisplayStatistics(void)
 {
-    int schedule_dsr;
-
-    cyg_drv_interrupt_mask( vector );   // mask this interrupt
-
-    schedule_dsr = i82559_mux_isr();    // process interrupt
+    int i;
+    I82559_COUNTERS *p_statistics;
+    cyg_uint32 *p_counter;
+    cyg_uint32 *p_register;
+    int reg_count;
+    int status;
+    
+    while ( 1 ) {
+#ifdef DISPLAY_82559_STATISTICS
+        for ( i = 0; i < 2; i ++ ) {
+            p_statistics = (I82559_COUNTERS *)i82559[i].p_statistics;
+            if ( (p_statistics->done & 0xFFFF) == 0xA007 ) {
+                p_counter = (cyg_uint32 *)&i82559_counters[i];
+                p_register = (cyg_uint32 *)&p_statistics->tx_good;
+                for ( reg_count = 20; reg_count != 0; reg_count--) {
+                    *p_counter += *p_register;
+                    p_counter++;
+                    p_register++;
+                }
+                p_statistics->done = 0;
+                // make sure no command operating
+            	wait_for_cmd_done(i82559[i].io_address);
+                // start register dump
+                OUTW(CU_DUMPSTATS, i82559[i].io_address + SCBCmd);
+            }
+        }
+#endif
+        os_printf("\nRx\nPackets = %d  %d\n",
+        statistics[0].rx_count, statistics[1].rx_count);
+        os_printf("Deliver   %d  %d\n",
+        statistics[0].rx_deliver, statistics[1].rx_deliver);
+        os_printf("Resource  %d  %d\n",
+        statistics[0].rx_resource, statistics[1].rx_resource);
+        os_printf("Restart   %d  %d\n",
+        statistics[0].rx_restart, statistics[1].rx_restart);
 
-    cyg_drv_interrupt_acknowledge( vector ); // ack interrupt
+#ifdef DISPLAY_82559_STATISTICS
+        os_printf("Count     %d  %d\n",
+        i82559_counters[0].rx_good, i82559_counters[1].rx_good);
+        os_printf("CRC       %d  %d\n",
+        i82559_counters[0].rx_crc_errors, i82559_counters[1].rx_crc_errors);
+        os_printf("Align     %d  %d\n",
+        i82559_counters[0].rx_align_errors, i82559_counters[1].rx_align_errors);
+        os_printf("Resource  %d  %d\n",
+        i82559_counters[0].rx_resource_errors, i82559_counters[1].rx_resource_errors);
+        os_printf("Overrun   %d  %d\n",
+        i82559_counters[0].rx_overrun_errors, i82559_counters[1].rx_overrun_errors);
+        os_printf("Collision %d  %d\n",
+        i82559_counters[0].rx_collisions, i82559_counters[1].rx_collisions);
+        os_printf("Short     %d  %d\n",
+        i82559_counters[0].rx_short_frames, i82559_counters[1].rx_short_frames);
+#endif
+        os_printf("\nTx\nPackets = %d  %d\n",
+        statistics[0].tx_count, statistics[1].tx_count);
+        os_printf("Complete  %d  %d\n",
+        statistics[0].tx_complete, statistics[1].tx_complete);
+        os_printf("Dropped   %d  %d\n",
+        statistics[0].tx_dropped, statistics[1].tx_dropped);
+        os_printf("Count     %d  %d\n",
+        i82559_counters[0].tx_good, i82559_counters[1].tx_good);
+#ifdef DISPLAY_82559_STATISTICS
+        os_printf("Collision %d  %d\n",
+        i82559_counters[0].tx_max_collisions,i82559_counters[1].tx_max_collisions);
+        os_printf("Late Col. %d  %d\n",
+        i82559_counters[0].tx_late_collisions,i82559_counters[1].tx_late_collisions);
+        os_printf("Underrun  %d  %d\n",
+        i82559_counters[0].tx_underrun,i82559_counters[1].tx_underrun);
+        os_printf("Carrier   %d  %d\n",
+        i82559_counters[0].tx_carrier_loss,i82559_counters[1].tx_carrier_loss);
+        os_printf("Deferred  %d  %d\n",
+        i82559_counters[0].tx_deferred, i82559_counters[1].tx_deferred);
+        os_printf("1 Col     %d  %d\n",
+        i82559_counters[0].tx_single_collisions, i82559_counters[0].tx_single_collisions);
+        os_printf("Mult. Col %d  %d\n",
+        i82559_counters[0].tx_mult_collisions, i82559_counters[0].tx_mult_collisions);
+        os_printf("Total Col %d  %d\n",
+        i82559_counters[0].tx_total_collisions, i82559_counters[0].tx_total_collisions);
+#endif
+        status = INB(i82559[0].io_address + SCBGenStatus);
+        os_printf("Interface 0 Link = %s, %s Mbps, %s Duplex\n",
+            status & GEN_STATUS_LINK ? "Up" : "Down",
+            status & GEN_STATUS_100MBPS ?  "100" : "10",
+            status & GEN_STATUS_FDX ? "Full" : "Half");
+
+        status = INB(i82559[1].io_address + SCBGenStatus);
+        os_printf("Interface 1 Link = %s, %s Mbps, %s Duplex\n",
+            status & GEN_STATUS_LINK ? "Up" : "Down",
+            status & GEN_STATUS_100MBPS ?  "100" : "10",
+            status & GEN_STATUS_FDX ? "Full" : "Half");
+
+        cyg_thread_delay(1000);
+    }
+}
+#endif // DISPLAY_STATISTICS
+#endif // KEEP_STATISTICS
 
-    // schedule further processing ?
-    if ( schedule_dsr )
-        return CYG_ISR_CALL_DSR;        // yes, schedule DSR
-    
-    // else...
-    cyg_drv_interrupt_unmask( vector ); // allow more of these interrupts
-    return CYG_ISR_HANDLED;
+void dump_rfd(RFD *p_rfd, int anyway )
+{
+    if ( (0 != p_rfd->status) || anyway ) {
+        os_printf("RFD @ %x = ", (int)p_rfd);
+        os_printf("status = %x ", p_rfd->status);
+        os_printf("link = %x ", p_rfd->link);
+//        os_printf("rdb_address = %x ", p_rfd->rdb_address);
+        os_printf("count = %x ", p_rfd->count);
+        os_printf("f = %x ", p_rfd->f);
+        os_printf("eof = %x ", p_rfd->eof);
+        os_printf("size = %x\n", p_rfd->size);
+        os_printf("[%04x %04x %04x] ",
+                  *((cyg_uint16 *)(&(p_rfd->buffer[0]))),
+                  *((cyg_uint16 *)(&(p_rfd->buffer[2]))),
+                  *((cyg_uint16 *)(&(p_rfd->buffer[4]))) );
+        os_printf("[%04x %04x %04x] %04x : ",          
+                  *((cyg_uint16 *)(&(p_rfd->buffer[6]))),
+                  *((cyg_uint16 *)(&(p_rfd->buffer[8]))),
+                  *((cyg_uint16 *)(&(p_rfd->buffer[10]))),
+                  *((cyg_uint16 *)(&(p_rfd->buffer[12]))) );
+        os_printf("(%04x %04x %04x %04x) ",            
+                  *((cyg_uint16 *)(&(p_rfd->buffer[14]))),
+                  *((cyg_uint16 *)(&(p_rfd->buffer[16]))),
+                  *((cyg_uint16 *)(&(p_rfd->buffer[18]))),
+                  *((cyg_uint16 *)(&(p_rfd->buffer[20]))) );
+        os_printf("[%04x %04x %04x] ",                 
+                  *((cyg_uint16 *)(&(p_rfd->buffer[22]))),
+                  *((cyg_uint16 *)(&(p_rfd->buffer[24]))),
+                  *((cyg_uint16 *)(&(p_rfd->buffer[26]))) );
+        os_printf("%d.%d.%d.%d ",
+                  *((cyg_uint8  *)(&(p_rfd->buffer[28]))),
+                  *((cyg_uint8  *)(&(p_rfd->buffer[29]))),
+                  *((cyg_uint8  *)(&(p_rfd->buffer[30]))),
+                  *((cyg_uint8  *)(&(p_rfd->buffer[31]))) );
+        os_printf("[%04x %04x %04x] ",                 
+                  *((cyg_uint16 *)(&(p_rfd->buffer[32]))),
+                  *((cyg_uint16 *)(&(p_rfd->buffer[34]))),
+                  *((cyg_uint16 *)(&(p_rfd->buffer[36]))) );
+        os_printf("%d.%d.%d.%d ...\n",
+                  *((cyg_uint8  *)(&(p_rfd->buffer[38]))),
+                  *((cyg_uint8  *)(&(p_rfd->buffer[39]))),
+                  *((cyg_uint8  *)(&(p_rfd->buffer[40]))),
+                  *((cyg_uint8  *)(&(p_rfd->buffer[41]))) );
+    }
+}
+
+void dump_all_rfds( int intf )
+{
+    struct i82559* p_i82559 = &i82559[intf];
+    int i, j;
+    j = p_i82559->next_rx_descriptor;
+    os_printf("rx descriptors for interface %d (eth%d):\n", intf, intf );
+    for ( i = 0; i < MAX_RX_DESCRIPTORS; i++ )
+        dump_rfd( p_i82559->rx_ring[i], (i > (j-3) && (i <= j)) );
+    os_printf("next rx descriptor = %x\n\n", j);
+}
+
+
+void dump_packet(cyg_uint8 *p_buffer, int length)
+{
+    int count;
+
+    count = 0;
+    while ( length > 0 ) {
+        if ( count == 0 )
+            os_printf("\n");
+        count = (count + 1) & 0x0F;
+        os_printf("%02X ", *p_buffer++);
+        length--;
+    }
+    os_printf("\n");
 }
 
 // ------------------------------------------------------------------------
 
-void eth_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
-{
-    while ( (i82559_q_out != i82559_q_in) || (i82559_q_full) ) {
-        switch ( i82559_queue[i82559_q_out].request ) {
-        case PACKET_RX:
-            PacketRxReady(i82559_queue[i82559_q_out].p);
-            break;
-            
-        case PACKET_TX:
-            PacketTxDone(i82559_queue[i82559_q_out].p,
-                         i82559_queue[i82559_q_out].key);
-            break;
-        }
-        i82559_q_full = 0;
-        if ( ++i82559_q_out == I82559_QUEUE_SIZE )
-            i82559_q_out = 0;
-    }
-    // allow interrupts to continue from whichever source
-    // (if multiple device actions were dispatched in this DSR call,
-    //  another call will occur almost immediately)
-    cyg_drv_interrupt_unmask(vector);
-}
-
-// ------------------------------------------------------------------------
-//
-//  Function : pci_init_find_82559s
-//
-// This is called exactly once at the start of time to:
-//  o scan the PCI bus for objects
-//  o record them in the device table
-//  o acquire all the info needed for the driver to access them
-//  o instantiate interrupts for them
-//  o attach those interrupts appropriately
-// ------------------------------------------------------------------------
-static int
-pci_init_find_82559s( void )
-{
-    cyg_pci_device_id devid;
-    cyg_pci_device dev_info;
-    cyg_uint16 cmd;
-    int device_index;
-
-    // MUX interrupt - special case when 2 cards share one intr.
-    static cyg_handle_t mux_interrupt_handle = 0;
-    static cyg_interrupt mux_interrupt_object;
-
-#ifdef DEBUG
-    db_printf("pci_init_find_82559s()\n");
-#endif
-
-    // allocate memory to be used in ioctls later
-    if (mem_reserved_ioctl != (void*)0) {
-        db_printf("pci_init_find_82559s() called > once\n");
-        return 0;
-    }
-
-    // First initialize the heap in PCI window'd memory
-    i82559_heap_size = CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_SIZE;
-    i82559_heap_base = (cyg_uint8 *)CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_BASE;
-    i82559_heap_free = i82559_heap_base;
-
-    mem_reserved_ioctl = pciwindow_mem_alloc(MAX_MEM_RESERVED_IOCTL);     
-
-    // initialize the event queue for DSR actions
-    i82559_q_out = i82559_q_in = 0;
-    i82559_q_full = 0;
-
-    cyg_pci_init();
-#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++) {
-        struct i82559 *p_i82559 = &i82559[device_index];
-        p_i82559->index = device_index;
-
-        if (cyg_pci_find_device(0x8086, 0x1229, &devid) ) {
-#ifdef DEBUG
-            db_printf("eth%d = 82559\n", device_index);
-#endif
-            cyg_pci_get_device_info(devid, &dev_info);
-
-            if (cyg_pci_translate_interrupt(&dev_info, &p_i82559->vector)) {
-#ifdef DEBUG
-                db_printf(" Wired to HAL vector %d\n", p_i82559->vector);
-#endif
-                cyg_drv_interrupt_create(
-                    p_i82559->vector,
-                    0,                  // Priority - unused
-                    (CYG_ADDRWORD)p_i82559, // Data item passed to ISR
-                    eth_isr,            // ISR
-                    eth_dsr,            // DSR
-                    &p_i82559->interrupt_handle, // handle to intr obj
-                    &p_i82559->interrupt_object ); // space for int obj
-
-                cyg_drv_interrupt_attach(p_i82559->interrupt_handle);
-
-                // Don't unmask the interrupt yet, that could get us into a
-                // race.
-
-                // ALSO attach it to interrupt #18 for multiplexed
-                // interrupts.  This is for certain boards where the
-                // PCI backplane is wired "straight through" instead of
-                // with a rotation of interrupt lines in the different
-                // slots.
-                if ( ! mux_interrupt_handle ) {
-#ifdef DEBUG
-                    db_printf(" Also attaching to HAL vector %d\n", 
-                              CYGNUM_HAL_INTERRUPT_PCI_IRQ);
-#endif
-                    cyg_drv_interrupt_create(
-                        CYGNUM_HAL_INTERRUPT_PCI_IRQ,
-                        0,              // Priority - unused
-                        0,              // Data item passed to ISR (not used)
-                        eth_mux_isr,    // ISR
-                        eth_dsr,        // DSR
-                        &mux_interrupt_handle,
-                        &mux_interrupt_object );
-                    
-                    cyg_drv_interrupt_attach(mux_interrupt_handle);
-                }
-            }
-            else {
-                p_i82559->vector=0;
-#ifdef DEBUG
-                db_printf(" Does not generate interrupts.\n");
-#endif
-            }
-
-            if (cyg_pci_configure_device(&dev_info)) {
-#ifdef DEBUG
-                int i;
-                db_printf("Found device on bus %d, devfn 0x%02x:\n",
-                          CYG_PCI_DEV_GET_BUS(devid),
-                          CYG_PCI_DEV_GET_DEVFN(devid));
-
-                if (dev_info.command & CYG_PCI_CFG_COMMAND_ACTIVE) {
-                    db_printf(" Note that board is active. Probed"
-                              " sizes and CPU addresses invalid!\n");
-                }
-                db_printf(" Vendor    0x%04x", dev_info.vendor);
-                db_printf("\n Device    0x%04x", dev_info.device);
-                db_printf("\n Command   0x%04x, Status 0x%04x\n",
-                          dev_info.command, dev_info.status);
-                
-                db_printf(" Class/Rev 0x%08x", dev_info.class_rev);
-                db_printf("\n Header 0x%02x\n", dev_info.header_type);
-
-                db_printf(" SubVendor 0x%04x, Sub ID 0x%04x\n",
-                          dev_info.header.normal.sub_vendor, 
-                          dev_info.header.normal.sub_id);
-
-                for(i = 0; i < CYG_PCI_MAX_BAR; i++) {
-                    db_printf(" BAR[%d]    0x%08x /", i, dev_info.base_address[i]);
-                    db_printf(" probed size 0x%08x / CPU addr 0x%08x\n",
-                              dev_info.base_size[i], dev_info.base_map[i]);
-                }
-                db_printf(" eth%d configured\n", device_index);
-#endif
-                p_i82559->found = 1;
-                p_i82559->active = 0;
-                p_i82559->devid = devid;
-                p_i82559->memory_address = dev_info.base_map[0];
-                p_i82559->io_address = dev_info.base_map[1];
-#ifdef DEBUG
-                db_printf(" memory address = 0x%08x\n", dev_info.base_map[0]);
-                db_printf(" I/O address = 0x%08x\n", dev_info.base_map[1]);
-#endif
-
-                // Don't use cyg_pci_set_device_info since it clears
-                // some of the fields we want to print out below.
-                cyg_pci_read_config_uint16(dev_info.devid, CYG_PCI_CFG_COMMAND, &cmd);
-                cmd |= CYG_PCI_CFG_COMMAND_IO // enable I/O space
-                    | CYG_PCI_CFG_COMMAND_MEMORY // enable memory space
-                    | CYG_PCI_CFG_COMMAND_MASTER; // enable bus master
-                cyg_pci_write_config_uint16(dev_info.devid, CYG_PCI_CFG_COMMAND, cmd);
-
-                // Now the PCI part of the device is configured, reset it. This 
-                // should make it safe to enable the interrupt
-                i82559_reset(p_i82559);
-
-                if (p_i82559->vector != 0) {
-                    cyg_interrupt_acknowledge(p_i82559->vector);
-                    cyg_drv_interrupt_unmask(p_i82559->vector);
-                }
-#ifdef DEBUG
-                db_printf(" **** Device enabled for I/O and Memory and Bus Master\n");
-#endif
-            }
-            else {
-                p_i82559->found = 0;
-                p_i82559->active = 0;
-                db_printf("Failed to configure device %d\n",device_index);
-            }
-        }
-        else {
-            p_i82559->found = 0;
-            p_i82559->active = 0;
-            db_printf("eth%d not found\n", device_index);
-        }
-    }
-
-    // Now enable the mux shared interrupt if it is in use
-    if (mux_interrupt_handle) {
-        cyg_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_PCI_IRQ);
-        cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_PCI_IRQ);
-    }
-
-    return 1;
-}
-
-
-
-// ------------------------------------------------------------------------
-
 // EOF if_ebsa285.c
--- a/packages/ecos.db
+++ b/packages/ecos.db
@@ -210,6 +210,31 @@ package CYGPKG_IO_SERIAL_SH_EDK7708 {
 }
 
 
+package CYGPKG_DEVS_ETH_ARM_EDB7XXX {
+	alias 		{ "Cirrus Logic ethernet driver" edb7xxx_eth_driver }
+	hardware
+	directory	devs/eth/arm/edb7xxx
+	script		edb7xxx_eth_drivers.cdl
+        description     "Ethernet driver for Cirrus Logic EDB7xxx development boards."
+}
+
+package CYGPKG_DEVS_ETH_ARM_EBSA285 {
+	alias 		{ "Intel EBSA285 with PRO/100+ ethernet driver"
+			   devs_eth_arm_ebsa285 ebsa285_eth_driver }
+	hardware
+	directory	devs/eth/arm/ebsa285
+	script		ebsa285_eth_drivers.cdl
+        description     "Ethernet driver for Intel EBSA285 with PRO/100+ boards."
+}
+
+package CYGPKG_DEVS_ETH_POWERPC_QUICC {
+	alias 		{ "QUICC ethernet driver" quicc_eth_driver }
+	hardware
+	directory	devs/eth/powerpc/quicc
+	script		quicc_eth_drivers.cdl
+        description     "Ethernet driver for PowerPC QUICC (MPC8xx) based boards."
+}
+
 package CYGPKG_IO_PCI	{
 	alias		{ "PCI configuration library" io_pci }
 	directory	io/pci
--- a/packages/hal/sh/arch/current/ChangeLog
+++ b/packages/hal/sh/arch/current/ChangeLog
@@ -1,3 +1,17 @@
+2000-04-26  Jesper Skov  <jskov@redhat.com>
+
+	* src/hal_mk_defs.c: Added some caching data.
+
+	* src/vectors.S:
+	* include/hal_cache.h:
+	Rewrote caching functions in assembly with appropriate magic to
+	have the code execute out of a non-cachable memory shadow.
+
+2000-04-25  Jesper Skov  <jskov@redhat.com>
+
+	* include/hal_cache.h (HAL_UCACHE_WRITE_MODE): Also wiggle the WT
+	bit. It has opposite polarity of the CB bit.
+
 2000-04-12  Jesper Skov  <jskov@redhat.com>
 
 	* src/vectors.S: Entry code rewritten to allow ROMRAM startups.
--- a/packages/hal/sh/arch/current/include/hal_cache.h
+++ b/packages/hal/sh/arch/current/include/hal_cache.h
@@ -61,6 +61,8 @@
 //-----------------------------------------------------------------------------
 // Cache dimensions - one unified cache
 
+#define HAL_CACHE_UNIFIED
+
 #define HAL_UCACHE_SIZE                 CYGARC_SH_MOD_CAC_SIZE
 #define HAL_UCACHE_LINE_SIZE            CYGARC_SH_MOD_CAC_LINE_SIZE
 #define HAL_UCACHE_WAYS                 CYGARC_SH_MOD_CAC_WAYS
@@ -79,48 +81,28 @@
 //-----------------------------------------------------------------------------
 // Global control of cache
 
+// This is all handled in assembly (see vectors.S) due to a requirement about
+// not fiddling the cache from cachable memory.
+
+externC void cyg_hal_cache_enable(void);
+externC void cyg_hal_cache_disable(void);
+externC void cyg_hal_cache_invalidate_all(void);
+externC void cyg_hal_cache_sync(void);
+externC void cyg_hal_cache_write_mode(int mode);
 
 // Enable the cache
-#define HAL_UCACHE_ENABLE()                     \
-    CYG_MACRO_START                             \
-    register cyg_uint32 __tmp;                  \
-    HAL_READ_UINT32(CYGARC_REG_CCR, __tmp);     \
-    __tmp |= CYGARC_REG_CCR_CE;                 \
-    HAL_WRITE_UINT32(CYGARC_REG_CCR, __tmp);    \
-    CYG_MACRO_END
+#define HAL_UCACHE_ENABLE() cyg_hal_cache_enable()
 
 // Disable the cache
-#define HAL_UCACHE_DISABLE()                    \
-    CYG_MACRO_START                             \
-    register cyg_uint32 __tmp;                  \
-    HAL_READ_UINT32(CYGARC_REG_CCR, __tmp);     \
-    __tmp &= ~CYGARC_REG_CCR_CE;                \
-    HAL_WRITE_UINT32(CYGARC_REG_CCR, __tmp);    \
-    CYG_MACRO_END
+#define HAL_UCACHE_DISABLE() cyg_hal_cache_disable()
 
 // Invalidate the entire cache
-// Note: The CF bit does not cause any data to be written back before
-// invalidation of the cache.
-#define HAL_UCACHE_INVALIDATE_ALL()             \
-    CYG_MACRO_START                             \
-    register cyg_uint32 __tmp;                  \
-    HAL_READ_UINT32(CYGARC_REG_CCR, __tmp);     \
-    __tmp |= CYGARC_REG_CCR_CF;                 \
-    HAL_WRITE_UINT32(CYGARC_REG_CCR, __tmp);    \
-    CYG_MACRO_END
+#define HAL_UCACHE_INVALIDATE_ALL() cyg_hal_cache_invalidate_all()
 
 // Synchronize the contents of the cache with memory.
-#define HAL_UCACHE_SYNC()                                                   \
-    CYG_MACRO_START                                                         \
-    register cyg_uint32* __p;                                               \
-    register cyg_uint32* __top = (cyg_uint32*)CYGARC_REG_CACHE_ADDRESS_TOP; \
-    for (__p = (cyg_uint32*)CYGARC_REG_CACHE_ADDRESS_BASE;                  \
-         __p < __top;                                                       \
-         __p += CYGARC_REG_CACHE_ADDRESS_STEP/sizeof(cyg_uint32))           \
-        *__p = CYGARC_REG_CACHE_ADDRESS_FLUSH;                              \
-    CYG_MACRO_END
+#define HAL_UCACHE_SYNC() cyg_hal_cache_sync()
 
-// Query the state of the cache
+// Query the state of the cache (does not affect the caching)
 #define HAL_UCACHE_IS_ENABLED(_state_)          \
     CYG_MACRO_START                             \
     HAL_READ_UINT32(CYGARC_REG_CCR, (_state_)); \
@@ -131,15 +113,7 @@
 //#define HAL_UCACHE_BURST_SIZE(_size_)
 
 // Set the cache write mode
-#define HAL_UCACHE_WRITE_MODE( _mode_ )         \
-    CYG_MACRO_START                             \
-    register cyg_uint32 __tmp;                  \
-    HAL_READ_UINT32(CYGARC_REG_CCR, __tmp);     \
-    __tmp &= ~CYGARC_REG_CCR_CB;                \
-    if (HAL_UCACHE_WRITEBACK_MODE == (_mode_))  \
-        __tmp |= CYGARC_REG_CCR_CB;             \
-    HAL_WRITE_UINT32(CYGARC_REG_CCR, __tmp);    \
-    CYG_MACRO_END        
+#define HAL_UCACHE_WRITE_MODE( _mode_ ) cyg_hal_cache_write_mode(_mode_)
 
 #define HAL_UCACHE_WRITETHRU_MODE       0
 #define HAL_UCACHE_WRITEBACK_MODE       1
--- a/packages/hal/sh/arch/current/include/hal_intr.h
+++ b/packages/hal/sh/arch/current/include/hal_intr.h
@@ -448,7 +448,6 @@ externC cyg_uint8 cyg_hal_ILVL_table[];
     }                                                                    \
     CYG_MACRO_END
 
-
 #define HAL_INTERRUPT_MASK( _vector_ )                                    \
     CYG_MACRO_START                                                       \
     switch( (_vector_) ) {                                                \
@@ -491,10 +490,12 @@ externC cyg_uint8 cyg_hal_ILVL_table[];
     }                                                                     \
     CYG_MACRO_END
 
+
 #define HAL_INTERRUPT_ACKNOWLEDGE( _vector_ )
 
 #define HAL_INTERRUPT_CONFIGURE( _vector_, _level_, _up_ )
 
+
 //--------------------------------------------------------------------------
 // Clock control
 
--- a/packages/hal/sh/arch/current/src/hal_mk_defs.c
+++ b/packages/hal/sh/arch/current/src/hal_mk_defs.c
@@ -47,6 +47,7 @@
 
 #include <cyg/hal/hal_arch.h>           // HAL header
 #include <cyg/hal/hal_intr.h>           // HAL header
+#include <cyg/hal/hal_cache.h>          // HAL header
 #ifdef CYGPKG_KERNEL
 # include <pkgconf/kernel.h>
 # include <cyg/kernel/instrmnt.h>
@@ -103,6 +104,12 @@ main(void)
     DEFINE(CYGNUM_HAL_VSR_COUNT, CYGNUM_HAL_VSR_COUNT);
     DEFINE(CYGNUM_HAL_VSR_EXCEPTION_COUNT, CYGNUM_HAL_VSR_EXCEPTION_COUNT);
 
+    // Caching details
+    DEFINE(CYGARC_REG_CACHE_ADDRESS_FLUSH, CYGARC_REG_CACHE_ADDRESS_FLUSH);
+    DEFINE(CYGARC_REG_CACHE_ADDRESS_BASE,CYGARC_REG_CACHE_ADDRESS_BASE);
+    DEFINE(CYGARC_REG_CACHE_ADDRESS_TOP,CYGARC_REG_CACHE_ADDRESS_TOP);
+    DEFINE(CYGARC_REG_CACHE_ADDRESS_STEP,CYGARC_REG_CACHE_ADDRESS_STEP);
+
     // Variant definitions - want these to be included instead.
 }
 
--- a/packages/hal/sh/arch/current/src/vectors.S
+++ b/packages/hal/sh/arch/current/src/vectors.S
@@ -39,7 +39,8 @@
 ##               vectors. It also contains the first level default VSRs
 ##               that save and restore state for both exceptions and
 ##               interrupts.
-##
+## Notes:        The SH architecture files are still more SH3 specific than
+##               architecture neutral, hence the sub-variant configury.
 ######DESCRIPTIONEND####
 ##
 ##==========================================================================
@@ -494,6 +495,7 @@ 9:
 1:      
 #endif        
 
+
 #if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR)
         mov      #3,r7
 #endif
@@ -885,6 +887,121 @@ restore_state:
 #endif
 
 #---------------------------------------------------------------------------
+# Cache operations
+# These need to be written in assembly to ensure they do not rely on data
+# in cachable space (i.e., code must use registers exclusively, not the stack).
+
+# This macro must be used at the top of each cache function. It ensures
+# that the code gets executed from a shadow region where caching is disabled
+# (0xA0000000).
+        .macro GOTO_NONCACHED_SHADOW
+        mova    10f,r0
+        mov.l   $MASK,r1
+        and     r1,r0
+        mov.l   $BASE,r1
+        or      r1,r0
+        jmp     @r0
+         nop
+        .align  2
+10:
+        .endm
+
+        .globl _cyg_hal_cache_enable
+_cyg_hal_cache_enable:
+        GOTO_NONCACHED_SHADOW
+        mov     #CYGARC_REG_CCR,r1
+        mov.l   @r1,r0
+        or      #CYGARC_REG_CCR_CE,r0
+        mov.l   r0,@r1
+        nop
+        rts
+         nop
+
+        .globl _cyg_hal_cache_disable
+_cyg_hal_cache_disable:
+        GOTO_NONCACHED_SHADOW
+        mov     #CYGARC_REG_CCR,r1
+        mov.l   @r1,r0
+        mov     #CYGARC_REG_CCR_CE,r2
+        not     r2,r2
+        and     r2,r0
+        mov.l   r0,@r1
+        nop
+        rts
+         nop
+        
+        .globl _cyg_hal_cache_invalidate_all
+_cyg_hal_cache_invalidate_all:
+        GOTO_NONCACHED_SHADOW
+        mov     #CYGARC_REG_CCR,r1
+        mov.l   @r1,r0
+        or      #CYGARC_REG_CCR_CF,r0
+        mov.l   r0,@r1
+        nop                             ! Nothing in the docs suggest we need
+        nop                             ! nops here, but without them, the
+        nop                             ! CPU crashes.
+        rts
+         nop
+
+        .globl _cyg_hal_cache_sync
+_cyg_hal_cache_sync:
+        GOTO_NONCACHED_SHADOW
+        mov.l   $CYGARC_REG_CACHE_ADDRESS_FLUSH,r0
+        mov.l   $CYGARC_REG_CACHE_ADDRESS_BASE,r1
+        mov.l   $CYGARC_REG_CACHE_ADDRESS_TOP,r2
+        mov.l   $CYGARC_REG_CACHE_ADDRESS_STEP,r3
+1:      cmp/hi  r1,r2
+        bf      2f
+        mov.l   r0,@r1
+        bra     1b        
+         add     r3,r1                  ! delay slot!
+2:      nop
+        rts
+         nop
+
+        .globl _cyg_hal_cache_write_mode
+_cyg_hal_cache_write_mode:
+        GOTO_NONCACHED_SHADOW
+        # Mode argument in r4. Compute the WT and CB states from this
+        mov     r4,r0
+        and     #1,r0
+        shll    r0                      ! shift to WT position
+        mov     r0,r1                   ! duplicate at CB position
+        shll    r1
+        or      r1,r0
+        xor     #CYGARC_REG_CCR_WT,r0   ! WT must be 0 for write-back
+        # Read current state and mask out the two caching mode bits
+        mov     #CYGARC_REG_CCR,r1
+        mov.l   @r1,r3
+        mov     #CYGARC_REG_CCR_CB|CYGARC_REG_CCR_WT,r2
+        not     r2,r2
+        and     r2,r3
+        # Or in the new settings and restore to CCR
+        or      r0,r3
+        mov.l   r3,@r1
+        nop
+        rts
+         nop
+        
+
+
+        .align  2
+$CYGARC_REG_CACHE_ADDRESS_FLUSH:
+        .long   CYGARC_REG_CACHE_ADDRESS_FLUSH
+$CYGARC_REG_CACHE_ADDRESS_BASE:
+        .long   CYGARC_REG_CACHE_ADDRESS_BASE
+$CYGARC_REG_CACHE_ADDRESS_TOP:
+        .long   CYGARC_REG_CACHE_ADDRESS_TOP
+$CYGARC_REG_CACHE_ADDRESS_STEP:
+        .long   CYGARC_REG_CACHE_ADDRESS_STEP
+
+
+$MASK:
+        .long   0x1fffffff              ! mask off top 3 bits
+$BASE:
+        .long   0xa0000000              ! base of non-cachable memory
+        
+#---------------------------------------------------------------------------
 # Interrupt vector tables.
 # These tables contain the isr, data and object pointers used to deliver
 # interrupts to user code.
--- a/packages/io/serial/current/ChangeLog
+++ b/packages/io/serial/current/ChangeLog
@@ -1,3 +1,7 @@
+2000-04-17  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* src/PKGconf.mak: remove; it's obsolete.
+
 2000-04-13  Gary Thomas  <gthomas@redhat.com>
 
 	* src/common/serial.c (serial_write): Make safer - only call
--- a/packages/io/wallclock/current/ChangeLog
+++ b/packages/io/wallclock/current/ChangeLog
@@ -1,3 +1,8 @@
+2000-04-19  Jesper Skov  <jskov@cygnus.co.uk>
+
+	* src/wallclock.cxx: Construct after kernel RTC since the
+	emulation implementation may have to use the RTC.
+
 2000-04-13  Jesper Skov  <jskov@redhat.com>
 
 	* tests/wallclock.cxx: Use TEST_NA if N/A.
--- a/packages/io/wallclock/current/src/wallclock.cxx
+++ b/packages/io/wallclock/current/src/wallclock.cxx
@@ -72,7 +72,7 @@
 //-----------------------------------------------------------------------------
 // Local static variables
 
-static Cyg_WallClock wallclock_instance CYG_INIT_PRIORITY( CLOCK );
+static Cyg_WallClock wallclock_instance CYGBLD_ATTRIB_INIT_AFTER( CYG_INIT_CLOCK );
 
 #ifndef CYGSEM_WALLCLOCK_SET_GET_MODE
 static cyg_uint32 epoch_ticks;
--- a/packages/kernel/current/ChangeLog
+++ b/packages/kernel/current/ChangeLog
@@ -1,3 +1,17 @@
+2000-04-26  Jesper Skov  <jskov@redhat.com>
+
+	* tests/kcache1.c: Also to flush testing with unified caches.
+
+2000-04-25  Jesper Skov  <jskov@redhat.com>
+
+	* tests/kcache1.c: Fixed cache check to also look for unified
+	caches.
+
+2000-04-12  Gary Thomas  <gthomas@redhat.com>
+
+	* src/common/kapi.cxx (cyg_scheduler_safe_lock): 
+	* include/kapi.h: Add 'cyg_scheduler_safe_lock()' function.
+
 2000-04-12  Jesper Skov  <jskov@redhat.com>
 
 	* cdl/interrupts.cdl: 
--- a/packages/kernel/current/include/kapi.h
+++ b/packages/kernel/current/include/kapi.h
@@ -127,6 +127,11 @@ void cyg_scheduler_start(void) __attribu
 void cyg_scheduler_lock(void);
 
 void cyg_scheduler_unlock(void);
+
+/* Just like 'cyg_scheduler_lock()', but never take the lock higher than 1  */
+/* Thus this call is safe even if the scheduler is already locked and a     */
+/* subsequent call to 'cyg_scheduler_unlock()' will completely unlock.      */
+void cyg_scheduler_safe_lock(void);
     
 /*---------------------------------------------------------------------------*/
 /* Thread operations */
--- a/packages/kernel/current/src/common/kapi.cxx
+++ b/packages/kernel/current/src/common/kapi.cxx
@@ -115,6 +115,18 @@ externC void cyg_scheduler_lock(void)
                 "Scheduler overlocked" );
 }
 
+/* Lock the scheduler, but never more than level=1. */
+externC void cyg_scheduler_safe_lock(void)
+{
+    Cyg_Scheduler::lock();
+    cyg_ucount32 slock = Cyg_Scheduler::get_sched_lock();
+    if (slock > 1)
+        Cyg_Scheduler::unlock();
+    // get_sched_lock() is unsigned, see below "cyg_ucount32 lock"
+    CYG_ASSERT( (0xff000000 & (Cyg_Scheduler::get_sched_lock())) == 0,
+                "Scheduler overlocked" );
+}
+
 /* Unlock the scheduler. */
 externC void cyg_scheduler_unlock(void)
 {
--- a/packages/kernel/current/tests/clockcnv.cxx
+++ b/packages/kernel/current/tests/clockcnv.cxx
@@ -166,6 +166,8 @@ static void entry0( CYG_ADDRWORD data )
             if (cyg_test_is_simulator)
                 j += 30;                // test fewer values
                                    /* tr.b..m..k.. */
+
+
             for ( delay = j; delay < 1000000000000ll; delay *= 10 ) {
                 // get the converted result
                 cyg_uint64 result = Cyg_Clock::convert( delay, &cv );
--- a/packages/kernel/current/tests/kcache1.c
+++ b/packages/kernel/current/tests/kcache1.c
@@ -43,12 +43,13 @@
 
 #include <cyg/infra/testcase.h>
 
-#ifdef HAL_DCACHE_SIZE
+#include <cyg/hal/hal_cache.h>
+
+#if defined(HAL_DCACHE_SIZE) || defined(HAL_UCACHE_SIZE)
 #ifdef CYGVAR_KERNEL_COUNTERS_CLOCK
 #ifdef CYGFUN_KERNEL_API_C
 
 #include <cyg/infra/diag.h>
-#include <cyg/hal/hal_cache.h>
 #include <cyg/hal/hal_intr.h>
 
 // -------------------------------------------------------------------------
@@ -175,7 +176,8 @@ void time1II(void)
 static void time0DI(register cyg_uint32 stride)
 {
     register cyg_uint32 j,k;
-    cyg_tick_count_t count0, count1;
+    volatile cyg_tick_count_t count0;
+    cyg_tick_count_t count1;
     cyg_ucount32 t;
     register char c;
 
@@ -217,7 +219,7 @@ void time1DI(void)
 static void entry0( cyg_addrword_t data )
 {
     register CYG_INTERRUPT_STATE oldints;
-    
+
 #ifdef HAL_CACHE_UNIFIED
 
     HAL_DISABLE_INTERRUPTS(oldints);
@@ -236,6 +238,16 @@ static void entry0( cyg_addrword_t data 
     CYG_TEST_INFO("Cache on");
     time1();
 
+#ifdef HAL_DCACHE_INVALIDATE_ALL
+    HAL_DISABLE_INTERRUPTS(oldints);
+    HAL_DCACHE_PURGE_ALL();
+    HAL_UCACHE_INVALIDATE_ALL();
+    HAL_UCACHE_ENABLE();
+    HAL_RESTORE_INTERRUPTS(oldints);    
+    CYG_TEST_INFO("Cache on: invalidate Cache (expect bogus times)");
+    time1DI();
+#endif
+
 #else // HAL_CACHE_UNIFIED
 
     HAL_DISABLE_INTERRUPTS(oldints);
@@ -313,8 +325,7 @@ static void entry0( cyg_addrword_t data 
         CYG_TEST_PASS_FINISH("End of test");
  
     cyg_test_is_simulator = 1;
-#endif
-    
+#endif    
 #ifdef HAL_ICACHE_INVALIDATE_ALL
     HAL_DISABLE_INTERRUPTS(oldints);
     HAL_DCACHE_PURGE_ALL();