changeset 177:4c750ce71ae3

Merge from eCos master repository on 2001-08-10-19:22:57-BST
author jlarmour
date Fri, 10 Aug 2001 19:27:55 +0000
parents 3902ef905c9c
children aa8364213009
files host/tools/Utils/common/Subprocess.cpp host/tools/configtool/common/common/build.cxx host/tools/configtool/standalone/wxwin/CHANGES.txt host/tools/configtool/standalone/wxwin/TODO.txt host/tools/configtool/standalone/wxwin/admindlg.cpp host/tools/configtool/standalone/wxwin/configtool.h host/tools/configtool/standalone/wxwin/configtooldoc.cpp host/tools/configtool/standalone/wxwin/configtooldoc.h host/tools/configtool/standalone/wxwin/mainwin.cpp host/tools/configtool/standalone/wxwin/mainwin.h host/tools/configtool/standalone/wxwin/readme.html host/tools/configtool/standalone/wxwin/symbols.h packages/NEWS packages/compat/posix/current/ChangeLog packages/compat/posix/current/cdl/posix.cdl packages/compat/posix/current/include/limits.h packages/compat/posix/current/include/muttypes.h packages/compat/posix/current/include/signal.h packages/compat/posix/current/include/sigsetjmp.h packages/compat/posix/current/include/types.h packages/compat/posix/current/src/misc.cxx packages/compat/posix/current/src/mutex.cxx packages/compat/posix/current/src/pprivate.h packages/compat/posix/current/src/pthread.cxx packages/compat/posix/current/src/signal.cxx packages/compat/posix/current/tests/mutex3.c packages/compat/posix/current/tests/pthread1.c packages/compat/posix/current/tests/pthread2.c packages/compat/posix/current/tests/pthread3.c packages/compat/posix/current/tests/signal1.c packages/compat/posix/current/tests/sigsetjmp.c packages/compat/posix/current/tests/timer1.c packages/compat/posix/current/tests/tm_basic.cxx packages/devs/flash/amd/am29xxxxx/current/ChangeLog packages/devs/flash/amd/am29xxxxx/current/include/flash_am29xxxxx.inl packages/devs/flash/arm/iq80310/current/ChangeLog packages/devs/flash/arm/iq80310/current/src/flash.h packages/devs/flash/intel/28fxxx/current/ChangeLog packages/devs/flash/intel/28fxxx/current/cdl/flash_intel_28fxxx.cdl packages/devs/flash/intel/28fxxx/current/include/flash_28fxxx.inl packages/devs/flash/intel/28fxxx/current/include/flash_28fxxx_parts.inl packages/devs/flash/mn10300/stb/current/ChangeLog packages/devs/flash/mn10300/stb/current/src/mn10300_stb_flash.c packages/devs/usb/sa11x0/current/ChangeLog packages/devs/usb/sa11x0/current/src/usbs_sa11x0.c packages/hal/arm/iq80310/current/ChangeLog packages/hal/arm/iq80310/current/include/hal_platform_setup.h packages/hal/common/current/ChangeLog packages/hal/common/current/cdl/hal.cdl packages/hal/common/current/include/drv_api.h packages/hal/common/current/src/drv_api.c packages/hal/common/current/tests/vaargs.c packages/hal/mips/rm7000/ocelot/current/ChangeLog packages/hal/mips/rm7000/ocelot/current/cdl/hal_mips_rm7000_ocelot.cdl packages/hal/mips/rm7000/ocelot/current/include/plf_intr.h packages/hal/mips/rm7000/var/current/ChangeLog packages/hal/mips/rm7000/var/current/include/var_intr.h packages/hal/mn10300/stb/current/ChangeLog packages/hal/mn10300/stb/current/cdl/hal_mn10300_am33_stb.cdl packages/hal/mn10300/stb/current/include/pkgconf/mlt_mn10300_am33_stb_rom.h packages/hal/mn10300/stb/current/include/pkgconf/mlt_mn10300_am33_stb_rom.mlt packages/hal/mn10300/stb/current/include/pkgconf/mlt_mn10300_am33_stb_sram1.h packages/hal/mn10300/stb/current/include/pkgconf/mlt_mn10300_am33_stb_sram1.ldi packages/hal/mn10300/stb/current/include/pkgconf/mlt_mn10300_am33_stb_sram1.mlt packages/hal/mn10300/stb/current/include/plf_intr.h packages/hal/mn10300/stb/current/include/plf_io.h packages/hal/mn10300/stb/current/include/plf_stub.h packages/hal/mn10300/stb/current/misc/redboot_RAM.ecm packages/hal/mn10300/stb/current/misc/redboot_ROM.ecm packages/hal/mn10300/stb/current/misc/redboot_SRAM1.ecm packages/hal/mn10300/stb/current/src/plf_misc.c packages/hal/mn10300/stb/current/src/plf_stub.c packages/hal/mn10300/stb/current/src/ser_stb.c packages/hal/mn10300/stdeval1/current/ChangeLog packages/hal/mn10300/stdeval1/current/include/plf_io.h packages/hal/sh/cq7750/current/ChangeLog packages/hal/sh/cq7750/current/cdl/hal_sh_sh7750_cq7750.cdl packages/hal/sh/cq7750/current/misc/redboot_ROM.ecm packages/hal/sh/dreamcast/current/ChangeLog packages/hal/sh/dreamcast/current/cdl/hal_sh_sh7750_dreamcast.cdl packages/hal/sh/sh4/current/ChangeLog packages/hal/sh/sh4/current/include/mod_7750.h packages/infra/current/ChangeLog packages/infra/current/include/cyg_type.h packages/infra/current/src/diag.cxx packages/infra/current/src/tcdiag.cxx packages/io/eth/current/ChangeLog packages/io/eth/current/src/net/eth_drv.c packages/io/eth/current/src/stand_alone/eth_drv.c packages/io/flash/current/ChangeLog packages/io/flash/current/cdl/io_flash.cdl packages/io/flash/current/include/flash.h packages/io/flash/current/src/flash.c packages/io/usb/slave/current/ChangeLog packages/io/usb/slave/current/include/usbs.h packages/isoinfra/current/ChangeLog packages/isoinfra/current/cdl/isoinfra.cdl packages/isoinfra/current/include/sys/types.h packages/isoinfra/current/include/time.h packages/kernel/current/ChangeLog packages/kernel/current/cdl/instrument.cdl packages/kernel/current/cdl/kernel.cdl packages/kernel/current/cdl/scheduler.cdl packages/kernel/current/include/bitmap.hxx packages/kernel/current/include/instrmnt.h packages/kernel/current/include/intr.hxx packages/kernel/current/include/kapi.h packages/kernel/current/include/kapidata.h packages/kernel/current/include/mlqueue.hxx packages/kernel/current/include/mutex.hxx packages/kernel/current/include/sched.hxx packages/kernel/current/include/sched.inl packages/kernel/current/include/smp.hxx packages/kernel/current/include/test/stackmon.h packages/kernel/current/include/thread.inl packages/kernel/current/src/common/kapi.cxx packages/kernel/current/src/common/thread.cxx packages/kernel/current/src/instrmnt/meminst.cxx packages/kernel/current/src/intr/intr.cxx packages/kernel/current/src/sched/bitmap.cxx packages/kernel/current/src/sched/mlqueue.cxx packages/kernel/current/src/sched/sched.cxx packages/kernel/current/src/sync/mutex.cxx packages/kernel/current/tests/mutex2.cxx packages/kernel/current/tests/mutex3.cxx packages/kernel/current/tests/release.cxx packages/kernel/current/tests/smp.cxx packages/kernel/current/tests/sync3.cxx packages/kernel/current/tests/thread2.cxx packages/kernel/current/tests/tm_basic.cxx packages/language/c/libc/stdio/current/ChangeLog packages/language/c/libc/stdio/current/include/streambuf.inl packages/language/c/libc/stdio/current/src/common/stream.cxx packages/language/c/libc/stdio/current/src/output/vfnprintf.cxx packages/language/c/libc/string/current/ChangeLog packages/language/c/libc/string/current/src/memchr.cxx packages/language/c/libc/string/current/src/memcmp.cxx packages/language/c/libc/string/current/src/memmove.cxx packages/language/c/libc/string/current/src/strncat.cxx packages/language/c/libc/string/current/src/strncmp.cxx packages/language/c/libc/string/current/src/strncpy.cxx packages/language/c/libc/string/current/src/strxfrm.cxx packages/redboot/current/ChangeLog packages/redboot/current/cdl/redboot.cdl packages/redboot/current/src/flash.c packages/redboot/current/src/fs/disk.c packages/redboot/current/src/io.c packages/redboot/current/src/net/net_io.c packages/redboot/current/src/version.c
diffstat 149 files changed, 6407 insertions(+), 1763 deletions(-) [+]
line wrap: on
line diff
--- a/host/tools/Utils/common/Subprocess.cpp
+++ b/host/tools/Utils/common/Subprocess.cpp
@@ -259,6 +259,8 @@ void CSubprocess::ThreadFunc()
   
   DWORD dwAvail;
   
+  DWORD dwExitCode;
+
   while (!m_bKillThread && m_pfnContinue(m_pContinuationFuncParam) && ::PeekNamedPipe(m_hrPipe, NULL, 0, 0, &dwAvail, NULL)){
 //TRACE(_T("P%d\n"),dwAvail);
     if(dwAvail){
@@ -274,15 +276,23 @@ void CSubprocess::ThreadFunc()
       buf[dwRead]='\0';
       Output(String::CStrToUnicodeStr(buf));
       delete [] buf;
-    } else if(!ProcessAlive()){
-      TRACE(_T("m_bThreadTerminated=%d\n"),m_bThreadTerminated);
-      break;
-    } else {
+    }
+    else if (!ProcessAlive())
+    {
+        TRACE(_T("m_bThreadTerminated=%d\n"),m_bThreadTerminated);
+        break;
+    }
+    // Fix for hanging in an endless loop under Windows ME, by Bill Diehls <billabloke@yahoo.com>
+    else if (::GetExitCodeProcess(m_hProcess, &dwExitCode) && dwExitCode!=STILL_ACTIVE) 
+    {
+		break;
+    }
+    else
+    {
       CeCosThreadUtils::Sleep(250);
     }
   }
 
-  DWORD dwExitCode;
   ::GetExitCodeProcess(m_hProcess, &dwExitCode);
   m_nExitCode=dwExitCode;
   
--- a/host/tools/configtool/common/common/build.cxx
+++ b/host/tools/configtool/common/common/build.cxx
@@ -74,14 +74,18 @@
 
 std::string makefile_header = "# eCos makefile\n\n# This is a generated file - do not edit\n\n";
 
+// This code seems to crash Tcl under Windows ME and Linux, so
+// disable for now. What should the criterion be? TCL version?
+#define SET_STDOUT_TO_NULL 0
+
 bool eval_tcl_command (const std::string command) {
 	Tcl_Interp * interp = Tcl_CreateInterp ();
-#ifdef _MSC_VER
+#if SET_STDOUT_TO_NULL
 	Tcl_Channel outchan = Tcl_OpenFileChannel (interp, "nul", "a+", 777);
 	Tcl_SetStdChannel (outchan, TCL_STDOUT); // direct standard output to the null device
 #endif
 	int nStatus = Tcl_Eval (interp, (char *) command.c_str ());
-#ifdef _MSC_VER
+#if SET_STDOUT_TO_NULL
 	Tcl_SetStdChannel (NULL, TCL_STDOUT);
 	Tcl_UnregisterChannel (interp, outchan);
 #endif
--- a/host/tools/configtool/standalone/wxwin/CHANGES.txt
+++ b/host/tools/configtool/standalone/wxwin/CHANGES.txt
@@ -1,6 +1,14 @@
 Release History for eCos Configuration Tool 2
 =============================================
 
+*** Version 2.05, August 10th 2001
+
+- Fixed a bug in the administration dialog that only looked at the filename of the
+  .epk to add and not the path.
+
+- Added "Tools | Generate Build Tree" menu so the build tree can be regenerated
+  without having to change values in the configuration and save the file.
+
 
 *** Version 2.04, July 16th 2001
 
@@ -10,6 +18,9 @@ Release History for eCos Configuration T
   flashing DOS box under Windows. Makefiles now define HOST=CYGWIN
   so that makefiles can use mkdir the right way under Windows.
 
+- Installation program will install run-time DLLs if newer than those
+  on the system.
+
 
 *** Version 2.03, July 9nd 2001
 
--- a/host/tools/configtool/standalone/wxwin/TODO.txt
+++ b/host/tools/configtool/standalone/wxwin/TODO.txt
@@ -15,3 +15,19 @@ To-Do List for Configuration Tool 2.x
 - Switching to Rich Edit control for Output Window causes scroll problems
   on Windows 98.
 
+- Added menu option Build | Generate Build Tree to simply recreate the
+  build tree, since otherwise one sometimes has to alter a value to convince the
+  tool to save and create the tree.
+
+- Resolve target makefile problems. A user:-
+
+  "It looks like the Configuration Tool 2.0 builds the library by replacing
+  lib members, not recreating the whole library. Example situation: I want to
+  remove POSIX pthread support and write my enhanced pthread_create() etc..
+  If I just uncheck POSIX thread support and rebuild, the pthread functions
+  remain in libtarget.a, resulting to redefinition error in my application
+  link phase. Is this intended for some obvious reason?
+  Now I must save to another xxx.ecc and build all."
+
+  Bart says: "The whole makefile generation system needs a major overhaul."
+
--- a/host/tools/configtool/standalone/wxwin/admindlg.cpp
+++ b/host/tools/configtool/standalone/wxwin/admindlg.cpp
@@ -30,7 +30,7 @@
 // Author(s):   julians
 // Contact(s):  julians
 // Date:        2000/09/28
-// Version:     $Id: admindlg.cpp,v 1.4 2001/03/23 13:38:04 julians Exp $
+// Version:     $Id: admindlg.cpp,v 1.5 2001/08/10 14:58:21 julians Exp $
 // Purpose:
 // Description: Implementation file for ecAdminDialog
 // Requires:
@@ -223,7 +223,7 @@ void ecAdminDialog::OnAdd(wxCommandEvent
         bool bRepositoryChanged = FALSE;
         //POSITION posPathName = dlg.GetStartPosition ();
         wxArrayString filenames;
-        dlg.GetFilenames(filenames);
+        dlg.GetPaths(filenames);
         size_t i;
         for (i = (size_t) 0; i < filenames.GetCount(); i++)
         {
--- a/host/tools/configtool/standalone/wxwin/configtool.h
+++ b/host/tools/configtool/standalone/wxwin/configtool.h
@@ -30,7 +30,7 @@
 // Author(s):   julians
 // Contact(s):  julians
 // Date:        2000/08/24
-// Version:     $Id: configtool.h,v 1.24 2001/07/13 15:17:43 julians Exp $
+// Version:     $Id: configtool.h,v 1.25 2001/08/10 14:58:21 julians Exp $
 // Purpose:
 // Description: main header file for the ConfigTool application
 // Requires:
@@ -302,6 +302,7 @@ protected:
 #define ecID_BUILD_REPOSITORY           2185
 #define ecID_BUILD_TEMPLATES            2186
 #define ecID_BUILD_PACKAGES             2187
+#define ecID_GENERATE_BUILD_TREE        2188
 
 // Tools menu
 #define ecID_PATHS                      2200
--- a/host/tools/configtool/standalone/wxwin/configtooldoc.cpp
+++ b/host/tools/configtool/standalone/wxwin/configtooldoc.cpp
@@ -30,7 +30,7 @@
 // Author(s):   julians
 // Contact(s):  julians
 // Date:        2000/10/05
-// Version:     $Id: configtooldoc.cpp,v 1.35 2001/07/05 10:42:16 julians Exp $
+// Version:     $Id: configtooldoc.cpp,v 1.36 2001/08/10 14:58:21 julians Exp $
 // Purpose:
 // Description: Implementation file for the ecConfigToolDoc class
 // Requires:
@@ -326,6 +326,58 @@ bool ecConfigToolDoc::OnSaveDocument(con
     return rc;
 }
 
+// Can we generate the build tree yet?
+bool ecConfigToolDoc::CanGenerateBuildTree()
+{
+    if (m_strBuildTree.IsEmpty() || m_strInstallTree.IsEmpty() )
+        return FALSE;
+
+    int nCount=0;
+    if (GetCdlConfig ())
+    {
+        // calculate the number of conflicts
+        int nCount = GetCdlConfig ()->get_all_conflicts ().size ();
+
+        if (nCount > 0)
+            return FALSE;
+    }
+    else
+        return FALSE;
+
+    return TRUE;
+}
+
+// A standalone method for generating a build tree without saving first
+bool ecConfigToolDoc::GenerateBuildTree()
+{
+    wxBusyCursor wait;
+    if (CanGenerateBuildTree())
+    {
+        ecFileName buildFilename(m_strBuildTree);
+        ecFileName installFilename(m_strInstallTree);
+        
+        if (!buildFilename.CreateDirectory() || !installFilename.CreateDirectory())
+        {
+            wxString msg;
+            msg.Printf(_("Failed to create build tree"));
+            
+            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION);
+            return FALSE;
+        }
+        else if (GenerateHeaders() && CopyMLTFiles())
+        {
+            // in each case errors already emitted
+            // copy new MLT files to the build tree as necessary
+            bool rc = generate_build_tree (GetCdlConfig(), ecUtils::UnicodeToStdStr(m_strBuildTree), ecUtils::UnicodeToStdStr(m_strInstallTree));
+            rc = TRUE;
+        }
+
+    }
+    else
+        return FALSE;
+    return TRUE;
+}
+
 bool ecConfigToolDoc::OnOpenDocument(const wxString& filename)
 {
     wxGetApp().GetSettings().m_lastFilename = filename;
--- a/host/tools/configtool/standalone/wxwin/configtooldoc.h
+++ b/host/tools/configtool/standalone/wxwin/configtooldoc.h
@@ -30,7 +30,7 @@
 // Author(s):   julians
 // Contact(s):  julians
 // Date:        2000/10/05
-// Version:     $Id: configtooldoc.h,v 1.14 2001/06/29 13:48:22 julians Exp $
+// Version:     $Id: configtooldoc.h,v 1.15 2001/08/10 14:58:21 julians Exp $
 // Purpose:
 // Description: Header file for ecConfigToolDoc
 // Requires:
@@ -158,6 +158,11 @@ public:
     bool ImportFile();
     void RunTests();
 
+    // A standalone method for generating a build tree without saving first
+    bool GenerateBuildTree();
+    // Can we generate the build tree yet?
+    bool CanGenerateBuildTree() ;
+
     void SelectTemplate (const wxString& newTemplate, const wxString& newTemplateVersion);
     void SelectHardware (const wxString& newTemplate);
     void SelectPackages ();
--- a/host/tools/configtool/standalone/wxwin/mainwin.cpp
+++ b/host/tools/configtool/standalone/wxwin/mainwin.cpp
@@ -30,7 +30,7 @@
 // Author(s):   julians
 // Contact(s):  julians
 // Date:        2000/08/24
-// Version:     $Id: mainwin.cpp,v 1.47 2001/07/09 14:21:32 julians Exp $
+// Version:     $Id: mainwin.cpp,v 1.48 2001/08/10 14:58:21 julians Exp $
 // Purpose:
 // Description: Implementation file for the ConfigTool main window
 // Requires:
@@ -165,6 +165,7 @@ BEGIN_EVENT_TABLE(ecMainFrame, wxDocPare
     EVT_MENU(ecID_CLEAN, ecMainFrame::OnClean)
     EVT_MENU(ecID_SHELL, ecMainFrame::OnShell)
     EVT_MENU(ecID_INDEX_DOCS, ecMainFrame::OnIndexDocs)
+    EVT_MENU(ecID_GENERATE_BUILD_TREE, ecMainFrame::OnGenerateBuildTree)
 
     EVT_UPDATE_UI(ecID_PLATFORMS, ecMainFrame::OnUpdatePlatforms)
     EVT_UPDATE_UI(ecID_BUILD_OPTIONS, ecMainFrame::OnUpdateBuildOptions)
@@ -205,6 +206,7 @@ BEGIN_EVENT_TABLE(ecMainFrame, wxDocPare
     EVT_UPDATE_UI(ecID_STOP_BUILD, ecMainFrame::OnUpdateStopBuild)
     EVT_UPDATE_UI(ecID_BUILD_LIBRARY, ecMainFrame::OnUpdateBuildLibrary)
     EVT_UPDATE_UI(ecID_BUILD_TESTS, ecMainFrame::OnUpdateBuildTests)
+    EVT_UPDATE_UI(ecID_GENERATE_BUILD_TREE, ecMainFrame::OnUpdateGenerateBuildTree)
 
     EVT_UPDATE_UI(ecID_SHELL, ecMainFrame::OnUpdateShell)
 
@@ -328,6 +330,8 @@ ecMainFrame::ecMainFrame(wxDocManager *m
     buildMenu->Append(ecID_CLEAN, _("&Clean"), _("Deletes intermediate and output files"));
     buildMenu->Append(ecID_STOP_BUILD, _("&Stop"), _("Stops the build"));
     buildMenu->AppendSeparator();
+    buildMenu->Append(ecID_GENERATE_BUILD_TREE, _("&Generate Build Tree"), _("Explicitly recreates the build tree"));
+    buildMenu->AppendSeparator();
     buildMenu->Append(ecID_BUILD_OPTIONS, _("&Options..."), _("Changes build options"));
     buildMenu->Append(ecID_BUILD_REPOSITORY, _("&Repository..."), _("Selects repository"));
     buildMenu->Append(ecID_BUILD_TEMPLATES, _("&Templates..."), _("Selects the package templates"));
@@ -1513,6 +1517,9 @@ void ecMainFrame::OnWebUitron(wxCommandE
 
 void ecMainFrame::OnBuildLibrary(wxCommandEvent& event)
 {
+    // TODO: possibly add wxT("clean build") to ensure library is
+    // cleanly built. No, can't do that because it would clean
+    // out any user code too :-(
     wxGetApp().Build();
 }
 
@@ -1669,3 +1676,19 @@ void ecMainFrame::OnUpdateIndexDocs(wxUp
 {
     event.Enable( wxGetApp().GetConfigToolDoc() != NULL );
 }
+
+void ecMainFrame::OnGenerateBuildTree(wxCommandEvent& event)
+{
+    if (wxGetApp().GetConfigToolDoc() && wxGetApp().GetConfigToolDoc()->CanGenerateBuildTree())
+    {
+        if (!wxGetApp().GetConfigToolDoc()->GenerateBuildTree())
+        {
+            // Error probably already reported
+        }
+    }
+}
+
+void ecMainFrame::OnUpdateGenerateBuildTree(wxUpdateUIEvent& event)
+{
+    event.Enable( (wxGetApp().GetConfigToolDoc() != NULL) && wxGetApp().GetConfigToolDoc()->CanGenerateBuildTree());
+}
--- a/host/tools/configtool/standalone/wxwin/mainwin.h
+++ b/host/tools/configtool/standalone/wxwin/mainwin.h
@@ -30,7 +30,7 @@
 // Author(s):   julians
 // Contact(s):  julians
 // Date:        2000/08/24
-// Version:     $Id: mainwin.h,v 1.18 2001/07/13 15:17:43 julians Exp $
+// Version:     $Id: mainwin.h,v 1.19 2001/08/10 14:58:21 julians Exp $
 // Purpose:
 // Description: Header file for the ConfigTool main window
 // Requires:
@@ -112,6 +112,7 @@ public:
     void OnStopBuild(wxCommandEvent& event);
     void OnClean(wxCommandEvent& event);
     void OnShell(wxCommandEvent& event);
+    void OnGenerateBuildTree(wxCommandEvent& event);
 
     void OnNewRegion(wxCommandEvent& event);
     void OnNewSection(wxCommandEvent& event);
@@ -148,6 +149,7 @@ public:
     void OnUpdateFind(wxUpdateUIEvent& event);
     void OnUpdateFindNext(wxUpdateUIEvent& event);
     void OnUpdateIndexDocs(wxUpdateUIEvent& event);
+    void OnUpdateGenerateBuildTree(wxUpdateUIEvent& event);
 
     void OnUpdateNewRegion(wxUpdateUIEvent& event);
     void OnUpdateNewSection(wxUpdateUIEvent& event);
deleted file mode 100644
--- a/host/tools/configtool/standalone/wxwin/readme.html
+++ /dev/null
@@ -1,416 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
-<HTML>
-<HEAD>
-	<TITLE>eCos Configuration Tool Version 2</TITLE>
-	<META NAME="GENERATOR" CONTENT="StarOffice/5.1 (Win32)">
-	<META NAME="CREATED" CONTENT="20010523;11445847">
-	<META NAME="CHANGEDBY" CONTENT="Julian Smart">
-	<META NAME="CHANGED" CONTENT="20010531;13251797">
-	<!-- StartFragment -->
-</HEAD>
-<BODY>
-<H1>eCos Configuration Tool Version 2</H1>
-<HR SIZE=3 NOSHADE>
-<P>This page describes how to run and compile the new, portable
-version of the Configuration Tool.</P>
-<H2>Contents</H2>
-<OL>
-	<LI><P>Introduction and where to get the Configuration Tool</P>
-	<LI><P>What's in this release?</P>
-	<LI><P>Installing the Configuration Tool</P>
-	<LI><P>Running the Configuration Tool</P>
-	<LI><P>Frequently Asked Questions</P>
-	<LI><P>Building the Configuration Tool under Linux</P>
-	<LI><P>Building the Configuration Tool under Windows</P>
-</OL>
-<H2>Introduction</H2>
-<P>Welcome to the eCos Configuration Tool, a graphical tool to help a
-user configure and build a custom version of the eCos operating
-system.</P>
-<P>This is a cross-platform version built using the wxWindows
-toolkit. The tool uses the GTK+ widget set on Linux, and the WIN32
-API on Windows 9x, Windows NT and Windows 2000. It is similar to the
-MFC, Windows-only version but at present lacks a few of its features,
-such as the Memory Layout Tool and the ability to run tests from
-within the tool.</P>
-<P>Please note that this is alpha-level code. However, all feedback
-to the eCos team is appreciated, via <a href="mailto:ecos-discuss@sources.redhat.com">ecos-discuss@sources.redhat.com</a>
-or the bug reporting form at
-<A HREF="http://sources.redhat.com/ecos/problemreport.html">http://sources.redhat.com/ecos/problemreport.html</A>.</P>
-<P>The source for the Configuration Tool is available from anonymous
-CVS.</P>
-<P>Binary packages are also available (see instructions below).</P>
-<H2>What's in this release?</H2>
-<P>This version allows you to edit, load, save and build eCos
-configurations much as the original Windows Configuration Tool.
-However the following features are missing with respect to the
-original tool:</P>
-<OL>
-	<LI><P>Memory Layout Tool</P>
-	<LI><P>Administration functionality (initial code present but
-	untested)</P>
-	<LI><P>Gauge indicating time left to build library and tests</P>
-</OL>
-<P>The following features are present in the new tool but not in the
-original tool:</P>
-<OL>
-	<LI><P>Repository Information dialog (available from the Help menu)</P>
-	<LI><P>Most dialogs are resizeable</P>
-</OL>
-<P>Documentation works a little differently. Instead of using a
-precompiled HTML Help file, this version compiles a documentation
-index on the fly for use with its own internal HTML help viewer. The
-cached indexes are placed in the .eCosDocs directory under the user's
-home directory (Linux) or in the installed repository (Windows). The
-internal viewer cannot cope with all of the eCos and GNUPro
-documentation, so for these occasions please use an external browser
-(see the Settings dialog).</P>
-<P>The documentation for the Configuration Tool is supplied in its
-install directory as HTML only, and is a modified version of the eCos
-User's Guide. Invoke the tool help from the &quot;Help|Configuration
-Tool Help&quot; menu item, or from the internal help viewer's index,
-under &quot;Linux Configuration Tool Guide&quot;.</P>
-<H4>Known bugs:</H4>
-<P>The documentation index only lists the packages in the
-configuration active when the documentation was indexed (normally
-when the repository is first seen by the Configuration Tool).</P>
-<H2>Installing the Configuration Tool</H2>
-<P>The Configuration Tool can be used with existing eCos
-installations and CVS source hierarchies. You can get the binaries
-from <A HREF="ftp://sources.redhat.com/pub/ecos/ct2/">ftp://sources.redhat.com/pub/ecos/ct2/</A>.</P>
-<P>See also mirror sites at:</P>
-<P><A HREF="http://sources.redhat.com/ecos/mirror.html">http://sources.redhat.com/ecos/mirror.html</A><BR><A HREF="http://sources.redhat.com/mirrors.html">http://sources.redhat.com/mirrors.html</A></P>
-<P>Please try to use a mirror site close to you, as it will be
-faster.</P>
-<H3>Under Linux:</H3>
-<P>Download <A HREF="ftp://sources.redhat.com/pub/ecos/ct2/configtool-2.02-i386.tar.gz">configtool-2.02-i386.tar.gz</A> (3.1Mb) or <A HREF="ftp://sources.redhat.com/pub/ecos/ct2/configtool-2.02-i386.tar.bz2">configtool-2.02-i386.tar.bz2</A> (2.8Mb).</P>
-<P>Unarchive the tar file into a suitable directory and add the
-directory to your path. You do not have to install it as root. For
-example:</P>
-<P>% mkdir -p
-<TT>
-/opt/ecos/configtool/bin<BR>% cd /opt/ecos/configtool/bin<BR>% tar
-xvfz /cdrom/configtool.tgz<BR>% export
-PATH=/opt/ecos/configtool/bin:$PATH</TT></P>
-<P>The following files will be extracted to the installation
-directory:</P>
-<P><TT>configtool, ecoslogo.png,
-rhlogo.png, about.htm, README.txt, license.txt, ecosplatforms.tar.gz,
-manual/</TT></P>
-<P>Optionally, untar the contents of ecosplatforms.tar.gz into your
-home directory, where it will create a directory called
-.eCosPlatforms. The information in these files isn't yet used by the
-Configuration Tool, but will keep the tool from generating some
-warnings.</P>
-<P>The executable is statically linked to the wxWindows library, but
-does require the GTK+ 1.2, GDK 1.2 and TCL 8.x libraries to be
-installed.</P>
-<H3>Under Windows:</H3>
-<P>Download <A HREF="ftp://sources.redhat.com/pub/ecos/ct2/configtool-2.02-setup.exe">configtool-2.02-setup.exe</A>.</P>
-<P>Run the installer provided, preferably having installed eCos for
-Windows on your PC previously so the tool can pick up the relevant
-registry information added by the eCos installer. A new eCos
-Configuration Tool group will be added to your Start menu and a
-shortcut to the Configuration Tool will appear on your desktop.</P>
-<H2>Running the Configuration Tool</H2>
-<P>Run the configtool executable and (on Linux) ignore any initial
-console messages, which may be suppressed by unarchiving
-ecosplatforms.tar.gz as per the installation instructions above.</P>
-<P>You can invoke the tool with zero, one, or two parameters. The two
-parameters can be the location of the repository and/or the location
-of a save file (extension .ecc). If no parameters are passed, the
-tool will look in the current directory for a save file and also (on
-Linux) in the /opt/ecos directory for a suitable repository. Failing
-that, the tool will use the last loaded repository or ask the user
-for a suitable location.</P>
-<P>For detailed information about the Configuration Tool, please
-refer to the HTML manual which may be invoked from the Help menu or
-by clicking on the &quot;Linux Configuration Tool Guide&quot; in the
-internal help system's contents. This is similar to but different
-from &quot;The eCos Configuration Tool&quot; section in the eCos User
-Guide, which refers to the original Windows version of the
-configuration tool (as opposed to the new cross-platform Linux and
-Windows version).</P>
-<H2>Frequently Asked Questions</H2>
-<P><B>Q: On Linux, invoking HTML documentation for a configuration
-item doesn't seem to work.</B></P>
-<P>A: You need to have a .mailcap entry similar to the following:</P>
-<P><TT>text/html; netscape
--no-about-splash %s</TT>
-</P>
-<P>and in .mime.types:</P>
-<P><TT>type=text/html \<BR>desc=&quot;HTML
-document&quot; \<BR>exts=&quot;htm,html&quot;</TT></P>
-<P>Also, be aware that the browser can sometimes end up behind the
-configuration tool so it may have run even if you think it didn't.</P>
-<P><B>Q: On Linux, right-clicking in the configuration pane and
-choosing 'What's This?' causes an information window to pop up and
-then quickly disappear.</B></P>
-<P>A: If the window manager options are set to raise a window when it
-gains the focus, the information window can get sent behind the
-application window when the popup menu loses focus. Either adjust
-your window manager settings, or use an alternate way of invoking
-help for the item: click on the arrow/question mark toolbar button,
-then on the item you are interested in.</P>
-<P><B>Q: The internal HTML help viewer doesn't display HTML
-correctly.</B></P>
-<P>A: The internal HTML help viewer cannot display some of the more
-complex HTML correctly, such as the GNUPro reference. We hope to
-provide the documentation in a suitable form in future, but for now,
-please use an external browser to view this documentation. You can
-use the Settings dialog, Viewers tab, to choose to view using an
-external browser.</P>
-<P><B>Q: Why does the Configuration Tool use wxWindows?</B></P>
-<P>A: wxWindows is an open source, mature multi-platform GUI toolkit
-for C++. It makes platform-independence relatively easy to achieve,
-whilst remaining compatibility with the look and feel of GTK+ and
-WIN32 on the respective platforms. wxWindows was chosen on its own
-merits but, by sheer coincidence, the author of the new Configuration
-Tool is also the original author of wxWindows. Using a
-platform-independent API will make it easier to port the
-Configuration Tool to other platforms if needed.</P>
-<P><B>Q: Where can I get more information about wxWindows?</B></P>
-<P>A: The wxWindows web site is at <A HREF="http://www.wxwindows.org/">http://www.wxwindows.org</A>.
-wxWindows distributions come with documentation in a variety of
-formats.</P>
-<P><B>Q: Does the new Configuration Tool make the old one obsolete?</B></P>
-<P>A: Not yet. The new tool doesn't yet support some features, such
-as the Memory Layout Tool. When these have
-been implemented, and the tool has been subject to the required
-quality assurance procedure, then we can retire the old tool.</P>
-<P><B>Q: How can I help improve the Configuration Tool?</B></P>
-<P>A: All help is very welcome: please see
-<A HREF="http://sources.redhat.com/ecos/faq.html">http://sources.redhat.com/ecos/faq.html</A>
-for how to contribute.</P>
-<P><B>Q: Who do I contact when things go wrong?</B></P>
-<P>A: Please discuss problems on the ecos-discuss mailing list: see
-<A HREF="http://sources.redhat.com/ecos/intouch.html">http://sources.redhat.com/ecos/intouch.html</A>.</P>
-<P><B>Q: The compiler fails to compile dcclient.cpp. What do I do?</B></P>
-<P>A: It may be that you have a non-standard GTK+ 1.2.6 which has
-changes backported from 1.2.7. Use the makefile target 'wxgtkfix' to
-fix this after the error has happened (i.e. after configure has
-produced the setup.h and makefiles):</P>
-<P><TT>% make -f
-$CONFIGTOOLDIR/Makefile WXDIR=$WXDIR ECOSDIR=$ECOSDIR LEVEL=release
-wxgtkfix</TT></P>
-<P>or</P>
-<P><TT>% make -f
-$CONFIGTOOLDIR/Makefile WXDIR=$WXDIR ECOSDIR=$ECOSDIR LEVEL=debug
-wxgtkfix</TT></P>
-<P>Now use the 'wx ecc ct' targets (not 'full') to continue building.</P>
-<H2>Building the Configuration Tool under Linux</H2>
-<P>This build system is subject to change.</P>
-<H4>You will need:</H4>
-<OL>
-	<LI><P>gcc 2.95.2 or later</P>
-	<LI><P>GTK+ and glib 1.2.6 or above. Please remove any 1.3
-	development RPMs from your setup using for example:</P>
-	<P>rpm -e gtk+-gtkbeta-devel-1.3.1b-2</P>
-	<P>You can get GTK+ and glib for Red Hat 6.2 and above
-	from:<BR><BR><A HREF="ftp://ftp.gtk.org/pub/gtk/v1.2/binary/RPMS/RedHat-6.2/RPMS/i386/gtk+-1.2.8-1.i386.rpm">ftp://ftp.gtk.org/pub/gtk/v1.2/binary/RPMS/RedHat-6.2/RPMS/i386/gtk+-1.2.8-1.i386.rpm</A><BR><A HREF="ftp://ftp.gtk.org/pub/gtk/v1.2/binary/RPMS/RedHat-6.2/RPMS/i386/glib-1.2.8-1.i386.rpm">ftp://ftp.gtk.org/pub/gtk/v1.2/binary/RPMS/RedHat-6.2/RPMS/i386/glib-1.2.8-1.i386.rpm</A></P>
-	<LI><P>a suitable version of wxWindows for GTK+, available from
-	<A HREF="ftp://sources.redhat.com/pub/ecos/ct2/">ftp://sources.redhat.com/pub/ecos/ct2/</A>.</P>
-	<P>Unarchive the file wxGTK-x.y.z.tar.bz2 (downloaded from
-        <A href="ftp://sources.redhat.com/pub/ecos/ct2/">
-        ftp://sources.redhat.com/pub/ecos/ct2/</A>) into a suitable directory,
-	e.g. 
-	</P>
-	<P><TT>% mkdir /home/julians/wxWindows<BR>% cd /home/julians/wxWindows<BR>%
-	tar xvfz /tmp/wxGTK-x.y.z.tgz</TT></P>
-	<P>You may also wish to download and unarchive wxWindows
-	documentation, which is supplied in zip form. Unarchive using e.g.:</P>
-	<P><TT>% cd /home/julians/wxWindows<BR>% unzip -a
-	wxWindows-x.y.z-HTML.zip</TT></P>
-	<LI><P>an eCos source hierarchy. See
-	<A HREF="http://sources.redhat.com/ecos/anoncvs.html">http://sources.redhat.com/ecos/anoncvs.html</A>
-	for how to download this from the CVS repository. For example:</P>
-	<P><TT>cvs -d :pserver:anoncvs@sources.redhat.com:/cvs/ecos co ecos/host</TT></P>
-	<LI><P>other tools:</P>
-	<P>Tcl/Tk 8.2 or above. See <A HREF="http://dev.scriptics.com/">http://dev.scriptics.com/</A></P>
-</OL>
-<H4>Summary:</H4>
-<P>There is no 'configure' step for the eCos Configuration Tool as a
-whole, although the host tool libraries and wxWindows have configure
-scripts which are invoked by the makefile.</P>
-<P>You work in a build directory of your choosing, and the makefile
-will create the following directories underneath it:</P>
-<TABLE WIDTH=100% BORDER=0 CELLPADDING=4 CELLSPACING=0>
-	<COL WIDTH=59*>
-	<COL WIDTH=197*>
-	<THEAD>
-		<TR VALIGN=TOP>
-			<TD WIDTH=23%>
-				<P>ct-build-debug/</P>
-			</TD>
-			<TD WIDTH=77%>
-				<P>Configtool debug build</P>
-			</TD>
-		</TR>
-	</THEAD>
-	<TBODY>
-		<TR VALIGN=TOP>
-			<TD WIDTH=23%>
-				<P>ecc-build-debug/ 
-				</P>
-			</TD>
-			<TD WIDTH=77%>
-				<P>eCos libraries debug build</P>
-			</TD>
-		</TR>
-		<TR VALIGN=TOP>
-			<TD WIDTH=23%>
-				<P>wxwin-build-debug/ 
-				</P>
-			</TD>
-			<TD WIDTH=77%>
-				<P>wxWindows debug build</P>
-			</TD>
-		</TR>
-		<TR VALIGN=TOP>
-			<TD WIDTH=23%>
-				<P>ct-build-release/ 
-				</P>
-			</TD>
-			<TD WIDTH=77%>
-				<P>Configtool release build</P>
-			</TD>
-		</TR>
-		<TR VALIGN=TOP>
-			<TD WIDTH=23%>
-				<P>ecc-build-release/ 
-				</P>
-			</TD>
-			<TD WIDTH=77%>
-				<P>eCos libraries release build</P>
-			</TD>
-		</TR>
-		<TR VALIGN=TOP>
-			<TD WIDTH=23%>
-				<P>wxwin-build-release/ 
-				</P>
-			</TD>
-			<TD WIDTH=77%>
-				<P>wxWindows release build</P>
-			</TD>
-		</TR>
-	</TBODY>
-</TABLE>
-<P>You need to pass the wxWindows source directory (WXDIR) and eCos
-hierarchy directory (ECOSDIR) to the makefile, along with the build
-LEVEL (debug or release). Please see makect.sh in the source
-directory, which is a useful helper script for making it easier to
-invoke the makefile.</P>
-<P>You also supply a target to build, such as full (everything), ct
-(just the Configuration Tool), wx (wxWindows only) or ecc (eCos
-libraries only). It is important to supply the target as the <B>last</B>
-command(s) on the command line.</P>
-<P>The makefile builds and uses wxWindows as a static library, which
-minimizes problems with shared libraries and still results in a
-reasonable size of executable (around 6 MB). Switching off
-unnecessary wxWindows features may result in smaller executables.</P>
-<P>IMPORTANT NOTE: currently, there are inadequate dependencies in
-the makefiles, so please make sure you start with a clean directory
-before building (use the cleanct target if necessary).</P>
-<H4>Examples:</H4>
-<P>This builds the eCos libraries, wxWindows, and the Configuration
-Tool, debug mode.</P>
-<TT><P>% export ECOSDIR=/home/julians/cvs/eCos # The dir above 'host'<BR>%
-export
-CONFIGTOOLDIR=$ECOSDIR/host/tools/configtool/standalone/wxwin<BR>%
-export WXDIR=/home/julians/wxWindows<BR>% mkdir /tmp/ecos-build<BR>%
-cd /tmp/ecos-build<BR>% make -f $CONFIGTOOLDIR/Makefile WXDIR=$WXDIR
-ECOSDIR=$ECOSDIR LEVEL=debug full</P>
-</TT>
-<P>This builds just the Configuration Tool, say after a file was
-edited, in release mode.</P>
-<TT><P>% export ECOSDIR=/home/julians/cvs/eCos<BR>% export
-CONFIGTOOLDIR=$ECOSDIR/host/tools/configtool/standalone/wxwin<BR>%
-export WXDIR=/home/julians/wxWindows<BR>% cd /tmp/ecos-build<BR>%
-make -f $CONFIGTOOLDIR/Makefile WXDIR=$WXDIR ECOSDIR=$ECOSDIR
-LEVEL=release ct</P>
-</TT>
-<H4>Troubleshooting</H4>
-<P>Please see the FAQ for what to do if the wxWindows file
-dcclient.cpp fails to compile.</P>
-<H2>Building the Configuration Tool under Windows</H2>
-<H4>You will need:</H4>
-<OL>
-	<LI><P>Microsoft Visual C++ 6.0 or later</P>
-	<LI><P>a suitable version of wxWindows for MS Windows, available
-	from <A HREF="ftp://sources.redhat.com/pub/ecos/ct2/">ftp://sources.redhat.com/pub/ecos/ct2/</A>.
-	To install the sources in 'setup' form, just run the executable and
-	follow the instructions. If you have downloaded the sources in zip
-	format, you will need to unarchive the file wxMSW-x.y.z.zip into a
-	suitable directory, e.g.</P>
-    <TT>
-	<P>&gt; mkdir c:\wxWindows<BR>&gt; c:<BR>&gt; cd \wxWindows<BR>&gt;
-	unzip c:\temp\wxMSW-x.y.z.zip</P>
-	</TT>
-	<P>Alternatively, you can use WinZip or similar utility to unarchive
-	the files.</P>
-	<P>Documentation in Windows HTML Help format is supplied in the
-	setup or zipped distribution and does not have to be downloaded
-	separately.</P>
-	<LI><P>an eCos source hierarchy. See
-	<A HREF="http://sources.redhat.com/ecos/anoncvs.html">http://sources.redhat.com/ecos/anoncvs.html</A>
-	for how to download this from the CVS repository. For example:</P>
-	<TT><P>cvs -d :pserver:anoncvs@sources.redhat.com:/cvs/ecos co ecos/host</P></TT>
-	<LI><P>other tools:</P>
-	<UL>
-		<LI><P>Cygwin (sometimes called GNUPro). See
-		<A HREF="http://sources.redhat.com/cygwin/">http://sources.redhat.com/cygwin/</A></P>
-		<LI><P>Tcl/Tk 8.2 or above. See <A HREF="http://dev.scriptics.com/">http://dev.scriptics.com/</A></P>
-	</UL>
-</OL>
-<H4>Summary:</H4>
-<P>There are two main steps: building wxWindows, and building the
-Configuration Tool. The Configuration Tool project file also builds
-the required eCos libraries. Note that unlike compilation under
-Linux, the wxWindows objects and libraries end up in the wxWindows
-source tree.</P>
-<P>Before routinely building the Configuration Tool, you will need to
-set up Visual C++ with the correct paths (see below).</P>
-<H4>Steps:</H4>
-<OL>
-	<LI><P>Execute in a DOS box:</P>
-	<TT><P>subst v: d:\tmp</P></TT>
-	<P>where d:\tmp is a suitable temporary directory where the
-	Configuration Tool binaries and objects will end up.</P>
-	<LI><P>Set the TCLHOME environment variable to where Tcl is
-	installed. On Windows 9x, edit autoexec.bat. On Windows NT or W2K,
-	use the System control panel applet.</P>
-	<LI><P>Build wxWindows. To do this, run VC++ and open src/msvc.dsw
-	in the wxWindows project hierarchy. Select Build | Batch Build and
-	check &quot;wxvc - WIN32 Debug&quot; and &quot;wxvc - WIN32
-	Release&quot;. Click on Build.</P>
-	<LI><P>Open the
-	eCos/ecc/host/tools/configtool/standalone/wxwin/ConfigtoolVC.dsw
-	workspace. Choose Tools | Options and click on the Directories tab.</P>
-	<P>Select Show directories for: Include files.</P>
-	<P>You need to add paths such as these:</P>
-    <TT>
-	<P>c:\Program Files\Tcl\include<BR>d:\wxWindows-010212\include</P></TT>
-	<P>Select Show directories for: Library files. Add these paths,
-	changing as necessary:</P>
-	<TT>
-	<P>c:\Program Files\Tcl\lib<BR>d:\wxWindows-010212\lib</P>
-	</TT>
-	<LI><P>Click on Select Active Configuration... and select the one
-	you wish to build, such as WIN32 Ansi Debug (note that Unicode
-	configurations are not yet available). Choose Build | Rebuild All to
-	build the project. The configtool.exe executable should end up in
-	v:\Configtool\AnsiDebug.</P>
-</OL>
-<P>When compiled, configtool.exe depends on the following DLLs found
-in your system32 directory that should be supplied with the
-executable:</P>
-<UL>
-	<LI>TCL82.DLL (or other name if you used a different version of
-	TCL)
-	<LI>MSVCIRT.DLL
-	<LI>MSVCP60.DLL
-	<LI>MSVCRT.DLL
-</UL>
-<P><!-- EndFragment --></P>
-</BODY>
-</HTML>
--- a/host/tools/configtool/standalone/wxwin/symbols.h
+++ b/host/tools/configtool/standalone/wxwin/symbols.h
@@ -30,7 +30,7 @@
 // Author(s):   julians
 // Contact(s):  julians
 // Date:        2001/05/14
-// Version:     $Id: symbols.h,v 1.7 2001/07/16 14:02:56 julians Exp $
+// Version:     $Id: symbols.h,v 1.8 2001/08/10 14:58:21 julians Exp $
 // Purpose:
 // Description: Some important symbols, such as the version
 // Requires:
@@ -43,5 +43,5 @@
 //
 //===========================================================================
 
-#define ecCONFIGURATION_TOOL_VERSION        2.04
+#define ecCONFIGURATION_TOOL_VERSION        2.05
 
--- a/packages/NEWS
+++ b/packages/NEWS
@@ -1,3 +1,5 @@
+* Generic SMP support added.
+* RedBoot support added to AM33-STB port.
 * Add Atmel AT91/EB40 port, including flash and serial drivers.
 * Added HAL port to SEGA Dreamcast.
   Contributed by Takeshi Yaegashi <t@keshi.org>
--- a/packages/compat/posix/current/ChangeLog
+++ b/packages/compat/posix/current/ChangeLog
@@ -1,3 +1,74 @@
+2001-08-06  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* cdl/posix.cdl: Reorganize dependencies so that signals, timers
+	and pthreads really can be disabled, and the relevant files don't
+	get built.
+	Build new mutex.cxx file.
+	Remove duplicate CYGPKG_POSIX_SCHED dependency for pthreads.
+
+	* include/limits.h: Don't include irrelevant header dependencies.
+
+	* include/muttypes.h: New type defining mutex/cond var types separately
+	from other pthread types.
+
+	* include/types.h: Remove mutex/cond var types.
+
+	* include/signal.h: Conditionalize on CYGPKG_POSIX_SIGNALS
+
+	* include/sigsetjmp.h: Don't include irrelevant header dependencies.
+	Rewrite sigsetjmp in a much more compiler friendly (and readable)
+	way with less type punning.
+
+	* src/misc.cxx: Don't include sysconf cases when pthreads or
+	CYGPKG_POSIX_TIMERS not enabled.
+
+	* src/mutex.cxx: New file, broken out of pthreads.cxx, as most
+	of it is not fixed to the pthreads implementation, and I've fixed
+	the bits that were too tied to it.
+
+	* src/pprivate.h: Conditionalize definitions that are specific
+	to CYGPKG_POSIX_PTHREAD. Ditto for prototypes for CYGPKG_POSIX_SIGNALS
+	and CYGPKG_POSIX_TIMERS. Move PTHREAD_ENTRY/RETURN etc. macros
+	here so they can be used throughout the package.
+
+	* src/pthread.cxx: Remove mutex/cond var implementation, and
+	entry/return macros, as per above.
+
+	* src/signal.cxx (cyg_sigqueue): Don't just set non-queueable signals 
+	pending - also forcibly wake up any blocked threads.
+	(siglongjmp): Use new layout of sigjmp_buf.
+
+	* tests/mutex3.c:
+	* tests/pthread1.c:
+	* tests/pthread2.c:
+	* tests/pthread3.c:
+	* tests/signal1.c:
+	* tests/sigsetjmp.c:
+	* tests/timer1.c:
+	* tests/tm_basic.cxx:
+	Correct configuration dependencies, and do NA appropriately.
+	
+2001-08-03  Nick Garnett  <nickg@cygnus.co.uk>
+
+	Imported from a development branch:
+	
+	2001-06-27  Nick Garnett  <nickg@cygnus.co.uk>
+
+		* tests/pthread3.c:
+		Modified the loop that waits for the threads to get going so that
+		it will function correctly in an SMP system, where the threads
+		will run in parallel.
+
+		* tests/mutex3.c: Disabled this test for SMP systems. It depends
+		too much on predicting the priority-driven execution order of the
+		threads. In an SMP system, some threads will run in parallel and
+		falsify the assumptions.
+
+	2001-05-25  Nick Garnett  <nickg@cygnus.co.uk>
+
+		* src/signal.cxx (siglongjmp): Minor change to satisfy latest C++
+		compiler.
+
 2001-06-14  Jonathan Larmour  <jlarmour@redhat.com>
 
 	* src/pthread.cxx (pthread_attr_setstacksize): Correct stack
--- a/packages/compat/posix/current/cdl/posix.cdl
+++ b/packages/compat/posix/current/cdl/posix.cdl
@@ -23,7 +23,7 @@
 #                                                                          
 # The Initial Developer of the Original Code is Red Hat.                   
 # Portions created by Red Hat are                                          
-# Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+# Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.      
 # All Rights Reserved.                                                     
 # -------------------------------------------                              
 #                                                                          
@@ -56,18 +56,17 @@ cdl_package CYGPKG_POSIX {
     implements     CYGINT_ISO_SIGNAL_NUMBERS
     implements     CYGINT_ISO_SIGNAL_IMPL
     implements     CYGINT_ISO_POSIX_LIMITS
-    implements     CYGINT_ISO_SIGSETJMP
+    implements     CYGINT_ISO_PMUTEXTYPES
     requires       { CYGBLD_ISO_SIGNAL_NUMBERS_HEADER == \
                          "<cyg/posix/signal.h>" }
     requires       { CYGBLD_ISO_SIGNAL_IMPL_HEADER == \
                          "<cyg/posix/signal.h>" }
     requires       { CYGBLD_ISO_POSIX_LIMITS_HEADER == \
                          "<cyg/posix/limits.h>" }
-    requires       { CYGBLD_ISO_SIGSETJMP_HEADER == \
-                         "<cyg/posix/sigsetjmp.h>" }
+    requires       { CYGBLD_ISO_PMUTEXTYPES_HEADER == \
+                         "<cyg/posix/muttypes.h>" }
     
-    compile        pthread.cxx mqueue.cxx sem.cxx time.cxx signal.cxx \
-                   sched.cxx except.cxx misc.cxx
+    compile        mqueue.cxx mutex.cxx sem.cxx misc.cxx
     compile       -library=libextras.a startup.cxx
 
     # ----------------------------------------------------------------
@@ -79,6 +78,8 @@ cdl_package CYGPKG_POSIX {
 	default_value    1
 	description      "This component provides controls over scheduling
 	                  in POSIX."
+        requires         CYGPKG_POSIX_TIMERS
+        compile          sched.cxx
 
 	cdl_option _POSIX_PRIORITY_SCHEDULING {
 	    display       "POSIX priority scheduling feature test macro"
@@ -98,10 +99,9 @@ cdl_package CYGPKG_POSIX {
 	display          "POSIX pthread configuration"
 	flavor           bool
 	default_value    1
-	requires         CYGPKG_POSIX_SCHED
 	description      "This component provides configuration controls for
 	                  the POSIX pthreads package."
-
+        compile          pthread.cxx
 	script           pthread.cdl
     }
 
@@ -122,6 +122,7 @@ cdl_package CYGPKG_POSIX {
         requires         CYGPKG_KERNEL
         requires         CYGVAR_KERNEL_COUNTERS_CLOCK
         requires         CYGPKG_POSIX_PTHREAD
+        compile          time.cxx
 	description      "This component provides configuration controls for
 	                  the POSIX timers."
     }
@@ -201,8 +202,12 @@ cdl_package CYGPKG_POSIX {
         requires         CYGPKG_POSIX_PTHREAD
         requires         CYGPKG_POSIX_TIMERS
         implements       CYGINT_POSIX_REALTIME_SIGNALS
+        implements       CYGINT_ISO_SIGSETJMP
+        requires         { CYGBLD_ISO_SIGSETJMP_HEADER == \
+                             "<cyg/posix/sigsetjmp.h>" }
 	description      "This component provides configuration controls for
 	                  the POSIX signals."
+        compile          signal.cxx except.cxx 
     }
 
     # ----------------------------------------------------------------
--- a/packages/compat/posix/current/include/limits.h
+++ b/packages/compat/posix/current/include/limits.h
@@ -25,7 +25,7 @@
 //                                                                          
 // The Initial Developer of the Original Code is Red Hat.                   
 // Portions created by Red Hat are                                          
-// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.      
 // All Rights Reserved.                                                     
 // -------------------------------------------                              
 //                                                                          
@@ -50,8 +50,6 @@
 //
 //=============================================================================
 
-#include <pkgconf/hal.h>
-#include <pkgconf/kernel.h>
 #include <pkgconf/posix.h>
 
 //-----------------------------------------------------------------------------
new file mode 100644
--- /dev/null
+++ b/packages/compat/posix/current/include/muttypes.h
@@ -0,0 +1,128 @@
+#ifndef CYGONCE_POSIX_MUTTYPES_H
+#define CYGONCE_POSIX_MUTTYPES_H
+//=============================================================================
+//
+//      muttypes.h
+//
+//      POSIX mutex types header
+//
+//=============================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.               
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//=============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     nickg
+// Contributors:  nickg,jlarmour
+// Date:          2000-03-17
+// Purpose:       POSIX types header
+// Description:   This header contains POSIX type definitions for mutexes
+//                and cond vars. These types are implementation defined.
+//              
+// Usage:         #include <sys/types.h>
+//              
+//
+//####DESCRIPTIONEND####
+//
+//=============================================================================
+
+#include <pkgconf/posix.h>
+
+#include <cyg/infra/cyg_type.h>
+
+//-----------------------------------------------------------------------------
+// Mutex object
+// This structure must exactly correspond in size and layout to the underlying
+// eCos C++ class that implements this object. Because we have to support
+// PTHREAD_MUTEX_INITIALIZER we cannot abstract this object very easily.
+
+typedef struct
+{
+    CYG_WORD32  locked;
+    CYG_ADDRESS owner;
+    CYG_ADDRESS queue;
+
+#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
+    CYG_WORD32  protocol;       // this mutex's protocol
+#endif    
+    
+#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
+    CYG_WORD32  ceiling;        // mutex priority ceiling
+#endif
+    
+} pthread_mutex_t;
+
+#if defined(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC) &&\
+    defined(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING)
+#define PTHREAD_MUTEX_INITIALIZER { 0, 0, 0, 0, 0 }
+#elif defined(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC) ||\
+    defined(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING)
+#define PTHREAD_MUTEX_INITIALIZER { 0, 0, 0, 0 }
+#else
+#define PTHREAD_MUTEX_INITIALIZER { 0, 0, 0 }
+#endif
+
+//-----------------------------------------------------------------------------
+// Mutex attributes structure
+
+typedef struct
+{
+    int         protocol;
+#ifdef _POSIX_THREAD_PRIO_PROTECT    
+    int         prioceiling;
+#endif    
+} pthread_mutexattr_t;
+
+// Values for protocol
+#define PTHREAD_PRIO_NONE       1
+#if defined(_POSIX_THREAD_PRIO_INHERIT)
+#define PTHREAD_PRIO_INHERIT    2
+#endif
+#if defined(_POSIX_THREAD_PRIO_PROTECT)
+#define PTHREAD_PRIO_PROTECT    3
+#endif
+
+//-----------------------------------------------------------------------------
+// Condition Variable structure.
+// Like mutexes, this must match the underlying eCos implementation class.
+
+typedef struct
+{
+    CYG_ADDRESS         mutex;
+    CYG_ADDRESS         queue;    
+} pthread_cond_t;
+
+#define PTHREAD_COND_INITIALIZER { 0, 0 }
+
+//-----------------------------------------------------------------------------
+// Condition variable attributes structure
+
+typedef struct
+{
+    int         dummy;
+} pthread_condattr_t;
+
+//-----------------------------------------------------------------------------
+#endif // ifndef CYGONCE_POSIX_MUTTYPES_H
+// End of muttypes.h
--- a/packages/compat/posix/current/include/signal.h
+++ b/packages/compat/posix/current/include/signal.h
@@ -25,7 +25,7 @@
 //                                                                          
 // The Initial Developer of the Original Code is Red Hat.                   
 // Portions created by Red Hat are                                          
-// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.      
 // All Rights Reserved.                                                     
 // -------------------------------------------                              
 //                                                                          
@@ -52,6 +52,8 @@
 #include <pkgconf/kernel.h>
 #include <pkgconf/posix.h>
 
+#ifdef CYGPKG_POSIX_SIGNALS
+
 #include <stddef.h>             // NULL, size_t
 
 #include <limits.h>
@@ -295,6 +297,8 @@ externC sa_sighandler_t signal(int __sig
 
 externC int raise(int __sig);
 
+#endif // ifdef CYGPKG_POSIX_SIGNALS
+
 //-----------------------------------------------------------------------------
 #endif // ifndef CYGONCE_SIGNAL_H
 // End of signal.h
--- a/packages/compat/posix/current/include/sigsetjmp.h
+++ b/packages/compat/posix/current/include/sigsetjmp.h
@@ -25,7 +25,7 @@
 //                                                                          
 // The Initial Developer of the Original Code is Red Hat.                   
 // Portions created by Red Hat are                                          
-// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.      
 // All Rights Reserved.                                                     
 // -------------------------------------------                              
 //                                                                          
@@ -48,11 +48,8 @@
 //
 //=============================================================================
 
-#include <pkgconf/hal.h>
-#include <pkgconf/kernel.h>
-#include <pkgconf/posix.h>
-
 #include <signal.h>
+#include <cyg/hal/hal_arch.h>       // hal_jmp_buf
 
 //=============================================================================
 // sigjmp_buf structure
@@ -62,18 +59,20 @@
 // sizeof(hal_jmp_buf)                    savemask value (an int)
 // sizeof(hal_jmp_buf)+sizeof(int)...     sigset_t containing saved mask
 
-typedef cyg_uint8 sigjmp_buf[sizeof(hal_jmp_buf)+sizeof(int)+(sizeof(sigset_t))];
+typedef struct {
+    hal_jmp_buf __jmp_buf;
+    int  __savemask;
+    sigset_t __sigsavemask;
+} sigjmp_buf[1];
 
 //=============================================================================
 // sigsetjmp() macro
 
 #define sigsetjmp( _env_, _savemask_ )                                        \
 (                                                                             \
- (*(int *)&((_env_)[sizeof(hal_jmp_buf)])=(_savemask_)),                      \
- ((_savemask_)?pthread_sigmask(SIG_BLOCK,NULL,                                \
-                                  (sigset_t *)&(_env_)[sizeof(hal_jmp_buf)+   \
-                                                      sizeof(int)]):0),       \
- hal_setjmp(*(hal_jmp_buf *)&_env_[0])                                        \
+ ((_env_)[0].__savemask = _savemask_),                                        \
+ ((_savemask_)?pthread_sigmask(SIG_BLOCK,NULL,&((_env_)[0].__sigsavemask)):0),\
+ hal_setjmp((_env_)[0].__jmp_buf)                                             \
 )
 
 //=============================================================================
--- a/packages/compat/posix/current/include/types.h
+++ b/packages/compat/posix/current/include/types.h
@@ -25,7 +25,7 @@
 //                                                                          
 // The Initial Developer of the Original Code is Red Hat.                   
 // Portions created by Red Hat are                                          
-// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.      
 // All Rights Reserved.                                                     
 // -------------------------------------------                              
 //                                                                          
@@ -99,77 +99,5 @@ typedef struct pthread_attr_t
 #define PTHREAD_EXPLICIT_SCHED          2
 
 //-----------------------------------------------------------------------------
-// Mutex object
-// This structure must exactly correspond in size and layout to the underlying
-// eCos C++ class that implements this object. Because we have to support
-// PTHREAD_MUTEX_INITIALIZER we cannot abstract this object very easily.
-
-typedef struct
-{
-    CYG_WORD32  locked;
-    CYG_ADDRESS owner;
-    CYG_ADDRESS queue;
-
-#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
-    CYG_WORD32  protocol;       // this mutex's protocol
-#endif    
-    
-#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
-    CYG_WORD32  ceiling;        // mutex priority ceiling
-#endif
-    
-} pthread_mutex_t;
-
-#if defined(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC) &&\
-    defined(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING)
-#define PTHREAD_MUTEX_INITIALIZER { 0, 0, 0, 0, 0 }
-#elif defined(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC) ||\
-    defined(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING)
-#define PTHREAD_MUTEX_INITIALIZER { 0, 0, 0, 0 }
-#else
-#define PTHREAD_MUTEX_INITIALIZER { 0, 0, 0 }
-#endif
-
-//-----------------------------------------------------------------------------
-// Mutex attributes structure
-
-typedef struct
-{
-    int         protocol;
-#ifdef _POSIX_THREAD_PRIO_PROTECT    
-    int         prioceiling;
-#endif    
-} pthread_mutexattr_t;
-
-// Values for protocol
-#define PTHREAD_PRIO_NONE       1
-#if defined(_POSIX_THREAD_PRIO_INHERIT)
-#define PTHREAD_PRIO_INHERIT    2
-#endif
-#if defined(_POSIX_THREAD_PRIO_PROTECT)
-#define PTHREAD_PRIO_PROTECT    3
-#endif
-
-//-----------------------------------------------------------------------------
-// Condition Variable structure.
-// Like mutexes, this must match the underlying eCos implementation class.
-
-typedef struct
-{
-    CYG_ADDRESS         mutex;
-    CYG_ADDRESS         queue;    
-} pthread_cond_t;
-
-#define PTHREAD_COND_INITIALIZER { 0, 0 }
-
-//-----------------------------------------------------------------------------
-// Condition variable attributes structure
-
-typedef struct
-{
-    int         dummy;
-} pthread_condattr_t;
-
-//-----------------------------------------------------------------------------
 #endif // ifndef CYGONCE_POSIX_TYPES_H
 // End of types.h
--- a/packages/compat/posix/current/src/misc.cxx
+++ b/packages/compat/posix/current/src/misc.cxx
@@ -23,7 +23,7 @@
 //                                                                          
 // The Initial Developer of the Original Code is Red Hat.                   
 // Portions created by Red Hat are                                          
-// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.      
 // All Rights Reserved.                                                     
 // -------------------------------------------                              
 //                                                                          
@@ -127,15 +127,18 @@
         SC_CASE( _SC_SEM_VALUE_MAX,                     SEM_VALUE_MAX );
         SC_CASE( _SC_SIGQUEUE_MAX,                      SIGQUEUE_MAX );
         SC_CASE( _SC_STREAM_MAX,                        STREAM_MAX );
+#ifdef CYGPKG_POSIX_PTHREAD
         SC_CASE( _SC_THREAD_DESTRUCTOR_ITERATIONS,      PTHREAD_DESTRUCTOR_ITERATIONS );
         SC_CASE( _SC_THREAD_KEYS_MAX,                   PTHREAD_KEYS_MAX );
         SC_CASE( _SC_THREAD_STACK_MIN,                  PTHREAD_STACK_MIN );
         SC_CASE( _SC_THREAD_THREADS_MAX,                PTHREAD_THREADS_MAX );
+#endif
         SC_CASE( _SC_TIMER_MAX,                         TIMER_MAX );
         SC_CASE( _SC_TTY_NAME_MAX,                      TTY_NAME_MAX );
         SC_CASE( _SC_TZNAME_MAX,                        TZNAME_MAX );
         SC_CASE( _SC_VERSION,                           _POSIX_VERSION );
 
+#ifdef CYGPKG_POSIX_TIMERS
     case _SC_CLK_TCK:
     {
         struct timespec ts;
@@ -144,6 +147,7 @@
         cyg_tick_count ticks = cyg_timespec_to_ticks( &ts );
         return ticks;
     }
+#endif
 
     case _SC_ASYNCHRONOUS_IO:
     #ifdef _POSIX_ASYNCHRONOUS_IO
new file mode 100644
--- /dev/null
+++ b/packages/compat/posix/current/src/mutex.cxx
@@ -0,0 +1,515 @@
+//==========================================================================
+//
+//      pthread.cxx
+//
+//      POSIX pthreads implementation
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 2000, 2001 Red Hat, Inc.
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):           nickg
+// Contributors:        nickg, jlarmour
+// Date:                2000-03-27
+// Purpose:             POSIX pthread implementation
+// Description:         This file contains the implementation of the POSIX pthread
+//                      functions.
+//              
+//              
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/posix.h>
+
+#include <cyg/infra/cyg_trac.h>        // tracing macros
+#include <cyg/infra/cyg_ass.h>         // assertion macros
+
+#include "pprivate.h"                  // POSIX private header
+
+#include <cyg/kernel/thread.hxx>       // thread definitions
+#include <cyg/kernel/mutex.hxx>        // mutex definitions
+#include <cyg/kernel/clock.hxx>        // clock definitions
+#include <pthread.h>
+
+#include <cyg/kernel/thread.inl>       // thread inlines
+
+//-----------------------------------------------------------------------------
+// new operator to allow us to construct mutex objects
+
+inline void *operator new(size_t size,  cyg_uint8 *ptr) { return (void *)ptr; };
+
+//=============================================================================
+// Mutexes
+
+//-----------------------------------------------------------------------------
+// Mutex attributes manipulation functions
+
+//-----------------------------------------------------------------------------
+// Initialize attribute object
+
+externC int pthread_mutexattr_init ( pthread_mutexattr_t *attr)
+{
+    PTHREAD_ENTRY();
+    
+    PTHREAD_CHECK(attr);
+
+    attr->protocol      = PTHREAD_PRIO_NONE;
+#ifdef _POSIX_THREAD_PRIO_PROTECT    
+    attr->prioceiling   = 0;
+#endif
+    
+    PTHREAD_RETURN(0);
+}
+
+//-----------------------------------------------------------------------------
+// Destroy attribute object
+
+externC int pthread_mutexattr_destroy ( pthread_mutexattr_t *attr)
+{
+    PTHREAD_ENTRY();
+    
+    PTHREAD_CHECK(attr);
+
+    // Nothing to do here...
+    
+    PTHREAD_RETURN(0);
+}
+
+//-----------------------------------------------------------------------------
+// Optional functions depending on priority inversion protection options.
+
+#if defined(_POSIX_THREAD_PRIO_INHERIT) || defined(_POSIX_THREAD_PRIO_PROTECT)
+
+// Set priority inversion protection protocol
+externC int pthread_mutexattr_setprotocol ( pthread_mutexattr_t *attr,
+                                            int protocol)
+{
+    PTHREAD_ENTRY();
+    
+    PTHREAD_CHECK(attr);
+
+    switch( protocol )
+    {
+    case PTHREAD_PRIO_NONE:
+#if defined(_POSIX_THREAD_PRIO_INHERIT)        
+    case PTHREAD_PRIO_INHERIT:
+#endif
+#if defined(_POSIX_THREAD_PRIO_PROTECT)
+    case PTHREAD_PRIO_PROTECT:
+#endif        
+        attr->protocol = protocol;
+        PTHREAD_RETURN(0);
+
+    default:
+        PTHREAD_RETURN(EINVAL);
+    }
+    
+    PTHREAD_RETURN(0);
+}
+
+// Get priority inversion protection protocol
+externC int pthread_mutexattr_getprotocol ( pthread_mutexattr_t *attr,
+                                            int *protocol)
+{
+    PTHREAD_ENTRY();
+    
+    PTHREAD_CHECK(attr);
+
+    if( protocol != NULL )
+        *protocol = attr->protocol;
+    
+    PTHREAD_RETURN(0);
+}
+
+#if defined(_POSIX_THREAD_PRIO_PROTECT)
+
+// Set priority for priority ceiling protocol
+externC int pthread_mutexattr_setprioceiling ( pthread_mutexattr_t *attr,
+                                               int prioceiling)
+{
+    PTHREAD_ENTRY();
+    
+    PTHREAD_CHECK(attr);
+
+    
+    attr->prioceiling = prioceiling;
+    
+    PTHREAD_RETURN(0);
+}
+
+// Get priority for priority ceiling protocol
+externC int pthread_mutexattr_getprioceiling ( pthread_mutexattr_t *attr,
+                                               int *prioceiling)
+{
+    PTHREAD_ENTRY();
+    
+    PTHREAD_CHECK(attr);
+
+    if( prioceiling != NULL )
+        *prioceiling = attr->prioceiling;
+    
+    PTHREAD_RETURN(0);
+}
+
+// Set priority ceiling of given mutex, returning old ceiling.
+externC int pthread_mutex_setprioceiling( pthread_mutex_t *mutex,
+                                          int prioceiling,
+                                          int *old_ceiling)
+{
+    PTHREAD_ENTRY();
+    
+    PTHREAD_CHECK(mutex);
+
+    pthread_mutex_lock( mutex );
+
+    Cyg_Mutex *mx = (Cyg_Mutex *)mutex;
+
+    if( old_ceiling != NULL )
+        *old_ceiling = mx->get_ceiling();
+    
+    mx->set_ceiling( prioceiling );
+    
+    pthread_mutex_unlock( mutex );
+
+    PTHREAD_RETURN(0);
+}
+
+// Get priority ceiling of given mutex
+externC int pthread_mutex_getprioceiling( pthread_mutex_t *mutex,
+                                          int *prioceiling)
+{
+    PTHREAD_ENTRY();
+    
+    PTHREAD_CHECK(mutex);
+
+    Cyg_Mutex *mx = (Cyg_Mutex *)mutex;
+
+    if( prioceiling != NULL )
+        *prioceiling = mx->get_ceiling();
+        
+    PTHREAD_RETURN(0);
+}
+
+#endif // defined(_POSIX_THREAD_PRIO_PROTECT)
+
+#endif // defined(_POSIX_THREAD_PRIO_INHERIT) || defined(_POSIX_THREAD_PRIO_PROTECT)
+
+//-----------------------------------------------------------------------------
+// Mutex functions
+
+//-----------------------------------------------------------------------------
+// Initialize mutex. If mutex_attr is NULL, use default attributes.
+
+externC int pthread_mutex_init (pthread_mutex_t *mutex,
+                                const pthread_mutexattr_t *mutex_attr)
+{
+    PTHREAD_ENTRY();
+
+    PTHREAD_CHECK( mutex );
+    
+    pthread_mutexattr_t use_attr;
+
+    // Set up the attributes we are going to use
+    if( mutex_attr == NULL )
+        pthread_mutexattr_init( &use_attr );
+    else use_attr = *mutex_attr;
+
+    // Now translate the POSIX protocol identifier into the eCos one.
+    Cyg_Mutex::cyg_protcol protocol;
+    
+    switch( use_attr.protocol )
+    {
+#if defined(_POSIX_THREAD_PRIO_PROTECT)
+    case PTHREAD_PRIO_PROTECT:
+        protocol = Cyg_Mutex::CEILING;
+        break;
+#endif
+#if defined(_POSIX_THREAD_PRIO_INHERIT)
+    case PTHREAD_PRIO_INHERIT:
+        protocol = Cyg_Mutex::INHERIT;
+        break;
+#endif        
+    case PTHREAD_PRIO_NONE:
+        protocol = Cyg_Mutex::NONE;
+        break;
+
+    default:
+        PTHREAD_RETURN(EINVAL);
+    }
+
+    Cyg_Mutex *mx = new((cyg_uint8 *)mutex) Cyg_Mutex(  protocol );
+
+    mx = mx; // silence compiler warning
+#if defined(_POSIX_THREAD_PRIO_PROTECT)
+    if ( protocol == Cyg_Mutex::CEILING )
+        mx->set_ceiling( use_attr.prioceiling );
+#endif
+    
+    PTHREAD_RETURN(0);
+}
+
+//-----------------------------------------------------------------------------
+// Destroy mutex.
+
+externC int pthread_mutex_destroy (pthread_mutex_t *mutex)
+{
+    PTHREAD_ENTRY();
+
+    int err = ENOERR;
+    
+    PTHREAD_CHECK( mutex );
+
+    Cyg_Mutex *mx = (Cyg_Mutex *)mutex;
+    
+    if( mx->get_owner() != NULL )
+        err = EBUSY;
+    else mx->~Cyg_Mutex();
+    
+    PTHREAD_RETURN(err);
+}
+
+//-----------------------------------------------------------------------------
+// Lock mutex, waiting for it if necessary.
+
+externC int pthread_mutex_lock (pthread_mutex_t *mutex)
+{
+    PTHREAD_ENTRY();
+
+    PTHREAD_CHECK( mutex );
+
+    Cyg_Mutex *mx = (Cyg_Mutex *)mutex;
+
+    if( mx->get_owner() == Cyg_Thread::self() )
+        PTHREAD_RETURN(EDEADLK);
+    
+    // Loop here until we acquire the mutex. Even if we are kicked out
+    // of the wait by a signal or release we must retry.
+    while( !mx->lock() )
+        continue;
+    
+    PTHREAD_RETURN(0);
+}
+
+//-----------------------------------------------------------------------------
+// Try to lock mutex.
+
+externC int pthread_mutex_trylock (pthread_mutex_t *mutex)
+{
+    PTHREAD_ENTRY();
+
+    PTHREAD_CHECK( mutex );
+    
+    Cyg_Mutex *mx = (Cyg_Mutex *)mutex;
+
+    if( mx->get_owner() == Cyg_Thread::self() )
+        PTHREAD_RETURN(EDEADLK);
+    
+    if( mx->trylock() )
+        PTHREAD_RETURN(0);
+
+    PTHREAD_RETURN(EBUSY);
+}
+
+
+//-----------------------------------------------------------------------------
+// Unlock mutex.
+
+externC int pthread_mutex_unlock (pthread_mutex_t *mutex)
+{
+    PTHREAD_ENTRY();
+
+    PTHREAD_CHECK( mutex );
+    
+    Cyg_Mutex *mx = (Cyg_Mutex *)mutex;
+
+    mx->unlock();
+    
+    PTHREAD_RETURN(0);
+}
+
+
+//=============================================================================
+// Condition Variables
+
+//-----------------------------------------------------------------------------
+// Attribute manipulation functions
+// We do not actually support any attributes at present, so these do nothing.
+
+//-----------------------------------------------------------------------------
+// Initialize condition variable attributes
+
+externC int pthread_condattr_init (pthread_condattr_t *attr)
+{
+    PTHREAD_ENTRY();
+    
+    PTHREAD_CHECK(attr);
+
+    // There are no condition variable attributes at present
+    
+    PTHREAD_RETURN(0);
+}
+
+//-----------------------------------------------------------------------------
+// Destroy condition variable attributes
+
+externC int pthread_condattr_destroy (pthread_condattr_t *attr)
+{
+    PTHREAD_ENTRY();
+    
+    PTHREAD_CHECK(attr);
+
+    // nothing to do here...
+    
+    PTHREAD_RETURN(0);
+}
+
+//-----------------------------------------------------------------------------
+// Condition variable functions
+
+//-----------------------------------------------------------------------------
+// Initialize condition variable.
+
+externC int pthread_cond_init (pthread_cond_t *cond,
+                               const pthread_condattr_t *attr)
+{
+    PTHREAD_ENTRY();
+
+    PTHREAD_CHECK( cond );
+
+    Cyg_Condition_Variable *cv =
+        new((cyg_uint8 *)cond) Cyg_Condition_Variable();
+
+    cv = cv;
+    
+    PTHREAD_RETURN(0);
+}
+
+//-----------------------------------------------------------------------------
+// Destroy condition variable.
+
+externC int pthread_cond_destroy (pthread_cond_t *cond)
+{
+    PTHREAD_ENTRY();
+
+    PTHREAD_CHECK( cond );
+
+    ((Cyg_Condition_Variable *)cond)->~Cyg_Condition_Variable();
+    
+    PTHREAD_RETURN(0);
+}
+
+//-----------------------------------------------------------------------------
+// Wake up one thread waiting for condition variable
+
+externC int pthread_cond_signal (pthread_cond_t *cond)
+{
+    PTHREAD_ENTRY();
+
+    PTHREAD_CHECK( cond );
+
+    ((Cyg_Condition_Variable *)cond)->signal();
+    
+    PTHREAD_RETURN(0);
+}
+
+//-----------------------------------------------------------------------------
+// Wake up all threads waiting for condition variable
+
+externC int pthread_cond_broadcast (pthread_cond_t *cond)
+{
+    PTHREAD_ENTRY();
+
+    PTHREAD_CHECK( cond );
+
+    ((Cyg_Condition_Variable *)cond)->broadcast();
+    
+    PTHREAD_RETURN(0);
+}
+
+//-----------------------------------------------------------------------------
+// Block on condition variable until signalled. The mutex is
+// assumed to be locked before this call, will be unlocked
+// during the wait, and will be re-locked on wakeup.
+
+externC int pthread_cond_wait (pthread_cond_t *cond,
+                               pthread_mutex_t *mutex)
+{
+    PTHREAD_ENTRY();
+
+    // check for cancellation first.
+    PTHREAD_TESTCANCEL();
+
+    PTHREAD_CHECK( cond );
+    PTHREAD_CHECK( mutex );    
+
+    ((Cyg_Condition_Variable *)cond)->wait( *(Cyg_Mutex *)mutex );
+    
+    // check if we were woken because we were being cancelled
+    PTHREAD_TESTCANCEL();
+
+    PTHREAD_RETURN(0);
+}
+
+//-----------------------------------------------------------------------------
+// Block on condition variable until signalled, or the timeout expires.
+
+externC int pthread_cond_timedwait (pthread_cond_t *cond,
+                                    pthread_mutex_t *mutex,
+                                    const struct timespec *abstime)
+{
+    PTHREAD_ENTRY();
+
+    // check for cancellation first.
+    PTHREAD_TESTCANCEL();
+
+    PTHREAD_CHECK( cond );
+    PTHREAD_CHECK( mutex );    
+    PTHREAD_CHECK( abstime );    
+
+    cyg_tick_count ticks;
+    struct Cyg_Clock::converter ns_converter, sec_converter;
+    
+    Cyg_Clock::real_time_clock->get_other_to_clock_converter( 1, &ns_converter );
+    Cyg_Clock::real_time_clock->get_other_to_clock_converter( 1000000000, &sec_converter );
+
+    ticks = Cyg_Clock::convert( abstime->tv_sec, &sec_converter );
+    ticks += Cyg_Clock::convert( abstime->tv_nsec, &ns_converter );
+    
+    ((Cyg_Condition_Variable *)cond)->wait( *(Cyg_Mutex *)mutex, ticks );
+    
+    // check if we were woken because we were being cancelled
+    PTHREAD_TESTCANCEL();
+
+    if ( Cyg_Thread::self()->get_wake_reason() == Cyg_Thread::TIMEOUT )
+        PTHREAD_RETURN(ETIMEDOUT);
+    else
+        PTHREAD_RETURN(0);
+}
+
+// -------------------------------------------------------------------------
+// EOF mutex.cxx
--- a/packages/compat/posix/current/src/pprivate.h
+++ b/packages/compat/posix/current/src/pprivate.h
@@ -25,7 +25,7 @@
 //                                                                          
 // The Initial Developer of the Original Code is Red Hat.                   
 // Portions created by Red Hat are                                          
-// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.      
 // All Rights Reserved.                                                     
 // -------------------------------------------                              
 //                                                                          
@@ -82,6 +82,7 @@
 // This is pointed to by the CYGNUM_KERNEL_THREADS_DATA_POSIX entry of the
 // per-thread data.
 
+#ifdef CYGPKG_POSIX_PTHREAD
 typedef struct
 {
     unsigned int        state:4,                // Thread state
@@ -133,6 +134,45 @@ typedef struct
                                         // to be joined
 #define PTHREAD_STATE_EXITED    4       // The thread has exited and is ready to
                                         // be reaped
+#endif // ifdef CYGPKG_POSIX_PTHREAD
+//-----------------------------------------------------------------------------
+// Internal definitions
+
+// Handle entry to a pthread package function. 
+#define PTHREAD_ENTRY() CYG_REPORT_FUNCTYPE( "returning %d" )
+
+// Handle entry to a pthread package function with no args. 
+#define PTHREAD_ENTRY_VOID() CYG_REPORT_FUNCTION()
+
+// Do a pthread package defined return. This requires the error code to be
+// returned as the result of the function. This also gives us a place to
+// put any generic tidyup handling needed for things like signal delivery
+// and cancellation.
+#define PTHREAD_RETURN(err)                     \
+CYG_MACRO_START                                 \
+    CYG_REPORT_RETVAL( err );                   \
+    return err;                                 \
+CYG_MACRO_END
+
+// A void variant of the above.
+#define PTHREAD_RETURN_VOID                     \
+CYG_MACRO_START                                 \
+    CYG_REPORT_RETURN();                        \
+    return;                                     \
+CYG_MACRO_END
+
+// Check that a pointer passed in as an argument is valid and return
+// EINVAL if it is not. This should be used to check pointers that are
+// required to be valid. Pointers that may optionally be NULL should
+// be checked within the function.
+#define PTHREAD_CHECK(ptr) if( (ptr) == NULL ) PTHREAD_RETURN(EINVAL);
+
+#ifdef CYGPKG_POSIX_PTHREAD
+# define PTHREAD_TESTCANCEL() pthread_testcancel()
+#else
+# define PTHREAD_TESTCANCEL()
+#endif
+
 //-----------------------------------------------------------------------------
 // Priority translation.
 // eCos priorities run from 0 as the highest to 31 as the lowest. POSIX priorities
@@ -152,6 +192,7 @@ extern Cyg_Mutex pthread_mutex;
 //-----------------------------------------------------------------------------
 // Functions exported by pthread.cxx to the other parts of the POSIX subsystem.
 
+#ifdef CYGPKG_POSIX_PTHREAD
 externC void cyg_posix_pthread_start( void );
 
 externC pthread_info *pthread_self_info(void);
@@ -159,10 +200,12 @@ externC pthread_info *pthread_self_info(
 externC pthread_info *pthread_info_id( pthread_t id );
 
 externC void cyg_posix_pthread_release_thread( sigset_t *mask );
+#endif
 
 //-----------------------------------------------------------------------------
 // Functions exported by signal.cxx to the other parts of the POSIX subsystem.
 
+#ifdef CYGPKG_POSIX_SIGNALS
 externC void cyg_posix_signal_start();
 
 externC void cyg_posix_signal_asr(pthread_info *self);
@@ -176,10 +219,12 @@ externC void cyg_posix_thread_siginit( p
                                        pthread_info *parentthread );
 
 externC void cyg_posix_thread_sigdestroy( pthread_info *thread );
+#endif
 
 //-----------------------------------------------------------------------------
 // Functions exported by time.cxx to other parts of the POSIX subsystem.
 
+#ifdef CYGPKG_POSIX_TIMERS
 externC void cyg_posix_clock_start();
 
 externC cyg_tick_count cyg_timespec_to_ticks( const struct timespec *tp,
@@ -188,15 +233,18 @@ externC cyg_tick_count cyg_timespec_to_t
 externC void cyg_ticks_to_timespec( cyg_tick_count ticks, struct timespec *tp );
 
 externC void cyg_posix_timer_asr( pthread_info *self );
+#endif
 
 //-----------------------------------------------------------------------------
 // Functions exported by except.cxx
 
+#ifdef CYGPKG_POSIX_SIGNALS
 externC void cyg_posix_exception_start();
 
 externC void cyg_pthread_exception_init(pthread_info *thread);
 
 externC void cyg_pthread_exception_destroy(pthread_info *thread);
+#endif
 
 //-----------------------------------------------------------------------------
 #endif // ifndef CYGONCE_PPRIVATE_H
--- a/packages/compat/posix/current/src/pthread.cxx
+++ b/packages/compat/posix/current/src/pthread.cxx
@@ -60,7 +60,6 @@
 
 #include <cyg/kernel/sched.hxx>        // scheduler definitions
 #include <cyg/kernel/thread.hxx>       // thread definitions
-#include <cyg/kernel/mutex.hxx>        // mutex definitions
 #include <cyg/kernel/clock.hxx>        // clock definitions
 
 #include <cyg/kernel/sched.inl>        // scheduler inlines
@@ -84,39 +83,6 @@
 #error POSIX pthreads need per-thread data
 #endif
 
-//-----------------------------------------------------------------------------
-// Internal definitions
-
-// Handle entry to a pthread package function. 
-#define PTHREAD_ENTRY() CYG_REPORT_FUNCTYPE( "returning %d" )
-
-// Handle entry to a pthread package function with no args. 
-#define PTHREAD_ENTRY_VOID() CYG_REPORT_FUNCTION()
-
-// Do a pthread package defined return. This requires the error code to be
-// returned as the result of the function. This also gives us a place to
-// put any generic tidyup handling needed for things like signal delivery
-// and cancellation.
-#define PTHREAD_RETURN(err)                     \
-CYG_MACRO_START                                 \
-    CYG_REPORT_RETVAL( err );                   \
-    return err;                                 \
-CYG_MACRO_END
-
-// A void variant of the above.
-#define PTHREAD_RETURN_VOID                     \
-CYG_MACRO_START                                 \
-    CYG_REPORT_RETURN();                        \
-    return;                                     \
-CYG_MACRO_END
-
-// Check that a pointer passed in as an argument is valid and return
-// EINVAL if it is not. This should be used to check pointers that are
-// required to be valid. Pointers that may optionally be NULL should
-// be checked within the function.
-#define PTHREAD_CHECK(ptr) if( (ptr) == NULL ) PTHREAD_RETURN(EINVAL);
-
-
 //=============================================================================
 // Internal data structures
 
@@ -1290,451 +1256,6 @@ externC int pthread_getschedparam (pthre
 
 
 //=============================================================================
-// Mutexes
-
-//-----------------------------------------------------------------------------
-// Mutex attributes manipulation functions
-
-//-----------------------------------------------------------------------------
-// Initialize attribute object
-
-externC int pthread_mutexattr_init ( pthread_mutexattr_t *attr)
-{
-    PTHREAD_ENTRY();
-    
-    PTHREAD_CHECK(attr);
-
-    attr->protocol      = PTHREAD_PRIO_NONE;
-    attr->prioceiling   = 0;
-    
-    PTHREAD_RETURN(0);
-}
-
-//-----------------------------------------------------------------------------
-// Destroy attribute object
-
-externC int pthread_mutexattr_destroy ( pthread_mutexattr_t *attr)
-{
-    PTHREAD_ENTRY();
-    
-    PTHREAD_CHECK(attr);
-
-    // Nothing to do here...
-    
-    PTHREAD_RETURN(0);
-}
-
-//-----------------------------------------------------------------------------
-// Optional functions depending on priority inversion protection options.
-
-#if defined(_POSIX_THREAD_PRIO_INHERIT) || defined(_POSIX_THREAD_PRIO_PROTECT)
-
-// Set priority inversion protection protocol
-externC int pthread_mutexattr_setprotocol ( pthread_mutexattr_t *attr,
-                                            int protocol)
-{
-    PTHREAD_ENTRY();
-    
-    PTHREAD_CHECK(attr);
-
-    switch( protocol )
-    {
-    case PTHREAD_PRIO_NONE:
-#if defined(_POSIX_THREAD_PRIO_INHERIT)        
-    case PTHREAD_PRIO_INHERIT:
-#endif
-#if defined(_POSIX_THREAD_PRIO_PROTECT)
-    case PTHREAD_PRIO_PROTECT:
-#endif        
-        attr->protocol = protocol;
-        PTHREAD_RETURN(0);
-
-    default:
-        PTHREAD_RETURN(EINVAL);
-    }
-    
-    PTHREAD_RETURN(0);
-}
-
-// Get priority inversion protection protocol
-externC int pthread_mutexattr_getprotocol ( pthread_mutexattr_t *attr,
-                                            int *protocol)
-{
-    PTHREAD_ENTRY();
-    
-    PTHREAD_CHECK(attr);
-
-    if( protocol != NULL )
-        *protocol = attr->protocol;
-    
-    PTHREAD_RETURN(0);
-}
-
-#if defined(_POSIX_THREAD_PRIO_PROTECT)
-
-// Set priority for priority ceiling protocol
-externC int pthread_mutexattr_setprioceiling ( pthread_mutexattr_t *attr,
-                                               int prioceiling)
-{
-    PTHREAD_ENTRY();
-    
-    PTHREAD_CHECK(attr);
-
-    
-    attr->prioceiling = prioceiling;
-    
-    PTHREAD_RETURN(0);
-}
-
-// Get priority for priority ceiling protocol
-externC int pthread_mutexattr_getprioceiling ( pthread_mutexattr_t *attr,
-                                               int *prioceiling)
-{
-    PTHREAD_ENTRY();
-    
-    PTHREAD_CHECK(attr);
-
-    if( prioceiling != NULL )
-        *prioceiling = attr->prioceiling;
-    
-    PTHREAD_RETURN(0);
-}
-
-// Set priority ceiling of given mutex, returning old ceiling.
-externC int pthread_mutex_setprioceiling( pthread_mutex_t *mutex,
-                                          int prioceiling,
-                                          int *old_ceiling)
-{
-    PTHREAD_ENTRY();
-    
-    PTHREAD_CHECK(mutex);
-
-    pthread_mutex_lock( mutex );
-
-    Cyg_Mutex *mx = (Cyg_Mutex *)mutex;
-
-    if( old_ceiling != NULL )
-        *old_ceiling = mx->get_ceiling();
-    
-    mx->set_ceiling( prioceiling );
-    
-    pthread_mutex_unlock( mutex );
-
-    PTHREAD_RETURN(0);
-}
-
-// Get priority ceiling of given mutex
-externC int pthread_mutex_getprioceiling( pthread_mutex_t *mutex,
-                                          int *prioceiling)
-{
-    PTHREAD_ENTRY();
-    
-    PTHREAD_CHECK(mutex);
-
-    Cyg_Mutex *mx = (Cyg_Mutex *)mutex;
-
-    if( prioceiling != NULL )
-        *prioceiling = mx->get_ceiling();
-        
-    PTHREAD_RETURN(0);
-}
-
-#endif // defined(_POSIX_THREAD_PRIO_PROTECT)
-
-#endif // defined(_POSIX_THREAD_PRIO_INHERIT) || defined(_POSIX_THREAD_PRIO_PROTECT)
-
-//-----------------------------------------------------------------------------
-// Mutex functions
-
-//-----------------------------------------------------------------------------
-// Initialize mutex. If mutex_attr is NULL, use default attributes.
-
-externC int pthread_mutex_init (pthread_mutex_t *mutex,
-                                const pthread_mutexattr_t *mutex_attr)
-{
-    PTHREAD_ENTRY();
-
-    PTHREAD_CHECK( mutex );
-    
-    pthread_mutexattr_t use_attr;
-
-    // Set up the attributes we are going to use
-    if( mutex_attr == NULL )
-        pthread_mutexattr_init( &use_attr );
-    else use_attr = *mutex_attr;
-
-    // Now translate the POSIX protocol identifier into the eCos one.
-    Cyg_Mutex::cyg_protcol protocol;
-    
-    switch( use_attr.protocol )
-    {
-#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING        
-    case PTHREAD_PRIO_PROTECT:
-        protocol = Cyg_Mutex::CEILING;
-        break;
-#endif
-#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT        
-    case PTHREAD_PRIO_INHERIT:
-        protocol = Cyg_Mutex::INHERIT;
-        break;
-#endif        
-    case PTHREAD_PRIO_NONE:
-        protocol = Cyg_Mutex::NONE;
-        break;
-
-    default:
-        PTHREAD_RETURN(EINVAL);
-    }
-
-    Cyg_Mutex *mx = new((cyg_uint8 *)mutex) Cyg_Mutex(  protocol );
-
-    if ( protocol == Cyg_Mutex::CEILING )
-        mx->set_ceiling( use_attr.prioceiling );
-    
-    PTHREAD_RETURN(0);
-}
-
-//-----------------------------------------------------------------------------
-// Destroy mutex.
-
-externC int pthread_mutex_destroy (pthread_mutex_t *mutex)
-{
-    PTHREAD_ENTRY();
-
-    int err = ENOERR;
-    
-    PTHREAD_CHECK( mutex );
-
-    Cyg_Mutex *mx = (Cyg_Mutex *)mutex;
-    
-    if( mx->get_owner() != NULL )
-        err = EBUSY;
-    else mx->~Cyg_Mutex();
-    
-    PTHREAD_RETURN(err);
-}
-
-//-----------------------------------------------------------------------------
-// Lock mutex, waiting for it if necessary.
-
-externC int pthread_mutex_lock (pthread_mutex_t *mutex)
-{
-    PTHREAD_ENTRY();
-
-    PTHREAD_CHECK( mutex );
-
-    Cyg_Mutex *mx = (Cyg_Mutex *)mutex;
-
-    if( mx->get_owner() == Cyg_Thread::self() )
-        PTHREAD_RETURN(EDEADLK);
-    
-    // Loop here until we acquire the mutex. Even if we are kicked out
-    // of the wait by a signal or release we must retry.
-    while( !mx->lock() )
-        continue;
-    
-    PTHREAD_RETURN(0);
-}
-
-//-----------------------------------------------------------------------------
-// Try to lock mutex.
-
-externC int pthread_mutex_trylock (pthread_mutex_t *mutex)
-{
-    PTHREAD_ENTRY();
-
-    PTHREAD_CHECK( mutex );
-    
-    Cyg_Mutex *mx = (Cyg_Mutex *)mutex;
-
-    if( mx->get_owner() == Cyg_Thread::self() )
-        PTHREAD_RETURN(EDEADLK);
-    
-    if( mx->trylock() )
-        PTHREAD_RETURN(0);
-
-    PTHREAD_RETURN(EBUSY);
-}
-
-
-//-----------------------------------------------------------------------------
-// Unlock mutex.
-
-externC int pthread_mutex_unlock (pthread_mutex_t *mutex)
-{
-    PTHREAD_ENTRY();
-
-    PTHREAD_CHECK( mutex );
-    
-    Cyg_Mutex *mx = (Cyg_Mutex *)mutex;
-
-    mx->unlock();
-    
-    PTHREAD_RETURN(0);
-}
-
-
-//=============================================================================
-// Condition Variables
-
-//-----------------------------------------------------------------------------
-// Attribute manipulation functions
-// We do not actually support any attributes at present, so these do nothing.
-
-//-----------------------------------------------------------------------------
-// Initialize condition variable attributes
-
-externC int pthread_condattr_init (pthread_condattr_t *attr)
-{
-    PTHREAD_ENTRY();
-    
-    PTHREAD_CHECK(attr);
-
-    // There are no condition variable attributes at present
-    
-    PTHREAD_RETURN(0);
-}
-
-//-----------------------------------------------------------------------------
-// Destroy condition variable attributes
-
-externC int pthread_condattr_destroy (pthread_condattr_t *attr)
-{
-    PTHREAD_ENTRY();
-    
-    PTHREAD_CHECK(attr);
-
-    // nothing to do here...
-    
-    PTHREAD_RETURN(0);
-}
-
-//-----------------------------------------------------------------------------
-// Condition variable functions
-
-//-----------------------------------------------------------------------------
-// Initialize condition variable.
-
-externC int pthread_cond_init (pthread_cond_t *cond,
-                               const pthread_condattr_t *attr)
-{
-    PTHREAD_ENTRY();
-
-    PTHREAD_CHECK( cond );
-
-    Cyg_Condition_Variable *cv =
-        new((cyg_uint8 *)cond) Cyg_Condition_Variable();
-
-    cv = cv;
-    
-    PTHREAD_RETURN(0);
-}
-
-//-----------------------------------------------------------------------------
-// Destroy condition variable.
-
-externC int pthread_cond_destroy (pthread_cond_t *cond)
-{
-    PTHREAD_ENTRY();
-
-    PTHREAD_CHECK( cond );
-
-    ((Cyg_Condition_Variable *)cond)->~Cyg_Condition_Variable();
-    
-    PTHREAD_RETURN(0);
-}
-
-//-----------------------------------------------------------------------------
-// Wake up one thread waiting for condition variable
-
-externC int pthread_cond_signal (pthread_cond_t *cond)
-{
-    PTHREAD_ENTRY();
-
-    PTHREAD_CHECK( cond );
-
-    ((Cyg_Condition_Variable *)cond)->signal();
-    
-    PTHREAD_RETURN(0);
-}
-
-//-----------------------------------------------------------------------------
-// Wake up all threads waiting for condition variable
-
-externC int pthread_cond_broadcast (pthread_cond_t *cond)
-{
-    PTHREAD_ENTRY();
-
-    PTHREAD_CHECK( cond );
-
-    ((Cyg_Condition_Variable *)cond)->broadcast();
-    
-    PTHREAD_RETURN(0);
-}
-
-//-----------------------------------------------------------------------------
-// Block on condition variable until signalled. The mutex is
-// assumed to be locked before this call, will be unlocked
-// during the wait, and will be re-locked on wakeup.
-
-externC int pthread_cond_wait (pthread_cond_t *cond,
-                               pthread_mutex_t *mutex)
-{
-    PTHREAD_ENTRY();
-
-    // check for cancellation first.
-    pthread_testcancel();
-
-    PTHREAD_CHECK( cond );
-    PTHREAD_CHECK( mutex );    
-
-    ((Cyg_Condition_Variable *)cond)->wait( *(Cyg_Mutex *)mutex );
-    
-    // check if we were woken because we were being cancelled
-    pthread_testcancel();
-
-    PTHREAD_RETURN(0);
-}
-
-//-----------------------------------------------------------------------------
-// Block on condition variable until signalled, or the timeout expires.
-
-externC int pthread_cond_timedwait (pthread_cond_t *cond,
-                                    pthread_mutex_t *mutex,
-                                    const struct timespec *abstime)
-{
-    PTHREAD_ENTRY();
-
-    // check for cancellation first.
-    pthread_testcancel();
-
-    PTHREAD_CHECK( cond );
-    PTHREAD_CHECK( mutex );    
-    PTHREAD_CHECK( abstime );    
-
-    cyg_tick_count ticks;
-    struct Cyg_Clock::converter ns_converter, sec_converter;
-    
-    Cyg_Clock::real_time_clock->get_other_to_clock_converter( 1, &ns_converter );
-    Cyg_Clock::real_time_clock->get_other_to_clock_converter( 1000000000, &sec_converter );
-
-    ticks = Cyg_Clock::convert( abstime->tv_sec, &sec_converter );
-    ticks += Cyg_Clock::convert( abstime->tv_nsec, &ns_converter );
-    
-    ((Cyg_Condition_Variable *)cond)->wait( *(Cyg_Mutex *)mutex, ticks );
-    
-    // check if we were woken because we were being cancelled
-    pthread_testcancel();
-
-    pthread_info *self = pthread_self_info();
-
-    if ( self->thread->get_wake_reason() == Cyg_Thread::TIMEOUT )
-        PTHREAD_RETURN(ETIMEDOUT);
-    else
-        PTHREAD_RETURN(0);
-}
-
-//=============================================================================
 // Dynamic package initialization
 // Call init_routine just the once per control variable.
 
--- a/packages/compat/posix/current/src/signal.cxx
+++ b/packages/compat/posix/current/src/signal.cxx
@@ -63,8 +63,9 @@
 #include <unistd.h>                     // _exit
 
 #include <cyg/kernel/clock.hxx>
-
+#include <cyg/kernel/thread.hxx>
 #include <cyg/kernel/clock.inl>
+#include <cyg/kernel/thread.inl>
 
 // -------------------------------------------------------------------------
 // Internal definitions
@@ -241,12 +242,29 @@ cyg_bool cyg_sigqueue( const struct sige
     // else A non-queuable signal, just set it pending
 
     if( thread != NULL )
+    {
         sigaddset( &thread->sigpending, signo );
-    else sigaddset( &sig_pending, signo );
+        // just wake the thread up now if it's blocked somewhere
+        if ((thread->sigpending & ~thread->sigmask) != 0)
+        {
+            thread->thread->set_asr_pending();
+            thread->thread->release();
+        }
+    }
+    else
+    {
+        sigaddset( &sig_pending, signo );
+        // Wake up any threads in sigsuspend() and sigwait().
+        if (!signal_sigwait.get_queue()->empty())
+        {
+            signal_sigwait.broadcast();
+        } 
+        else
+        {
+            cyg_posix_pthread_release_thread( &sig_pending );
+        }
+    }
 
-    // Wake up any threads in sigsuspend() and sigwait().
-    signal_sigwait.broadcast();
-    
     if( !locked ) signal_mutex.unlock();
     
     return true;
@@ -648,7 +666,6 @@ externC int pthread_sigmask (int how, co
     SIGNAL_ENTRY();
 
     pthread_info *self = pthread_self_info();
-
     // Save old set
     if( oset != NULL )
         *oset = self->sigmask;
@@ -1124,11 +1141,11 @@ externC int raise(int sig)
     if( val == 0 )
         val = 1;
 
-    if( *(int *)&env[sizeof(hal_jmp_buf)] )
-        pthread_sigmask( SIG_SETMASK, (sigset_t *)&(env)[sizeof(hal_jmp_buf)+sizeof(int)], NULL );
+    if( env[0].__savemask )
+        pthread_sigmask( SIG_SETMASK, &env[0].__sigsavemask, NULL );
     
     HAL_REORDER_BARRIER(); // prevent any chance of optimisation re-ordering
-    hal_longjmp( (hal_jmp_buf)env, val );
+    hal_longjmp( env[0].__jmp_buf, val );
     HAL_REORDER_BARRIER(); // prevent any chance of optimisation re-ordering
 
 #ifdef CYGDBG_USE_ASSERTS
--- a/packages/compat/posix/current/tests/mutex3.c
+++ b/packages/compat/posix/current/tests/mutex3.c
@@ -23,7 +23,7 @@
 //                                                                          
 // The Initial Developer of the Original Code is Red Hat.                   
 // Portions created by Red Hat are                                          
-// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.      
 // All Rights Reserved.                                                     
 // -------------------------------------------                              
 //                                                                          
@@ -32,7 +32,7 @@
 //#####DESCRIPTIONBEGIN####
 //
 // Author(s):     hmt
-// Contributors:  hmt, nickg
+// Contributors:  hmt, nickg, jlarmour
 // Date:          2000-01-06
 // Description:   Tests mutex priority inheritance. This is simply a translation
 //                of the similarly named kernel test to the POSIX API
@@ -40,20 +40,15 @@
 
 // ------------------------------------------------------------------------
 
-#include <sys/types.h>
-#include <pthread.h>
-#include <semaphore.h>
-#include <time.h>
-
+#include <cyg/infra/testcase.h>
+#include <pkgconf/posix.h>
+#include <pkgconf/system.h>
+#ifdef CYGPKG_KERNEL
+#include <pkgconf/kernel.h>
+#endif
 
-#include <cyg/infra/testcase.h>
-
-#include <cyg/infra/cyg_ass.h>
-#include <cyg/infra/cyg_trac.h>
-#include <cyg/infra/diag.h>             // diag_printf
-
-#include <cyg/kernel/kapi.h>            // Some extras
-
+#if !defined(CYGPKG_POSIX_PTHREAD)
+#define NA_MSG "POSIX threads not enabled"
 
 // ------------------------------------------------------------------------
 //
@@ -61,8 +56,35 @@
 // should manifest as having no priority inheritance, but otherwise fine,
 // so the test should work correctly.
 
-#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) &&    \
-    defined(_POSIX_THREAD_PRIO_INHERIT)
+#elif !defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
+#define NA_MSG "No POSIX thread priority scheduling enabled"
+#elif !defined(_POSIX_THREAD_PRIO_INHERIT)
+#define NA_MSG "No POSIX thread priority inheritance enabled"
+#elif !defined(CYGFUN_KERNEL_API_C)
+#define NA_MSG "Kernel C API not enabled"
+#elif defined(CYGPKG_KERNEL_SMP_SUPPORT)
+#define NA_MSG "Test cannot run with SMP support"
+#endif
+
+#ifdef NA_MSG
+void
+cyg_start(void)
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA(NA_MSG);
+}
+#else
+
+#include <sys/types.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <time.h>
+
+#include <cyg/infra/cyg_ass.h>
+#include <cyg/infra/cyg_trac.h>
+#include <cyg/infra/diag.h>             // diag_printf
+
+#include <cyg/kernel/kapi.h>            // Some extras
 
 // ------------------------------------------------------------------------
 // Management functions
@@ -474,19 +496,6 @@ main( int argc, char **argv )
     for(;;) sem_wait( &main_sem );
 }
 
-#else // CYGVAR_KERNEL_COUNTERS_CLOCK &c
-
-externC int
-main( int argc, char **argv )
-{
-    CYG_TEST_INIT();
-    CYG_TEST_PASS_FINISH("Mutex3 test requires:\n"
-                         "CYGVAR_KERNEL_COUNTERS_CLOCK &&\n"
-                         "(CYGNUM_KERNEL_SCHED_PRIORITIES > 20)\n");
-}
-#endif // CYGVAR_KERNEL_COUNTERS_CLOCK &c
-
-
 // ------------------------------------------------------------------------
 // Documentation: enclosed is the design of this test.
 //
@@ -642,4 +651,6 @@ main( int argc, char **argv )
 // 
 // ------------------------------------------------------------------------
 
+#endif
+
 // EOF mutex3.cxx
--- a/packages/compat/posix/current/tests/pthread1.c
+++ b/packages/compat/posix/current/tests/pthread1.c
@@ -23,7 +23,7 @@
 //                                                                          
 // The Initial Developer of the Original Code is Red Hat.                   
 // Portions created by Red Hat are                                          
-// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.      
 // All Rights Reserved.                                                     
 // -------------------------------------------                              
 //                                                                          
@@ -39,11 +39,25 @@
 //####DESCRIPTIONEND####
 //==========================================================================
 
+#include <cyg/infra/testcase.h>
+#include <pkgconf/posix.h>
+
+#ifndef CYGPKG_POSIX_PTHREAD
+#define NA_MSG "POSIX threads not enabled"
+#endif
+
+#ifdef NA_MSG
+void
+cyg_start(void)
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA(NA_MSG);
+}
+#else
+
 #include <sys/types.h>
 #include <pthread.h>
 
-#include <cyg/infra/testcase.h>
-
 //--------------------------------------------------------------------------
 // Thread stack.
 
@@ -90,5 +104,7 @@ int main(int argc, char **argv)
         CYG_TEST_FAIL_FINISH( "pthread1" );
 }
 
+#endif
+
 //--------------------------------------------------------------------------
 // end of pthread1.c
--- a/packages/compat/posix/current/tests/pthread2.c
+++ b/packages/compat/posix/current/tests/pthread2.c
@@ -23,7 +23,7 @@
 //                                                                          
 // The Initial Developer of the Original Code is Red Hat.                   
 // Portions created by Red Hat are                                          
-// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.      
 // All Rights Reserved.                                                     
 // -------------------------------------------                              
 //                                                                          
@@ -39,11 +39,25 @@
 //####DESCRIPTIONEND####
 //==========================================================================
 
+#include <cyg/infra/testcase.h>
+#include <pkgconf/posix.h>
+
+#ifndef CYGPKG_POSIX_PTHREAD
+#define NA_MSG "POSIX threads not enabled"
+#endif
+
+#ifdef NA_MSG
+void
+cyg_start(void)
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA(NA_MSG);
+}
+#else
+
 #include <sys/types.h>
 #include <pthread.h>
 
-#include <cyg/infra/testcase.h>
-
 //--------------------------------------------------------------------------
 // Thread stack.
 
@@ -147,5 +161,7 @@ int main(int argc, char **argv)
         
 }
 
+#endif
+
 //--------------------------------------------------------------------------
 // end of pthread2.c
--- a/packages/compat/posix/current/tests/pthread3.c
+++ b/packages/compat/posix/current/tests/pthread3.c
@@ -23,7 +23,7 @@
 //                                                                          
 // The Initial Developer of the Original Code is Red Hat.                   
 // Portions created by Red Hat are                                          
-// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.      
 // All Rights Reserved.                                                     
 // -------------------------------------------                              
 //                                                                          
@@ -39,12 +39,26 @@
 //####DESCRIPTIONEND####
 //==========================================================================
 
+#include <cyg/infra/testcase.h>
+#include <pkgconf/posix.h>
+
+#ifndef CYGPKG_POSIX_PTHREAD
+#define NA_MSG "POSIX threads not enabled"
+#endif
+
+#ifdef NA_MSG
+void
+cyg_start(void)
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA(NA_MSG);
+}
+#else
+
 #include <sys/types.h>
 #include <pthread.h>
 #include <unistd.h> // sleep()
 
-#include <cyg/infra/testcase.h>
-
 //--------------------------------------------------------------------------
 // Thread info
 
@@ -185,7 +199,7 @@ void *pthread_entry3( void *arg)
 
 int main(int argc, char **argv)
 {
-    int i;
+    int i, j;
     int ret;
     void *retval[NTHREADS];
 
@@ -207,12 +221,17 @@ int main(int argc, char **argv)
         CYG_TEST_CHECK( ret == 0, "pthread_create() returned error");
     }
 
-    // Let the threads get going
+    // Let the threads get going    
     for ( i = 0; i < NTHREADS ; i++ ) {
         while ( thread_ready[i] == false )
             sched_yield();
     }
 
+    // Now wait a bit to be sure that the other threads have reached
+    // their cancellation points.
+    for ( j = 0; j < 20 ; j++ )
+        sched_yield();
+    
     // Now cancel them
     for( i = 0; i < NTHREADS; i++ )    
         pthread_cancel( thread[i] );
@@ -235,5 +254,7 @@ int main(int argc, char **argv)
         
 }
 
+#endif
+
 //--------------------------------------------------------------------------
 // end of pthread3.c
--- a/packages/compat/posix/current/tests/signal1.c
+++ b/packages/compat/posix/current/tests/signal1.c
@@ -23,7 +23,7 @@
 //                                                                          
 // The Initial Developer of the Original Code is Red Hat.                   
 // Portions created by Red Hat are                                          
-// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.      
 // All Rights Reserved.                                                     
 // -------------------------------------------                              
 //                                                                          
@@ -39,14 +39,30 @@
 //####DESCRIPTIONEND####
 //==========================================================================
 
+#include <cyg/infra/testcase.h>
+#include <pkgconf/posix.h>
+
+#if !defined(CYGPKG_POSIX_SIGNALS)
+#define NA_MSG "POSIX signals not enabled"
+#elif !defined(CYGPKG_POSIX_PTHREAD)
+#define NA_MSG "POSIX threads not enabled"
+#endif
+
+#ifdef NA_MSG
+void
+cyg_start(void)
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA(NA_MSG);
+}
+#else
+
 #include <sys/types.h>
 #include <pthread.h>
 #include <signal.h>
 #include <semaphore.h>
 #include <errno.h>
 
-#include <cyg/infra/testcase.h>
-
 //--------------------------------------------------------------------------
 // Thread stack.
 
@@ -271,5 +287,7 @@ int main(int argc, char **argv)
         CYG_TEST_FAIL_FINISH( "signal1" );
 }
 
+#endif
+
 //--------------------------------------------------------------------------
 // end of signal1.c
--- a/packages/compat/posix/current/tests/sigsetjmp.c
+++ b/packages/compat/posix/current/tests/sigsetjmp.c
@@ -23,7 +23,7 @@
 //                                                                          
 // The Initial Developer of the Original Code is Red Hat.                   
 // Portions created by Red Hat are                                          
-// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.      
 // All Rights Reserved.                                                     
 // -------------------------------------------                              
 //                                                                          
@@ -39,6 +39,24 @@
 //####DESCRIPTIONEND####
 //==========================================================================
 
+#include <cyg/infra/testcase.h>
+#include <pkgconf/posix.h>
+
+#if !defined(CYGPKG_POSIX_SIGNALS)
+#define NA_MSG "POSIX signals not enabled"
+#elif !defined(CYGPKG_POSIX_PTHREAD)
+#define NA_MSG "POSIX threads not enabled"
+#endif
+
+#ifdef NA_MSG
+void
+cyg_start(void)
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA(NA_MSG);
+}
+#else
+
 #include <sys/types.h>
 #include <pthread.h>
 #include <signal.h>
@@ -350,5 +368,7 @@ int main(int argc, char **argv)
     CYG_TEST_PASS_FINISH( "sigsetjmp" );
 }
 
+#endif
+
 //--------------------------------------------------------------------------
 // end of sigsetjmp.c
--- a/packages/compat/posix/current/tests/timer1.c
+++ b/packages/compat/posix/current/tests/timer1.c
@@ -23,7 +23,7 @@
 //                                                                          
 // The Initial Developer of the Original Code is Red Hat.                   
 // Portions created by Red Hat are                                          
-// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.      
 // All Rights Reserved.                                                     
 // -------------------------------------------                              
 //                                                                          
@@ -39,14 +39,30 @@
 //####DESCRIPTIONEND####
 //==========================================================================
 
+#include <cyg/infra/testcase.h>
+#include <pkgconf/posix.h>
+
+#ifndef CYGPKG_POSIX_SIGNALS
+#define NA_MSG "No POSIX signals"
+#elif !defined(CYGPKG_POSIX_TIMERS)
+#define NA_MSG "No POSIX timers"
+#endif
+
+#ifdef NA_MSG
+void
+cyg_start(void)
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA(NA_MSG);
+}
+#else
+
 #include <sys/types.h>
 #include <pthread.h>
 #include <signal.h>
 #include <semaphore.h>
 #include <time.h>
 
-#include <cyg/infra/testcase.h>
-
 //--------------------------------------------------------------------------
 // Thread stack.
 
@@ -312,5 +328,7 @@ int main(int argc, char **argv)
     CYG_TEST_PASS_FINISH( "timer1" );
 }
 
+#endif
+
 //--------------------------------------------------------------------------
 // end of timer1.c
--- a/packages/compat/posix/current/tests/tm_basic.cxx
+++ b/packages/compat/posix/current/tests/tm_basic.cxx
@@ -31,13 +31,48 @@
 //==========================================================================
 //#####DESCRIPTIONBEGIN####
 //
-// Author(s):     gthomas
-// Contributors:  gthomas
+// Author(s):     gthomas,nickg
+// Contributors:  jlarmour
 // Date:          1998-10-19
 // Description:   Very simple kernel timing test
 //####DESCRIPTIONEND####
 //==========================================================================
 
+
+#include <cyg/infra/testcase.h>
+#include <pkgconf/posix.h>
+#include <pkgconf/system.h>
+#ifdef CYGPKG_KERNEL
+#include <pkgconf/kernel.h>
+#endif
+
+#ifndef CYGPKG_POSIX_SIGNALS
+#define NA_MSG "No POSIX signals"
+#elif !defined(CYGPKG_POSIX_TIMERS)
+#define NA_MSG "No POSIX timers"
+#elif !defined(CYGPKG_POSIX_PTHREAD)
+#define NA_MSG "POSIX threads not enabled"
+#elif !defined(CYGFUN_KERNEL_API_C)
+#define NA_MSG "Kernel C API not enabled"
+#elif !defined(CYGSEM_KERNEL_SCHED_MLQUEUE)
+#define NA_MSG "Kernel mlqueue scheduler not enabled"
+#elif !defined(CYGVAR_KERNEL_COUNTERS_CLOCK)
+#define NA_MSG "Kernel clock not enabled"
+#elif CYGNUM_KERNEL_SCHED_PRIORITIES <= 12
+#define NA_MSG "Kernel scheduler properties <= 12"
+#endif
+
+//==========================================================================
+
+#ifdef NA_MSG
+extern "C" void
+cyg_start(void)
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA(NA_MSG);
+}
+#else
+
 #include <pkgconf/kernel.h>
 #include <pkgconf/hal.h>
 
@@ -74,15 +109,6 @@
 
 //==========================================================================
 
-#if defined(CYGPKG_POSIX) &&                    \
-    defined(CYGFUN_KERNEL_API_C) &&             \
-    defined(CYGSEM_KERNEL_SCHED_MLQUEUE) &&     \
-    defined(CYGVAR_KERNEL_COUNTERS_CLOCK) &&    \
-    !defined(CYGDBG_INFRA_DIAG_USE_DEVICE) &&   \
-    (CYGNUM_KERNEL_SCHED_PRIORITIES > 12)
-
-//==========================================================================
-
 // Structure used to keep track of times
 typedef struct fun_times {
     cyg_uint32 start;
@@ -1656,18 +1682,6 @@ int main( int argc, char **argv )
    
 }
 
-#else // CYGFUN_KERNEL_API_C
-
-int main( int argc, char **argv )
-{
-    CYG_TEST_INIT();
-    CYG_TEST_NA("Timing tests require:\n"
-                "CYGFUN_KERNEL_API_C && \n"
-                "CYGSEM_KERNEL_SCHED_MLQUEUE &&\n"
-                "CYGVAR_KERNEL_COUNTERS_CLOCK &&\n"
-                "!CYGDBG_INFRA_DIAG_USE_DEVICE &&\n"
-                "(CYGNUM_KERNEL_SCHED_PRIORITIES > 12)\n");
-}
 #endif // CYGFUN_KERNEL_API_C, etc.
 
 // EOF tm_basic.cxx
--- a/packages/devs/flash/amd/am29xxxxx/current/ChangeLog
+++ b/packages/devs/flash/amd/am29xxxxx/current/ChangeLog
@@ -1,3 +1,7 @@
+2001-08-10  Jesper Skov  <jskov@redhat.com>
+
+	* include/flash_am29xxxxx.inl (flash_hwr_init): Fix block number.
+
 2001-07-26  Jesper Skov  <jskov@redhat.com>
 
 	* include/flash_am29xxxxx.inl: Made code deal with multiple
--- a/packages/devs/flash/amd/am29xxxxx/current/include/flash_am29xxxxx.inl
+++ b/packages/devs/flash/amd/am29xxxxx/current/include/flash_am29xxxxx.inl
@@ -212,7 +212,7 @@ flash_hwr_init(void)
 
     // Hard wired for now
     flash_info.block_size = flash_dev_info->block_size;
-    flash_info.blocks = flash_dev_info->block_count;
+    flash_info.blocks = flash_dev_info->block_count * CYGNUM_FLASH_SERIES;
     flash_info.start = (void *)CYGNUM_FLASH_BASE;
     flash_info.end = (void *)(CYGNUM_FLASH_BASE+ (flash_dev_info->device_size * CYGNUM_FLASH_SERIES));
     return FLASH_ERR_OK;
--- a/packages/devs/flash/arm/iq80310/current/ChangeLog
+++ b/packages/devs/flash/arm/iq80310/current/ChangeLog
@@ -1,3 +1,7 @@
+2001-08-04  Mark Salter  <msalter@redhat.com>
+
+	* src/flash.h (FLASH_P2V): First 4K of flash now mapped at 0xd0000000.
+
 2001-06-11  Gary Thomas  <gthomas@redhat.com>
 
 	* src/iq80310_flash.c: Remove dependency on printf() via user functions.
--- a/packages/devs/flash/arm/iq80310/current/src/flash.h
+++ b/packages/devs/flash/arm/iq80310/current/src/flash.h
@@ -47,7 +47,7 @@
 // First 4K page of flash at physical address zero is
 // virtually mapped at address 0xa0000000.
 #define FLASH_P2V(x) ((volatile unsigned char *)(((unsigned)(x) < 0x1000) ?  \
-                           ((unsigned)(x) | 0xa0000000) :  \
+                           ((unsigned)(x) | 0xd0000000) :  \
                            (unsigned)(x)))
 
 #define FLASH_BOOT_BLOCK_SIZE   0x4000
--- a/packages/devs/flash/intel/28fxxx/current/ChangeLog
+++ b/packages/devs/flash/intel/28fxxx/current/ChangeLog
@@ -1,3 +1,12 @@
+2001-08-10  Jesper Skov  <jskov@redhat.com>
+
+	* cdl/flash_intel_28fxxx.cdl: Added options for variants.
+
+	* include/flash_28fxxx.inl: Support bootblock parts. Support
+	locking. Buffered writes are broken though.
+
+	* include/flash_28fxxx_parts.inl: Created.
+
 2001-06-29  Jesper Skov  <jskov@redhat.com>
 
 	* include/flash_28fxxx.inl: Fix 28F160 block size.
--- a/packages/devs/flash/intel/28fxxx/current/cdl/flash_intel_28fxxx.cdl
+++ b/packages/devs/flash/intel/28fxxx/current/cdl/flash_intel_28fxxx.cdl
@@ -50,4 +50,37 @@ cdl_package CYGPKG_DEVS_FLASH_INTEL_28FX
     implements    CYGHWR_IO_FLASH_DEVICE
 
     include_dir   cyg/io
+
+    requires      { CYGINT_DEVS_FLASH_INTEL_VARIANTS != 0 }
+
+    cdl_interface CYGINT_DEVS_FLASH_INTEL_VARIANTS {
+        display   "Number of included variants"
+    }
+
+    cdl_interface CYGHWR_DEVS_FLASH_INTEL_BUFFERED_WRITES {
+        flavor    booldata
+        display   "Must support buffered writes"
+    }
+
+    cdl_option CYGHWR_DEVS_FLASH_INTEL_28F160S5 {
+        display       "Intel 28F160S5 flash memory support"
+        default_value 0
+        implements    CYGINT_DEVS_FLASH_INTEL_VARIANTS
+        implements    CYGHWR_DEVS_FLASH_INTEL_BUFFERED_WRITES
+        description   "
+            When this option is enabled, the Intel flash driver will be
+            able to recognize and handle the 28F160S5
+            part in the family."
+    }
+
+    cdl_option CYGHWR_DEVS_FLASH_INTEL_28F320C3 {
+        display       "Intel 28F320C3 flash memory support"
+        default_value 0
+        implements    CYGHWR_IO_FLASH_BLOCK_LOCKING
+        implements    CYGINT_DEVS_FLASH_INTEL_VARIANTS
+        description   "
+            When this option is enabled, the Intel flash driver will be
+            able to recognize and handle the 28F320C3
+            part in the family."
+    }
 }
--- a/packages/devs/flash/intel/28fxxx/current/include/flash_28fxxx.inl
+++ b/packages/devs/flash/intel/28fxxx/current/include/flash_28fxxx.inl
@@ -39,19 +39,21 @@
 // Purpose:      
 // Description:  
 //              
-// Notes:        Only has FlashFile support at present
-//               Needs to get sizing details from part
-//               Needs locking.
+// Notes:        Device table could use unions of flags to save some space
+//
 //####DESCRIPTIONEND####
 //
 //==========================================================================
 
 #include <pkgconf/hal.h>
+#include <pkgconf/io_flash.h>
+#include <pkgconf/devs_flash_intel_28fxxx.h>
+
 #include <cyg/hal/hal_arch.h>
 #include <cyg/hal/hal_cache.h>
 #include CYGHWR_MEMORY_LAYOUT_H
 
-#define FLASH_P2V( _a_ ) ((volatile flash_data_t *)((unsigned int)(_a_)))
+#include <cyg/hal/hal_io.h>
 
 #define  _FLASH_PRIVATE_
 #include <cyg/io/flash.h>
@@ -64,6 +66,12 @@
 #define FLASH_Write_Buffer              FLASHWORD( 0xe8 )
 #define FLASH_Block_Erase  		FLASHWORD( 0x20 )
 #define FLASH_Confirm      		FLASHWORD( 0xD0 )
+#define FLASH_Resume      		FLASHWORD( 0xD0 )
+
+#define FLASH_Set_Lock                  FLASHWORD( 0x60 )
+#define FLASH_Set_Lock_Confirm          FLASHWORD( 0x01 )
+#define FLASH_Clear_Lock                FLASHWORD( 0x60 )
+#define FLASH_Clear_Lock_Confirm        FLASHWORD( 0xd0 )
 
 #define FLASH_Read_Status  		FLASHWORD( 0x70 )
 #define FLASH_Clear_Status 		FLASHWORD( 0x50 )
@@ -73,39 +81,26 @@
 #define FLASH_ErrorMask			FLASHWORD( 0x7E )
 #define FLASH_ErrorProgram		FLASHWORD( 0x10 )
 #define FLASH_ErrorErase		FLASHWORD( 0x20 )
+#define FLASH_ErrorLock  		FLASHWORD( 0x30 )
 #define FLASH_ErrorLowVoltage           FLASHWORD( 0x08 )
 #define FLASH_ErrorLocked               FLASHWORD( 0x02 )
 
 // Platform code must define the below
 // #define CYGNUM_FLASH_INTERLEAVE      : Number of interleaved devices (in parallel)
 // #define CYGNUM_FLASH_SERIES          : Number of devices in series
+// #define CYGNUM_FLASH_WIDTH           : Width of devices on platform
 // #define CYGNUM_FLASH_BASE            : Address of first device
-// And select one of the below device variants
 
-#ifdef CYGPKG_DEVS_FLASH_INTEL_28F160
-# define FLASH_BLOCK_SIZE               (0x10000*CYGNUM_FLASH_INTERLEAVE)
-# define FLASH_NUM_REGIONS              (32)
-# define CYGNUM_FLASH_WIDTH             (16)
-# define CYGNUM_FLASH_BLANK             (1)
-# define FLASH_BUFFER_SIZE              (32*CYGNUM_FLASH_INTERLEAVE)
-# define CYGNUM_FLASH_ID_MANUFACTURER   FLASHWORD(0xb0)
-# define CYGNUM_FLASH_ID_DEVICE         FLASHWORD(0xd0)
-#endif
+#define CYGNUM_FLASH_BLANK              (1)
+#define CYGNUM_FLASH_DEVICES            (CYGNUM_FLASH_INTERLEAVE*CYGNUM_FLASH_SERIES)
+
 
-#ifdef CYGPKG_DEVS_FLASH_INTEL_28F320
-# define FLASH_BLOCK_SIZE               (0x10000*CYGNUM_FLASH_INTERLEAVE)
-# define FLASH_NUM_REGIONS              (64)
-# define CYGNUM_FLASH_WIDTH             (16)
-# define CYGNUM_FLASH_BLANK             (1)
-# define FLASH_BUFFER_SIZE              (32*CYGNUM_FLASH_INTERLEAVE)
-# define CYGNUM_FLASH_ID_MANUFACTURER   FLASHWORD(0xb0)
-# define CYGNUM_FLASH_ID_DEVICE         FLASHWORD(0xd4)
+#ifndef FLASH_P2V
+# define FLASH_P2V( _a_ ) ((volatile flash_data_t *)((CYG_ADDRWORD)(_a_)))
 #endif
-
-#define FLASH_DEVICE_SIZE               (FLASH_BLOCK_SIZE*FLASH_NUM_REGIONS)
-#define CYGNUM_FLASH_DEVICES            (CYGNUM_FLASH_INTERLEAVE*CYGNUM_FLASH_SERIES)
-#define CYGNUM_FLASH_BASE_MASK          (~(FLASH_DEVICE_SIZE-1))
-#define CYGNUM_FLASH_BLOCK_MASK         (~(FLASH_BLOCK_SIZE-1))
+#ifndef CYGHWR_FLASH_28FXXX_PLF_INIT
+# define CYGHWR_FLASH_28FXXX_PLF_INIT()
+#endif
 
 //----------------------------------------------------------------------------
 // Now that device properties are defined, include magic for defining
@@ -113,6 +108,30 @@
 #include <cyg/io/flash_dev.h>
 
 //----------------------------------------------------------------------------
+// Information about supported devices
+typedef struct flash_dev_info {
+    flash_data_t device_id;
+    cyg_uint32   block_size;
+    cyg_int32    block_count;
+    cyg_uint32   base_mask;
+    cyg_uint32   device_size;
+    cyg_bool     locking;               // supports locking
+    cyg_bool     buffered_w;            // supports buffered writes
+    cyg_bool     bootblock;
+    cyg_uint32   bootblocks[12];         // 0 is bootblock offset, 1-11 sub-sector sizes (or 0)
+    cyg_bool     banked;
+    cyg_uint32   banks[2];               // bank offets, highest to lowest (lowest should be 0)
+                                         // (only one entry for now, increase to support devices
+                                         // with more banks).
+} flash_dev_info_t;
+
+static const flash_dev_info_t* flash_dev_info;
+static const flash_dev_info_t supported_devices[] = {
+#include <cyg/io/flash_28fxxx_parts.inl>
+};
+#define NUM_DEVICES (sizeof(supported_devices)/sizeof(flash_dev_info_t))
+
+//----------------------------------------------------------------------------
 // Functions that put the flash device into non-read mode must reside
 // in RAM.
 void flash_query(void* data) __attribute__ ((section (".2ram.flash_query")));
@@ -121,29 +140,40 @@ int  flash_erase_block(void* block, unsi
 int  flash_program_buf(void* addr, void* data, int len,
                        unsigned long block_mask, int buffer_size)
     __attribute__ ((section (".2ram.flash_program_buf")));
-
+int  flash_lock_block(void* addr)
+    __attribute__ ((section (".2ram.flash_lock_block")));
+int flash_unlock_block(void* block, int block_size, int blocks)
+    __attribute__ ((section (".2ram.flash_unlock_block")));
 
 //----------------------------------------------------------------------------
 // Initialize driver details
 int
 flash_hwr_init(void)
 {
+    int i;
     flash_data_t id[2];
 
+    CYGHWR_FLASH_28FXXX_PLF_INIT();
+
     flash_dev_query(id);
 
-    // Check that flash_id data is matching the one the driver was
-    // configured for.
-    if (id[0] != CYGNUM_FLASH_ID_MANUFACTURER
-        || id[1] != CYGNUM_FLASH_ID_DEVICE)
+    // Look through table for device data
+    flash_dev_info = supported_devices;
+    for (i = 0; i < NUM_DEVICES; i++) {
+        if (flash_dev_info->device_id == id[1])
+            break;
+        flash_dev_info++;
+    }
+
+    // Did we find the device? If not, return error.
+    if (NUM_DEVICES == i)
         return FLASH_ERR_DRV_WRONG_PART;
 
     // Hard wired for now
-    flash_info.block_size = FLASH_BLOCK_SIZE;
-    flash_info.blocks = FLASH_NUM_REGIONS;
+    flash_info.block_size = flash_dev_info->block_size;
+    flash_info.blocks = flash_dev_info->block_count * CYGNUM_FLASH_SERIES;
     flash_info.start = (void *)CYGNUM_FLASH_BASE;
-    flash_info.end = (void *)(CYGNUM_FLASH_BASE+ (FLASH_NUM_REGIONS * FLASH_BLOCK_SIZE * CYGNUM_FLASH_SERIES));
-    flash_info.buffer_size = FLASH_BUFFER_SIZE;
+    flash_info.end = (void *)(CYGNUM_FLASH_BASE+ (flash_dev_info->device_size * CYGNUM_FLASH_SERIES));
 
     return FLASH_ERR_OK;
 }
@@ -199,7 +229,6 @@ flash_query(void* data)
 
     // Stall, waiting for flash to return to read mode.
     while (w != ROM[0]);
-
 }
 
 //----------------------------------------------------------------------------
@@ -210,49 +239,68 @@ flash_erase_block(void* block, unsigned 
     int res = FLASH_ERR_OK;
     int timeout;
     unsigned long len;
+    int len_ix = 1;
     flash_data_t stat;
     volatile flash_data_t *ROM;
     volatile flash_data_t *b_p = (flash_data_t*) block;
     volatile flash_data_t *b_v;
-    ROM = FLASH_P2V((unsigned long)block & CYGNUM_FLASH_BASE_MASK);
-    b_v = FLASH_P2V(block);
+    cyg_bool bootblock;
+
+    ROM = FLASH_P2V((unsigned long)block & flash_dev_info->base_mask);
 
-    // Clear any error conditions
-    ROM[0] = FLASH_Clear_Status;
+    // Is this the boot sector?
+    bootblock = (flash_dev_info->bootblock &&
+                 (flash_dev_info->bootblocks[0] == ((unsigned long)block - (unsigned long)ROM)));
+    if (bootblock) {
+        len = flash_dev_info->bootblocks[len_ix++];
+    } else {
+        len = flash_dev_info->block_size;
+    }
 
-    ROM[0] = FLASH_Block_Erase;
-    *b_v = FLASH_Confirm;
+    while (len > 0) {
+        b_v = FLASH_P2V(b_p);
+
+        // Clear any error conditions
+        ROM[0] = FLASH_Clear_Status;
 
-    timeout = 5000000;
-    while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
-        if (--timeout == 0) break;
-    }
+        // Erase block
+        ROM[0] = FLASH_Block_Erase;
+        *b_v = FLASH_Confirm;
+
+        timeout = 5000000;
+        while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
+            if (--timeout == 0) break;
+        }
     
-    // Restore ROM to "normal" mode
-    ROM[0] = FLASH_Reset;
+        // Restore ROM to "normal" mode
+        ROM[0] = FLASH_Reset;
 
-    // Check if block got erased
-    len = block_size;
-    while (len > 0) {
-        b_v = FLASH_P2V(b_p++);
-        if (*b_v != FLASH_BlankValue ) break;
-        len -= sizeof( flash_data_t );
-    }
-    if (len != 0) {
         if (stat & FLASH_ErrorMask) {
-            if (!(stat & FLASH_ErrorErase))
+            if (!(stat & FLASH_ErrorErase)) {
                 res = FLASH_ERR_HWR;    // Unknown error
-            else {
+             } else {
                 if (stat & FLASH_ErrorLowVoltage)
                     res = FLASH_ERR_LOW_VOLTAGE;
                 else if (stat & FLASH_ErrorLocked)
-                    res = FLASH_ERR_LOCK;
+                    res = FLASH_ERR_PROTECT;
                 else
                     res = FLASH_ERR_ERASE;
             }
         }
-        else
-            res = FLASH_ERR_DRV_VERIFY;
+
+        // Check if block got erased
+        while (len > 0) {
+            b_v = FLASH_P2V(b_p++);
+            if (*b_v != FLASH_BlankValue ) {
+                // Only update return value if erase operation was OK
+                if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY;
+                return res;
+            }
+            len -= sizeof(*b_p);
+        }
+
+        if (bootblock)
+            len = flash_dev_info->bootblocks[len_ix++];
     }
 
     return res;
@@ -277,44 +325,51 @@ flash_program_buf(void* addr, void* data
     int res = FLASH_ERR_OK;
 
     // Base address of device(s) being programmed. 
-    ROM = FLASH_P2V((unsigned long)addr & CYGNUM_FLASH_BASE_MASK);
-    BA = FLASH_P2V((unsigned long)addr & CYGNUM_FLASH_BLOCK_MASK);
+    ROM = FLASH_P2V((unsigned long)addr & flash_dev_info->base_mask);
+    BA = FLASH_P2V((unsigned long)addr & ~(flash_dev_info->block_size - 1));
         
     // Clear any error conditions
     ROM[0] = FLASH_Clear_Status;
 
-    // Write any big chunks first
-    while (len >= buffer_size) {
-        wc = buffer_size;
-        if (wc > len) wc = len;
-        len -= wc;
-        wc = wc / ((CYGNUM_FLASH_WIDTH/8)*CYGNUM_FLASH_DEVICES);  // Word count
-        timeout = 5000000;
-
-        *BA = FLASH_Write_Buffer;
-        while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
-            if (--timeout == 0) {
-                res = FLASH_ERR_DRV_TIMEOUT;
-                goto bad;
-            }
+#ifdef CYGHWR_DEVS_FLASH_INTEL_BUFFERED_WRITES
+    // FIXME: This code has not been adjusted to handle bootblock
+    // parts yet.
+    // FIXME: This code does not appear to work anymore
+    if (0 && flash_dev_info->buffered_w) {
+        // Write any big chunks first
+        while (len >= buffer_size) {
+            wc = buffer_size;
+            if (wc > len) wc = len;
+            len -= wc;
+            wc = wc / ((CYGNUM_FLASH_WIDTH/8)*CYGNUM_FLASH_INTERLEAVE);  // Word count
+            timeout = 5000000;
+            
             *BA = FLASH_Write_Buffer;
-        }
-        *BA = FLASHWORD(wc-1);  // Count is 0..N-1
-        for (i = 0; i < wc;  i++) {
-            addr_v = FLASH_P2V(addr_p++);
-            *addr_v = *data_p++;
-        }
-        *BA = FLASH_Confirm;
-
-        ROM[0] = FLASH_Read_Status;
-        timeout = 5000000;
-        while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
-            if (--timeout == 0) {
-                res = FLASH_ERR_DRV_TIMEOUT;
-                goto bad;
+            while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
+                if (--timeout == 0) {
+                    res = FLASH_ERR_DRV_TIMEOUT;
+                    goto bad;
+                }
+                *BA = FLASH_Write_Buffer;
+            }
+            *BA = FLASHWORD(wc-1);  // Count is 0..N-1
+            for (i = 0; i < wc;  i++) {
+                addr_v = FLASH_P2V(addr_p++);
+                *addr_v = *data_p++;
+            }
+            *BA = FLASH_Confirm;
+            
+            ROM[0] = FLASH_Read_Status;
+            timeout = 5000000;
+            while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
+                if (--timeout == 0) {
+                    res = FLASH_ERR_DRV_TIMEOUT;
+                    goto bad;
+                }
             }
         }
     }
+#endif // CYGHWR_DEVS_FLASH_INTEL_BUFFERED_WRITES
 
     while (len > 0) {
         addr_v = FLASH_P2V(addr_p++);
@@ -334,14 +389,14 @@ flash_program_buf(void* addr, void* data
                 if (stat & FLASH_ErrorLowVoltage)
                     res = FLASH_ERR_LOW_VOLTAGE;
                 else if (stat & FLASH_ErrorLocked)
-                    res = FLASH_ERR_LOCK;
+                    res = FLASH_ERR_PROTECT;
                 else
                     res = FLASH_ERR_PROGRAM;
             }
             break;
         }
         ROM[0] = FLASH_Clear_Status;
-        ROM[0] = FLASH_Reset;            
+        ROM[0] = FLASH_Reset;
         if (*addr_v != *data_p++) {
             res = FLASH_ERR_DRV_VERIFY;
             break;
@@ -358,4 +413,194 @@ flash_program_buf(void* addr, void* data
     return res;
 }
 
+#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
+//----------------------------------------------------------------------------
+// Lock block
+int
+flash_lock_block(void* block)
+{
+    volatile flash_data_t *ROM;
+    int res = FLASH_ERR_OK;
+    flash_data_t state;
+    int timeout = 5000000;
+    volatile flash_data_t* b_p = (flash_data_t*) block;
+    volatile flash_data_t *b_v;
+    cyg_bool bootblock;
+    int len, len_ix = 1;
+
+    if (!flash_dev_info->locking)
+        return res;
+
+    ROM = (volatile flash_data_t*)((unsigned long)block & flash_dev_info->base_mask);
+
+    // Is this the boot sector?
+    bootblock = (flash_dev_info->bootblock &&
+                 (flash_dev_info->bootblocks[0] == ((unsigned long)block - (unsigned long)ROM)));
+    if (bootblock) {
+        len = flash_dev_info->bootblocks[len_ix++];
+    } else {
+        len = flash_dev_info->block_size;
+    }
+
+    while (len > 0) {
+        b_v = FLASH_P2V(b_p);
+
+        // Clear any error conditions
+        ROM[0] = FLASH_Clear_Status;
+
+        // Set lock bit
+        *b_v = FLASH_Set_Lock;
+        *b_v = FLASH_Set_Lock_Confirm;  // Confirmation
+        while(((state = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
+            if (--timeout == 0) {
+                res = FLASH_ERR_DRV_TIMEOUT;
+                break;
+            }
+        }
+
+        // Restore ROM to "normal" mode
+        ROM[0] = FLASH_Reset;
+        len = 0;
+
+        if (FLASH_ErrorLock == (state & FLASH_ErrorLock))
+            res = FLASH_ERR_LOCK;
+
+        if (res != FLASH_ERR_OK)
+            break;
+            
+        if (bootblock)
+            len = flash_dev_info->bootblocks[len_ix++];
+    }
+
+    return res;
+}
+
+//----------------------------------------------------------------------------
+// Unlock block
+
+int
+flash_unlock_block(void* block, int block_size, int blocks)
+{
+    volatile flash_data_t *ROM;
+    int res = FLASH_ERR_OK;
+    flash_data_t state;
+    int timeout = 5000000;
+    volatile flash_data_t* b_p = (flash_data_t*) block;
+    volatile flash_data_t *b_v;
+    cyg_bool bootblock;
+    int len, len_ix = 1;
+
+    if (!flash_dev_info->locking)
+        return res;
+
+    ROM = (volatile flash_data_t*)((unsigned long)block & flash_dev_info->base_mask);
+
+    // Is this the boot sector?
+    bootblock = (flash_dev_info->bootblock &&
+                 (flash_dev_info->bootblocks[0] == ((unsigned long)block - (unsigned long)ROM)));
+    if (bootblock) {
+        len = flash_dev_info->bootblocks[len_ix++];
+    } else {
+        len = flash_dev_info->block_size;
+    }
+
+    while (len > 0) {
+
+        b_v = FLASH_P2V(b_p);
+
+        // Clear any error conditions
+        ROM[0] = FLASH_Clear_Status;
+
+        // Clear lock bit
+        *b_v = FLASH_Clear_Lock;
+        *b_v = FLASH_Clear_Lock_Confirm;  // Confirmation
+        while(((state = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
+            if (--timeout == 0) {
+                res = FLASH_ERR_DRV_TIMEOUT;
+                break;
+            }
+        }
+
+        // Restore ROM to "normal" mode
+        ROM[0] = FLASH_Reset;
+        len = 0;
+
+        if (FLASH_ErrorLock == (state & FLASH_ErrorLock))
+            res = FLASH_ERR_LOCK;
+
+        if (res != FLASH_ERR_OK)
+            break;
+
+        if (bootblock)
+            len = flash_dev_info->bootblocks[len_ix++];
+    }
+
+    return res;
+
+    // FIXME: Unlocking need to support some other parts in the future
+    // as well which take a little more diddling.
+#if 0
+//
+// The difficulty with this operation is that the hardware does not support
+// unlocking single blocks.  However, the logical layer would like this to
+// be the case, so this routine emulates it.  The hardware can clear all of
+// the locks in the device at once.  This routine will use that approach and
+// then reset the regions which are known to be locked.
+//
+
+#define MAX_FLASH_BLOCKS (flash_dev_info->block_count * CYGNUM_FLASH_SERIES)
+
+    unsigned char is_locked[MAX_FLASH_BLOCKS];
+
+    // Get base address and map addresses to virtual addresses
+    ROM = FLASH_P2V( CYGNUM_FLASH_BASE_MASK & (unsigned int)block );
+    block = FLASH_P2V(block);
+
+    // Clear any error conditions
+    ROM[0] = FLASH_Clear_Status;
+
+    // Get current block lock state.  This needs to access each block on
+    // the device so currently locked blocks can be re-locked.
+    bp = ROM;
+    for (i = 0;  i < blocks;  i++) {
+        bpv = FLASH_P2V( bp );
+        *bpv = FLASH_Read_Query;
+        if (bpv == block) {
+            is_locked[i] = 0;
+        } else {
+            is_locked[i] = bpv[2];
+        }
+        bp += block_size / sizeof(*bp);
+    }
+
+    // Clears all lock bits
+    ROM[0] = FLASH_Clear_Locks;
+    ROM[0] = FLASH_Clear_Locks_Confirm;  // Confirmation
+    timeout = 5000000;
+    while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
+        if (--timeout == 0) break;
+    }
+
+    // Restore the lock state
+    bp = ROM;
+    for (i = 0;  i < blocks;  i++) {
+        bpv = FLASH_P2V( bp );
+        if (is_locked[i]) {
+            *bpv = FLASH_Set_Lock;
+            *bpv = FLASH_Set_Lock_Confirm;  // Confirmation
+            timeout = 5000000;
+            while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
+                if (--timeout == 0) break;
+            }
+        }
+        bp += block_size / sizeof(*bp);
+    }
+
+    // Restore ROM to "normal" mode
+    ROM[0] = FLASH_Reset;
+#endif
+}
+#endif // CYGHWR_IO_FLASH_BLOCK_LOCKING
+
 #endif // CYGONCE_DEVS_FLASH_INTEL_28FXXX_INL
+
new file mode 100644
--- /dev/null
+++ b/packages/devs/flash/intel/28fxxx/current/include/flash_28fxxx_parts.inl
@@ -0,0 +1,116 @@
+#ifndef CYGONCE_DEVS_FLASH_INTEL_28FXXX_PARTS_INL
+#define CYGONCE_DEVS_FLASH_INTEL_28FXXX_PARTS_INL
+//==========================================================================
+//
+//      flash_28fxxx_parts.inl
+//
+//      Intel 28Fxxx part descriptors
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//
+// -------------------------------------------
+// The contents of this file are subject to the Red Hat eCos Public License
+// Version 1.1 (the "License"); you may not use this file except in
+// compliance with the License.  You may obtain a copy of the License at
+// http://www.redhat.com/
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the
+// License for the specific language governing rights and limitations under
+// the License.
+//
+// The Original Code is eCos - Embedded Configurable Operating System,
+// released September 30, 1998.
+//
+// The Initial Developer of the Original Code is Red Hat.
+// Portions created by Red Hat are
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.
+// All Rights Reserved.
+// -------------------------------------------
+//
+//####COPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    jskov
+// Contributors: jskov
+// Date:         2001-08-07
+// Purpose:
+// Description:  Intel 28Fxxx part descriptors
+// Usage:        Should be included from the flash_28fxxx.inl file only.
+//
+// FIXME:        Add configury for selecting bottom/top bootblocks
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#if CYGNUM_FLASH_WIDTH == 8
+
+#else // 16 bit devices
+
+#ifdef CYGHWR_DEVS_FLASH_INTEL_28F320C3
+    {   // 28F320C3-T
+        device_id  : FLASHWORD(0x88c4),
+        block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE,
+        block_count: 64,
+        device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE,
+        base_mask  : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1),
+        locking    : true,
+        buffered_w : false,
+        bootblock  : true,
+        bootblocks : { 0x3e0000 * CYGNUM_FLASH_INTERLEAVE,
+                       0x001000 * CYGNUM_FLASH_INTERLEAVE,
+                       0x001000 * CYGNUM_FLASH_INTERLEAVE,
+                       0x001000 * CYGNUM_FLASH_INTERLEAVE,
+                       0x001000 * CYGNUM_FLASH_INTERLEAVE,
+                       0x001000 * CYGNUM_FLASH_INTERLEAVE,
+                       0x001000 * CYGNUM_FLASH_INTERLEAVE,
+                       0x001000 * CYGNUM_FLASH_INTERLEAVE,
+                       0x001000 * CYGNUM_FLASH_INTERLEAVE,
+                       0
+                     },
+        banked     : false
+    },
+    {   // 28F320C3-B
+        device_id  : FLASHWORD(0x88c5),
+        block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE,
+        block_count: 64,
+        device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE,
+        base_mask  : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1),
+        locking    : true,
+        buffered_w : false,
+        bootblock  : true,
+        bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE,
+                       0x001000 * CYGNUM_FLASH_INTERLEAVE,
+                       0x001000 * CYGNUM_FLASH_INTERLEAVE,
+                       0x001000 * CYGNUM_FLASH_INTERLEAVE,
+                       0x001000 * CYGNUM_FLASH_INTERLEAVE,
+                       0x001000 * CYGNUM_FLASH_INTERLEAVE,
+                       0x001000 * CYGNUM_FLASH_INTERLEAVE,
+                       0x001000 * CYGNUM_FLASH_INTERLEAVE,
+                       0x001000 * CYGNUM_FLASH_INTERLEAVE,
+                       0
+                     },
+        banked     : false
+    },
+#endif
+
+#ifdef CYGHWR_DEVS_FLASH_INTEL_28F160S5
+    {   // 28F160S5
+        device_id  : FLASHWORD(0x00d0),
+        block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE,
+        block_count: 32,
+        device_size: 0x200000 * CYGNUM_FLASH_INTERLEAVE,
+        base_mask  : ~(0x200000 * CYGNUM_FLASH_INTERLEAVE - 1),
+        buffered_w : true,
+        locking    : false,
+        bootblock  : false,
+        banked     : false
+    },
+#endif
+
+#endif // 16 bit devices
+
+
+#endif // CYGONCE_DEVS_FLASH_INTEL_28FXXX_PARTS_INL
--- a/packages/devs/flash/mn10300/stb/current/ChangeLog
+++ b/packages/devs/flash/mn10300/stb/current/ChangeLog
@@ -1,3 +1,7 @@
+2001-08-03  David Howells  <dhowells@redhat.com>
+
+	* src/mn10300_stb_flash.c: updated to latest AMD flash interface.
+
 2001-06-08  Jesper Skov  <jskov@redhat.com>
         From dhowells@redhat.com
 	* cdl/flash_stb.cdl: New package/file(s).
--- a/packages/devs/flash/mn10300/stb/current/src/mn10300_stb_flash.c
+++ b/packages/devs/flash/mn10300/stb/current/src/mn10300_stb_flash.c
@@ -44,21 +44,13 @@
 //--------------------------------------------------------------------------
 // Device properties
 
-#if 0
-// We use a four chip parallel AM29xxxxx module plugged into the SRAM2 socket
-// on the STB board.
-#define CYGNUM_FLASH_INTERLEAVE	(4)
-#define CYGNUM_FLASH_SERIES	(1)
-#define CYGNUM_FLASH_WIDTH      (8)
-#define CYGNUM_FLASH_BASE 	(0x82800000u) /* uncached shadow region */
-#else
 // We use a four chip parallel AM29xxxxx module plugged into the SRAM3 socket
 // on the STB board.
 #define CYGNUM_FLASH_INTERLEAVE	(4)
 #define CYGNUM_FLASH_SERIES	(1)
-#define CYGNUM_FLASH_CHIP_MODE	(8)
+#define CYGNUM_FLASH_WIDTH	(8)
+#define CYGNUM_FLASH_16AS8
 #define CYGNUM_FLASH_BASE 	(0x82C00000u) /* uncached shadow region */
-#endif
 
 //--------------------------------------------------------------------------
 // Platform specific extras
--- a/packages/devs/usb/sa11x0/current/ChangeLog
+++ b/packages/devs/usb/sa11x0/current/ChangeLog
@@ -1,3 +1,8 @@
+2001-08-06  Bart Veer  <bartv@redhat.com>
+
+	* src/usbs_sa11x0.c:
+	Add initial support for USB testing.
+
 2001-05-21  Bart Veer  <bartv@redhat.com>
 
 	* src/usbs_sa11x0.c (usbs_sa11x0_ep2_dsr):
--- a/packages/devs/usb/sa11x0/current/src/usbs_sa11x0.c
+++ b/packages/devs/usb/sa11x0/current/src/usbs_sa11x0.c
@@ -958,6 +958,8 @@ usbs_sa11x0_ep0_dsr(void)
                                  EP0_FORCE_STALL,
                                  EP0_OUT_READY);
             }
+            // Also remember to switch back to IDLE state 
+            ep0.ep_state = EP0_STATE_IDLE;
         }
         
     } else if (0 != (EP0_OUT_READY & hw_state)) {
@@ -2424,3 +2426,55 @@ usbs_sa11x0_init(void)
     cyg_drv_interrupt_attach(usbs_sa11x0_intr_handle);
     cyg_drv_interrupt_unmask(SA11X0_IRQ_USB_SERVICE_REQUEST);
 }
+
+// ----------------------------------------------------------------------------
+// Testing support.
+usbs_testing_endpoint usbs_testing_endpoints[] = {
+    {
+        endpoint_type   : USB_ENDPOINT_DESCRIPTOR_ATTR_CONTROL, 
+        endpoint_number : 0,
+        in_endpoint     : false,
+        endpoint        : (void*) &ep0.common,
+#ifdef CYGVAR_DEVS_USB_SA11X0_EP0_DEVTAB_ENTRY
+        devtab_entry    : CYGDAT_DEVS_USB_SA11X0_DEVTAB_BASENAME "0c",
+#else        
+        devtab_entry    : (const char*) 0,
+#endif        
+        min_size        : 1,            // zero-byte control transfers are meaningless
+        max_size        : 0x0FFFF,      // limit imposed by protocol
+        max_in_padding  : 0
+    },
+#ifdef CYGPKG_DEVS_USB_SA11X0_EP1
+    {
+        endpoint_type   : USB_ENDPOINT_DESCRIPTOR_ATTR_BULK,
+        endpoint_number : 1,
+        in_endpoint     : false,        // ep1 is an rx endpoint
+        endpoint        : (void*) &ep1.common,
+#ifdef CYGVAR_DEVS_USB_SA11X0_EP1_DEVTAB_ENTRY
+        devtab_entry    : CYGDAT_DEVS_USB_SA11X0_DEVTAB_BASENAME "1r",
+#else        
+        devtab_entry    : (const char*) 0,
+#endif        
+        min_size        : 0,
+        max_size        : -1,           // No hardware or driver limitation
+        max_in_padding  : 0
+    },
+#endif
+#ifdef CYGPKG_DEVS_USB_SA11X0_EP2
+    {
+        endpoint_type   : USB_ENDPOINT_DESCRIPTOR_ATTR_BULK,
+        endpoint_number : 2,
+        in_endpoint     : true,         // ep2 is a tx endpoint
+        endpoint        : (void*) &ep2.common,
+#ifdef CYGVAR_DEVS_USB_SA11X0_EP2_DEVTAB_ENTRY
+        devtab_entry    : CYGDAT_DEVS_USB_SA11X0_DEVTAB_BASENAME "2w",
+#else        
+        devtab_entry    : (const char*) 0,
+#endif        
+        min_size        : 0,
+        max_size        : -1,           // No hardware or driver limitation
+        max_in_padding  : 1             // hardware limitation
+    },
+#endif
+    USBS_TESTING_ENDPOINTS_TERMINATOR
+};
--- a/packages/hal/arm/iq80310/current/ChangeLog
+++ b/packages/hal/arm/iq80310/current/ChangeLog
@@ -1,3 +1,8 @@
+2001-08-04  Mark Salter  <msalter@redhat.com>
+
+	* include/hal_platform_setup.h: Fix mapping so first MB of SDRAM has
+	ECC turned on. Now map first 4K of flash at 0xd0000000.
+
 2001-06-21  Jonathan Larmour  <jlarmour@redhat.com>
 
 	* images/*: Remove. Don't bloat repository with things already on
--- a/packages/hal/arm/iq80310/current/include/hal_platform_setup.h
+++ b/packages/hal/arm/iq80310/current/include/hal_platform_setup.h
@@ -135,11 +135,11 @@
 	.endm
 
 	// form a first-level page table entry
-	.macro FL_PT_ENTRY base,d
+	.macro FL_PT_ENTRY base,p,d
 	// I wanted to use logical operations here, but since I am using symbols later 
 	// to fill in the parameters, I had to use addition to force the assembler to
 	// do it right
-	.word \base + (\d << 5) + 1
+	.word \base + (\p << 9) + (\d << 5) + 1
 	.endm
 
 	// form a second level small page entry
@@ -170,7 +170,7 @@
 
 	// 1MB of FLASH with i80312 MMRs mapped in using 4K small pages so we can
 	// set the access permission on flash and memory-mapped registers properly.
-	FL_PT_ENTRY mmu_table_flashbase,0
+	FL_PT_ENTRY mmu_table_flashbase,0,0
 
 	// Remaining 7MB of FLASH
 	//   rw, cacheable, non-bufferable
@@ -186,13 +186,11 @@
 	.set	__base,__base+1
 	.endr
 
-	// up to 512MB ECC SDRAM
+	// up to 512MB ECC SDRAM mapped 1-to-1
+	// first 1MB mapped in 4K chunks
 	//   x=c=b=1
-	// first 1MB mapped by second level table
-	FL_PT_ENTRY mmu_table_rambase,0
+	FL_PT_ENTRY mmu_table_rambase,1,0
 	.set	__base,__base+1
-	
-	// remainder of SDRAM mapped 1-to-1
 	.rept	0xC00 - 0xA01
 	FL_SECTION_ENTRY __base,1,3,1,0,1,1
 	.set	__base,__base+1
@@ -205,8 +203,13 @@
 	.set	__base,__base+1
 	.endr
 	
+	// Alias for first 1MB of FLASH
+	//  rw, cacheable, non-bufferable
+	FL_SECTION_ENTRY 0x000,0,3,0,0,1,0
+	.set	__base,__base+1
+
 	// Invalid
-	.rept	0xF00 - 0xD00
+	.rept	0xF00 - 0xD01
 	.word 0
 	.set	__base,__base+1
 	.endr
@@ -246,15 +249,10 @@
 	// Now is the second level table for the first megabyte
 	// of DRAM.
     mmu_table_rambase:
-	// Map 4k page at 0xa0000000 virt --> 0x00000000 physical
-	//   Read-Write, cacheable, non-bufferable
-	SL_SMPAGE_ENTRY 0x00000,3,3,3,3,1,0
-	.set	__base,__base+1		   
-
-	// Map remainder of first meg of SDRAM
+	// Map first meg of SDRAM
 	//   Read-Write, cacheable, bufferable
-	.set    __base,0xA0001
-	.rept	0x100 - 0x1
+	.set    __base,0xA0000
+	.rept	0x100
 	SL_XSMPAGE_ENTRY __base,1,3,1,1
 	.set	__base,__base+1
 	.endr
@@ -727,8 +725,20 @@ SDRAM_DRIVE_2_BANK_X8:
 	stmia	r11!, {r0-r7}
 	beq	15f
 	b	10b
-    15:	
+    15:
 	
+	// now copy 1st 4K page of flash into first 4K of RAM.
+	ldr	r1, =RAM_BASE	// base address of SDRAM
+	mov     r2, #0xd0000000 // alias for first 1M of flash
+	mov     r3, #0x1000
+    16:
+	ldr     r4, [r2]
+	add	r2, r2, #4
+	str	r4, [r1]
+	add	r1, r1, #4
+	subs    r3, r3, #4
+	bne     16b
+
 	// Battery Backup SDRAM Memory Test
 	// Store 4 byte Test Pattern back into memory
 	str r10, [r9, #0x0]
--- a/packages/hal/common/current/ChangeLog
+++ b/packages/hal/common/current/ChangeLog
@@ -1,3 +1,26 @@
+2001-08-03  Nick Garnett  <nickg@redhat.com>
+
+        Imported from a development branch:
+	
+	2001-07-11  Nick Garnett  <nickg@redhat.com>
+
+		* include/drv_api.h: 
+		* src/drv_api.c:
+		Added API for controlling routing of interrupts to CPUs in SMP
+		configurations.
+
+	2001-06-29  Nick Garnett  <nickg@cygnus.co.uk>
+
+		* include/drv_api.h: 
+		* src/drv_api.c:
+		Added API for using spinlocks.
+
+2001-08-03  Jesper Skov  <jskov@redhat.com>
+
+	* tests/vaargs.c: Added.
+	* cdl/hal.cdl: Added CYGPKG_HAL_BUILD_COMPILER_TESTS to allow cpp1
+	and vaargs tests to be compiled conditionally.
+
 2001-07-27  Jesper Skov  <jskov@redhat.com>
 
 	* tests/intr.c: Set up interrupt ISR using driver API so it works
--- a/packages/hal/common/current/cdl/hal.cdl
+++ b/packages/hal/common/current/cdl/hal.cdl
@@ -421,11 +421,18 @@ cdl_package CYGPKG_HAL {
 
     }
 
+    cdl_option     CYGPKG_HAL_BUILD_COMPILER_TESTS {
+        display       "Build Compiler sanity checking tests"
+        description   "
+            Enabling this option causes compiler tests to be built."
+    }
+
     cdl_option CYGPKG_HAL_TESTS {
         display "Common HAL tests"
         flavor  data
         no_define
-        calculated { "tests/cache tests/context tests/intr tests/cpp1" }
+        calculated { (!CYGPKG_HAL_BUILD_COMPILER_TESTS) ? "tests/cache tests/context tests/intr" :
+                     "tests/cache tests/context tests/intr tests/cpp1 tests/vaargs" }
         description   "
             This option specifies the set of tests for the common HAL."
     }
--- a/packages/hal/common/current/include/drv_api.h
+++ b/packages/hal/common/current/include/drv_api.h
@@ -94,6 +94,17 @@
 #define cyg_drv_interrupt_acknowledge  cyg_interrupt_acknowledge
 #define cyg_drv_interrupt_configure    cyg_interrupt_configure
 #define cyg_drv_interrupt_level        cyg_interrupt_level
+#define cyg_drv_interrupt_set_cpu      cyg_interrupt_set_cpu
+#define cyg_drv_interrupt_get_cpu      cyg_interrupt_get_cpu
+
+#define cyg_drv_spinlock_t             cyg_spinlock_t
+#define cyg_drv_spinlock_init          cyg_spinlock_init
+#define cyg_drv_spinlock_spin          cyg_spinlock_spin
+#define cyg_drv_spinlock_clear         cyg_spinlock_clear
+#define cyg_drv_spinlock_try           cyg_spinlock_try
+#define cyg_drv_spinlock_test          cyg_spinlock_test
+#define cyg_drv_spinlock_spin_intsave  cyg_spinlock_spin_intsave
+#define cyg_drv_spinlock_clear_intsave cyg_spinlock_clear_intsave
 
 #else /* CYGPKG_KERNEL */
 
@@ -104,8 +115,9 @@ typedef CYG_ADDRWORD cyg_addrword_t;    
 typedef cyg_addrword_t cyg_handle_t;        /* Object handle              */
 typedef cyg_uint32   cyg_priority_t;        /* type for priorities        */
 typedef cyg_uint32   cyg_vector_t;          /* Interrupt vector id        */
-typedef int cyg_bool_t;
-typedef cyg_int32      cyg_code_t;          /* type for various codes        */       
+typedef cyg_uint32   cyg_cpu_t;             /* CPU id                     */
+typedef int          cyg_bool_t;
+typedef cyg_int32    cyg_code_t;            /* type for various codes        */       
 
 typedef cyg_uint32 cyg_ISR_t( cyg_vector_t vector, cyg_addrword_t data);
 typedef void cyg_DSR_t(cyg_vector_t vector,
@@ -182,6 +194,8 @@ externC void cyg_drv_interrupt_configure
                      cyg_bool_t          up
                      );
 externC void cyg_drv_interrupt_level( cyg_vector_t vector, cyg_priority_t level );
+externC void cyg_drv_interrupt_set_cpu( cyg_vector_t vector, cyg_cpu_t cpu );
+externC cyg_cpu_t cyg_drv_interrupt_get_cpu( cyg_vector_t vector );
 
 
 enum cyg_ISR_results
@@ -190,6 +204,33 @@ enum cyg_ISR_results
     CYG_ISR_CALL_DSR = 2                /* Schedule DSR                      */
 };
 
+
+typedef struct
+{
+    cyg_atomic          lock;
+} cyg_drv_spinlock_t;
+
+void cyg_drv_spinlock_init(
+    cyg_drv_spinlock_t  *lock,          /* spinlock to initialize            */
+    cyg_bool_t          locked          /* init locked or unlocked           */
+);
+
+void cyg_drv_spinlock_destroy( cyg_drv_spinlock_t *lock );
+
+void cyg_drv_spinlock_spin( cyg_drv_spinlock_t *lock );
+
+void cyg_drv_spinlock_clear( cyg_drv_spinlock_t *lock );
+
+cyg_bool_t cyg_drv_spinlock_try( cyg_drv_spinlock_t *lock );
+
+cyg_bool_t cyg_drv_spinlock_test( cyg_drv_spinlock_t *lock );
+
+void cyg_drv_spinlock_spin_intsave( cyg_drv_spinlock_t *lock,
+                                    cyg_addrword_t *istate );
+
+void cyg_drv_spinlock_clear_intsave( cyg_drv_spinlock_t *lock,
+                                     cyg_addrword_t istate );
+
 #endif /* CYGPKG_KERNEL */
 
 /*------------------------------------------------------------------------*/
--- a/packages/hal/common/current/src/drv_api.c
+++ b/packages/hal/common/current/src/drv_api.c
@@ -62,6 +62,8 @@
 
 static volatile cyg_int32 isr_disable_counter = 1;  // ISR disable counter
 
+static CYG_INTERRUPT_STATE isr_disable_state;
+
 volatile cyg_int32 dsr_disable_counter  // DSR disable counter
                       CYGBLD_ATTRIB_ASM_ALIAS( cyg_scheduler_sched_lock );
 
@@ -215,11 +217,10 @@ cyg_uint32 chain_isr(cyg_vector_t vector
 
 externC void cyg_drv_isr_lock()
 {
-    CYG_INTERRUPT_STATE dummy;
-
     CYG_REPORT_FUNCTION();
 
-    HAL_DISABLE_INTERRUPTS(dummy);
+    if( isr_disable_counter == 0 )
+        HAL_DISABLE_INTERRUPTS(isr_disable_state);
 
     CYG_ASSERT( isr_disable_counter >= 0 , "Disable counter negative");
     
@@ -242,7 +243,7 @@ externC void cyg_drv_isr_unlock()
 
     if ( isr_disable_counter == 0 )
     {
-        HAL_ENABLE_INTERRUPTS();
+        HAL_RESTORE_INTERRUPTS(isr_disable_state);
     }
 
     CYG_REPORT_RETURN();
@@ -351,6 +352,8 @@ externC cyg_bool_t cyg_drv_mutex_trylock
     CYG_REPORT_FUNCTION();
 
     if( mutex->lock == 1 ) result = false;
+
+    mutex->lock = 1;
     
     CYG_REPORT_RETURN();
 
@@ -476,7 +479,107 @@ externC void cyg_drv_cond_broadcast( cyg
     
     CYG_REPORT_RETURN();    
 }
+
+//--------------------------------------------------------------------------
+// Spinlock support.
+// Since we can only support a single CPU in this version of the API, we only
+// set and clear the lock variable to keep track of what's happening.
+
+void cyg_drv_spinlock_init(
+    cyg_drv_spinlock_t  *lock,          /* spinlock to initialize            */
+    cyg_bool_t          locked          /* init locked or unlocked           */
+)
+{
+    CYG_REPORT_FUNCTION();
     
+    lock->lock = locked;
+
+    CYG_REPORT_RETURN();    
+}
+
+void cyg_drv_spinlock_destroy( cyg_drv_spinlock_t *lock )
+{
+    CYG_REPORT_FUNCTION();
+    
+    lock->lock = -1;
+
+    CYG_REPORT_RETURN();    
+}
+
+void cyg_drv_spinlock_spin( cyg_drv_spinlock_t *lock )
+{
+    CYG_REPORT_FUNCTION();
+    
+    CYG_ASSERT( lock->lock == 0 , "Trying to lock locked spinlock");
+
+    lock->lock = 1;
+
+    CYG_REPORT_RETURN();
+}
+
+void cyg_drv_spinlock_clear( cyg_drv_spinlock_t *lock )
+{
+    CYG_REPORT_FUNCTION();
+
+    CYG_ASSERT( lock->lock == 1 , "Trying to clear cleared spinlock");
+
+    lock->lock = 0;
+    
+    CYG_REPORT_RETURN();    
+}
+
+cyg_bool_t cyg_drv_spinlock_try( cyg_drv_spinlock_t *lock )
+{
+    cyg_bool_t result = true;
+    
+    CYG_REPORT_FUNCTION();
+
+    if( lock->lock == 1 ) result = false;
+
+    lock->lock = 1;
+    
+    CYG_REPORT_RETURN();
+
+    return result;
+}
+
+cyg_bool_t cyg_drv_spinlock_test( cyg_drv_spinlock_t *lock )
+{
+    cyg_bool_t result = true;
+    
+    CYG_REPORT_FUNCTION();
+
+    if( lock->lock == 1 ) result = false;
+
+    CYG_REPORT_RETURN();
+
+    return result;
+}
+
+void cyg_drv_spinlock_spin_intsave( cyg_drv_spinlock_t *lock,
+                                    cyg_addrword_t *istate )
+{
+    CYG_REPORT_FUNCTION();
+
+    HAL_DISABLE_INTERRUPTS( *istate );
+
+    lock->lock = 1;
+    
+    CYG_REPORT_RETURN();
+}
+    
+
+void cyg_drv_spinlock_clear_intsave( cyg_drv_spinlock_t *lock,
+                                     cyg_addrword_t istate )
+{
+    CYG_REPORT_FUNCTION();
+
+    lock->lock = 0;
+    
+    HAL_RESTORE_INTERRUPTS( istate );
+    
+    CYG_REPORT_RETURN();
+}
 
 //--------------------------------------------------------------------------
 // Create an interrupt object.
@@ -725,6 +828,42 @@ externC void cyg_drv_interrupt_level( cy
     CYG_REPORT_RETURN();
 }
 
+// -------------------------------------------------------------------------
+// CPU interrupt routing
+
+externC void cyg_drv_interrupt_set_cpu( cyg_vector_t vector, cyg_cpu_t cpu )
+{
+    CYG_REPORT_FUNCTION();
+    CYG_REPORT_FUNCARG2("vector = %d, cpu = %d", vector, cpu);
+
+    CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");    
+    CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
+
+#ifdef CYGPKG_HAL_SMP_SUPPORT    
+    HAL_INTERRUPT_SET_CPU( vector, cpu );
+#endif
+    
+    CYG_REPORT_RETURN();
+}
+
+externC cyg_cpu_t cyg_drv_interrupt_get_cpu( cyg_vector_t vector )
+{
+    cyg_cpu_t cpu = 0;
+    
+    CYG_REPORT_FUNCTION();
+    CYG_REPORT_FUNCARG1("vector = %d", vector);
+
+    CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");    
+    CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
+
+#ifdef CYGPKG_HAL_SMP_SUPPORT    
+    HAL_INTERRUPT_GET_CPU( vector, cpu );
+#endif
+    
+    CYG_REPORT_RETURN();
+
+    return cpu;
+}
 
 // -------------------------------------------------------------------------
 // Exception delivery function called from the HAL as a result of a
new file mode 100644
--- /dev/null
+++ b/packages/hal/common/current/tests/vaargs.c
@@ -0,0 +1,146 @@
+//=================================================================
+//
+//        vaargs.c
+//
+//        HAL variable argument calls test
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     jskov
+// Contributors:  jskov
+// Date:          2001-08-03
+//####DESCRIPTIONEND####
+//==========================================================================
+
+#include <cyg/infra/testcase.h>         // test case macros
+#include <cyg/infra/diag.h>             // diag_printf
+#include <cyg/infra/cyg_ass.h>          // assertions
+
+#include <cyg/hal/hal_arch.h>           // context macros
+
+#include <stdarg.h>                     // vaargs magic
+
+// -------------------------------------------------------------------------
+
+int
+function(int n, ...)
+{
+    va_list args;
+    int c = 11 * n;
+    int i = 1;
+    int res = 1;
+
+    CYG_ASSERT(n >= 0 && n < 8, "Invalid count argument");
+
+    va_start(args, n);
+
+    for (i = 1; i <= n; c++, i++) {
+        int v = va_arg(args, int);
+        if (v != c) {
+            diag_printf("FAIL:<Bad argument: index %d expected %d got %d>\n", i, c, v);
+            res = 0;
+        }
+    }       
+
+    va_end(args);
+
+    return res;
+}
+
+int
+function_proxy(int n, va_list args)
+{
+    int c = 11 * n;
+    int i = 1;
+    int res = 1;
+
+    CYG_ASSERT(n >= 0 && n < 8, "Invalid count argument");
+
+    for (i = 1; i <= n; c++, i++) {
+        int v = va_arg(args, int);
+        if (v != c) {
+            diag_printf("FAIL:<Bad argument: index %d expected %d got %d>\n", i, c, v);
+            res = 0;
+        }
+    }       
+
+    return res;
+}
+
+int
+proxy(int n, ...)
+{
+    int res;
+    va_list args;
+
+    va_start(args, n);
+    res = function_proxy(n, args);
+    va_end(args);
+
+    return res;
+}
+
+
+void
+entry(void)
+{
+    int res;
+
+    res =  function(0);
+    res &= function(1, 11);
+    res &= function(2, 22, 23);
+    res &= function(3, 33, 34, 35);
+    res &= function(4, 44, 45, 46, 47);
+    res &= function(5, 55, 56, 57, 58, 59);
+    res &= function(6, 66, 67, 68, 69, 70, 71);
+    res &= function(7, 77, 78, 79, 80, 81, 82, 83);
+    CYG_TEST_PASS_FAIL(res, "Direct vaargs calls");
+
+    res =  proxy(0);
+    res &= proxy(1, 11);
+    res &= proxy(2, 22, 23);
+    res &= proxy(3, 33, 34, 35);
+    res &= proxy(4, 44, 45, 46, 47);
+    res &= proxy(5, 55, 56, 57, 58, 59);
+    res &= proxy(6, 66, 67, 68, 69, 70, 71);
+    res &= proxy(7, 77, 78, 79, 80, 81, 82, 83);
+    CYG_TEST_PASS_FAIL(res, "Proxy vaargs calls");
+
+    CYG_TEST_FINISH("HAL vaargs test");
+}
+
+// -------------------------------------------------------------------------
+
+externC void
+cyg_start( void )
+{
+    entry();
+}
+
+// -------------------------------------------------------------------------
+// EOF vaargs.c
--- a/packages/hal/mips/rm7000/ocelot/current/ChangeLog
+++ b/packages/hal/mips/rm7000/ocelot/current/ChangeLog
@@ -1,3 +1,20 @@
+2001-08-09  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* include/plf_intr.h: Move HAL_INTERRUPT_ interrupt controller
+	access macros to variant HAL as they are generic.
+
+2001-08-08  Chris Morrow  <cmorrow@YottaYotta.com>
+
+	* include/plf_intr.h (HAL_INTERRUPT_MASK): Use correct comparison
+	for determining when to use interrupt control register.
+	Also use cfc rather than mfc insns. Also simplify a fraction.
+	(HAL_INTERRUPT_UNMASK): Ditto.
+
+2001-08-03  Jesper Skov  <jskov@redhat.com>
+
+	* cdl/hal_mips_rm7000_ocelot.cdl: Removed obsolete and wrong
+	gdb_module build runes.
+
 2001-06-22  Jesper Skov  <jskov@redhat.com>
 
 	* misc/redboot_RAM.ecm: Force 32k stack.
--- a/packages/hal/mips/rm7000/ocelot/current/cdl/hal_mips_rm7000_ocelot.cdl
+++ b/packages/hal/mips/rm7000/ocelot/current/cdl/hal_mips_rm7000_ocelot.cdl
@@ -297,8 +297,6 @@ cdl_package CYGPKG_HAL_MIPS_RM7000_OCELO
 
             make -priority 320 {
                 <PREFIX>/bin/gdb_module.srec : <PREFIX>/bin/gdb_module.img
-                $(OBJCOPY) --strip-unneeded -O srec $< pre-swap.srec
-                $(OBJCOPY) --change-address 0xbfc00000 -I binary -O srec be.bin $@
             }
         }
     }
--- a/packages/hal/mips/rm7000/ocelot/current/include/plf_intr.h
+++ b/packages/hal/mips/rm7000/ocelot/current/include/plf_intr.h
@@ -90,7 +90,7 @@
 #endif
 
 //--------------------------------------------------------------------------
-// Interrupt controler information
+// Interrupt controller information
 
 // V320USC 
 #define CYGARC_REG_INT_STAT   0xb80000ec
@@ -114,99 +114,6 @@
 #define CYGARC_REG_IO_MASK    0xb5300040
 
 
-#define HAL_INTERRUPT_MASK( _vector_ )                                      \
-    CYG_MACRO_START                                                         \
-    if( (_vector_) <= CYGNUM_HAL_INTERRUPT_COMPARE )                        \
-    {                                                                       \
-        asm volatile (                                                      \
-            "mfc0   $3,$12\n"                                               \
-            "la     $2,0x00000400\n"                                        \
-            "sllv   $2,$2,%0\n"                                             \
-            "nor    $2,$2,$0\n"                                             \
-            "and    $3,$3,$2\n"                                             \
-            "mtc0   $3,$12\n"                                               \
-            "nop; nop; nop\n"                                               \
-            :                                                               \
-            : "r"(_vector_)                                                 \
-            : "$2", "$3"                                                    \
-            );                                                              \
-    }                                                                       \
-    else if ((_vector_) >= CYGNUM_HAL_INTERRUPT_UART2)                      \
-    {                                                                       \
-        /* int 6:9 are masked in the Interrupt Control register */          \
-        asm volatile (                                                      \
-            "mfc1   $3,$20\n"                                               \
-            "la     $2,0x00000100\n"                                        \
-            "sllv   $2,$2,%0\n"                                             \
-            "nor    $2,$2,$0\n"                                             \
-            "and    $3,$3,$2\n"                                             \
-            "mtc1   $3,$20\n"                                               \
-            "nop; nop; nop\n"                                               \
-            :                                                               \
-            : "r"((_vector_) - CYGNUM_HAL_INTERRUPT_PMC1)                   \
-            : "$2", "$3"                                                    \
-            );                                                              \
-    }                                                                       \
-    CYG_MACRO_END
-
-#define HAL_INTERRUPT_UNMASK( _vector_ )                                    \
-    CYG_MACRO_START                                                         \
-    if( (_vector_) <= CYGNUM_HAL_INTERRUPT_COMPARE )                        \
-    {                                                                       \
-        asm volatile (                                                      \
-            "mfc0   $3,$12\n"                                               \
-            "la     $2,0x00000400\n"                                        \
-            "sllv   $2,$2,%0\n"                                             \
-            "or     $3,$3,$2\n"                                             \
-            "mtc0   $3,$12\n"                                               \
-            "nop; nop; nop\n"                                               \
-            :                                                               \
-            : "r"(_vector_)                                                 \
-            : "$2", "$3"                                                    \
-            );                                                              \
-    }                                                                       \
-    else if ((_vector_) >= CYGNUM_HAL_INTERRUPT_UART2)                      \
-    {                                                                       \
-        /* int 6:9 are masked in the Interrupt Control register */          \
-        asm volatile (                                                      \
-            "mfc1   $3,$20\n"                                               \
-            "la     $2,0x00000100\n"                                        \
-            "sllv   $2,$2,%0\n"                                             \
-            "or     $3,$3,$2\n"                                             \
-            "mtc1   $3,$20\n"                                               \
-            "nop; nop; nop\n"                                               \
-            :                                                               \
-            : "r"((_vector_) - CYGNUM_HAL_INTERRUPT_PMC1)                   \
-            : "$2", "$3"                                                    \
-            );                                                              \
-    }                                                                       \
-    CYG_MACRO_END
-
-#define HAL_INTERRUPT_ACKNOWLEDGE( _vector_ )                           \
-    CYG_MACRO_START                                                     \
-    /* All 10 interrupts have pending bits in the cause register */     \
-    cyg_uint32 _srvector_ = _vector_;                                   \
-    asm volatile (                                                      \
-        "mfc0   $3,$13\n"                                               \
-        "la     $2,0x00000400\n"                                        \
-        "sllv   $2,$2,%0\n"                                             \
-        "nor    $2,$2,$0\n"                                             \
-        "and    $3,$3,$2\n"                                             \
-        "mtc0   $3,$13\n"                                               \
-        "nop; nop; nop\n"                                               \
-        :                                                               \
-        : "r"(_srvector_)                                               \
-        : "$2", "$3"                                                    \
-        );                                                              \
-    CYG_MACRO_END
-
-#define HAL_INTERRUPT_CONFIGURE( _vector_, _level_, _up_ )
-
-#define HAL_INTERRUPT_SET_LEVEL( _vector_, _level_ )
-
-#define CYGHWR_HAL_INTERRUPT_CONTROLLER_ACCESS_DEFINED
-
-
 //----------------------------------------------------------------------------
 // Reset.
 // Uses Secondary Reset Bit in 21555. Don't know where it is mapped though.
--- a/packages/hal/mips/rm7000/var/current/ChangeLog
+++ b/packages/hal/mips/rm7000/var/current/ChangeLog
@@ -1,3 +1,8 @@
+2001-08-09  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* include/var_intr.h: Move HAL_INTERRUPT_ interrupt controller
+	access macros here from Ocelot HAL.
+
 2001-06-25  Jesper Skov  <jskov@redhat.com>
 
 	* include/var_cache.h: Default definition for
--- a/packages/hal/mips/rm7000/var/current/include/var_intr.h
+++ b/packages/hal/mips/rm7000/var/current/include/var_intr.h
@@ -55,6 +55,103 @@
 
 #include <cyg/hal/plf_intr.h>
 
+//--------------------------------------------------------------------------
+// Interrupt controller information
+
+#ifndef CYGHWR_HAL_INTERRUPT_CONTROLLER_ACCESS_DEFINED
+#define HAL_INTERRUPT_MASK( _vector_ )                                      \
+    CYG_MACRO_START                                                         \
+    if( (_vector_) <= CYGNUM_HAL_INTERRUPT_COMPARE )                        \
+    {                                                                       \
+        asm volatile (                                                      \
+            "mfc0   $3,$12\n"                                               \
+            "la     $2,0x00000400\n"                                        \
+            "sllv   $2,$2,%0\n"                                             \
+            "nor    $2,$2,$0\n"                                             \
+            "and    $3,$3,$2\n"                                             \
+            "mtc0   $3,$12\n"                                               \
+            "nop; nop; nop\n"                                               \
+            :                                                               \
+            : "r"(_vector_)                                                 \
+            : "$2", "$3"                                                    \
+            );                                                              \
+    }                                                                       \
+    else                                                                    \
+    {                                                                       \
+        /* int 6:9 are masked in the Interrupt Control register */          \
+        asm volatile (                                                      \
+            "cfc0   $3,$20\n"                                               \
+            "la     $2,0x00000004\n"                                        \
+            "sllv   $2,$2,%0\n"                                             \
+            "nor    $2,$2,$0\n"                                             \
+            "and    $3,$3,$2\n"                                             \
+            "ctc0   $3,$20\n"                                               \
+            "nop; nop; nop\n"                                               \
+            :                                                               \
+            : "r"((_vector_) )				                    \
+            : "$2", "$3"                                                    \
+            );                                                              \
+    }                                                                       \
+    CYG_MACRO_END
+
+#define HAL_INTERRUPT_UNMASK( _vector_ )                                    \
+    CYG_MACRO_START                                                         \
+    if( (_vector_) <= CYGNUM_HAL_INTERRUPT_COMPARE )                        \
+    {                                                                       \
+        asm volatile (                                                      \
+            "mfc0   $3,$12\n"                                               \
+            "la     $2,0x00000400\n"                                        \
+            "sllv   $2,$2,%0\n"                                             \
+            "or     $3,$3,$2\n"                                             \
+            "mtc0   $3,$12\n"                                               \
+            "nop; nop; nop\n"                                               \
+            :                                                               \
+            : "r"(_vector_)                                                 \
+            : "$2", "$3"                                                    \
+            );                                                              \
+    }                                                                       \
+    else								    \
+    {                                                                       \
+        /* int 6:9 are masked in the Interrupt Control register */          \
+        asm volatile (                                                      \
+            "cfc0   $3,$20\n"                                               \
+            "la     $2,0x00000004\n"                                        \
+            "sllv   $2,$2,%0\n"                                             \
+            "or     $3,$3,$2\n"                                             \
+            "ctc0   $3,$20\n"                                               \
+            "nop; nop; nop\n"                                               \
+            :                                                               \
+            : "r"((_vector_) )                                              \
+            : "$2", "$3"                                                    \
+            );                                                              \
+    }                                                                       \
+    CYG_MACRO_END
+
+#define HAL_INTERRUPT_ACKNOWLEDGE( _vector_ )                           \
+    CYG_MACRO_START                                                     \
+    /* All 10 interrupts have pending bits in the cause register */     \
+    cyg_uint32 _srvector_ = _vector_;                                   \
+    asm volatile (                                                      \
+        "mfc0   $3,$13\n"                                               \
+        "la     $2,0x00000400\n"                                        \
+        "sllv   $2,$2,%0\n"                                             \
+        "nor    $2,$2,$0\n"                                             \
+        "and    $3,$3,$2\n"                                             \
+        "mtc0   $3,$13\n"                                               \
+        "nop; nop; nop\n"                                               \
+        :                                                               \
+        : "r"(_srvector_)                                               \
+        : "$2", "$3"                                                    \
+        );                                                              \
+    CYG_MACRO_END
+
+#define HAL_INTERRUPT_CONFIGURE( _vector_, _level_, _up_ )
+
+#define HAL_INTERRUPT_SET_LEVEL( _vector_, _level_ )
+
+#define CYGHWR_HAL_INTERRUPT_CONTROLLER_ACCESS_DEFINED
+
+#endif
 
 //--------------------------------------------------------------------------
 // Interrupt vectors.
--- a/packages/hal/mn10300/stb/current/ChangeLog
+++ b/packages/hal/mn10300/stb/current/ChangeLog
@@ -1,3 +1,28 @@
+2001-08-03  David Howells  <dhowells@redhat.com>
+
+	* cdl/hal_mn10300_am33_stb.cdl: added vector support and made to
+	work with RedBoot and flash.
+	* include/plf_intr.h: ditto.
+	* include/plf_io.h: ditto.
+	* include/plf_stub.h: ditto.
+	* include/pkgconf/mlt_mn10300_am33_stb_rom.h: ditto.
+	* include/pkgconf/mlt_mn10300_am33_stb_rom.mlt: ditto.
+	* include/pkgconf/mlt_mn10300_am33_stb_sram1.h: ditto.
+	* include/pkgconf/mlt_mn10300_am33_stb_sram1.ldi: ditto.
+	* include/pkgconf/mlt_mn10300_am33_stb_sram1.mlt: ditto.
+	* misc/redboot_RAM.ecm: ditto.
+	* misc/redboot_ROM.ecm: ditto.
+	* misc/redboot_SRAM1.ecm: ditto.
+	* src/plf_misc.c: ditto.
+	* src/plf_stub.c: ditto.
+	* src/ser_stb.c: ditto.
+
+2001-08-02  Nick Garnett  <nickg@redhat.com>
+
+	* include/plf_io.h:
+	Added this file to match assumption now made in arch files that it
+	exists.
+
 2001-01-26  Jesper Skov  <jskov@redhat.com>
 
 	* include/plf_stub.h: Reset macros moved
--- a/packages/hal/mn10300/stb/current/cdl/hal_mn10300_am33_stb.cdl
+++ b/packages/hal/mn10300/stb/current/cdl/hal_mn10300_am33_stb.cdl
@@ -23,7 +23,7 @@
 #                                                                          
 # The Initial Developer of the Original Code is Red Hat.                   
 # Portions created by Red Hat are                                          
-# Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+# Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.                             
 # All Rights Reserved.                                                     
 # -------------------------------------------                              
 #                                                                          
@@ -50,10 +50,13 @@ cdl_package CYGPKG_HAL_MN10300_AM33_STB 
            The STB HAL package should be used when targetting the
            actual hardware for the AM33 STB evaluation board."
 
-    compile       hal_diag.c plf_stub.c plf_misc.c
+    compile       hal_diag.c plf_stub.c plf_misc.c ser_stb.c
 
     implements    CYGINT_HAL_DEBUG_GDB_STUBS
     implements    CYGINT_HAL_DEBUG_GDB_STUBS_BREAK
+    implements    CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT
+
+    requires CYGSEM_HAL_UNCACHED_FLASH_ACCESS == 1;
 
     define_proc {
         puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H   <pkgconf/hal_mn10300_am33.h>"
@@ -80,6 +83,18 @@ cdl_package CYGPKG_HAL_MN10300_AM33_STB 
            or program them into a FLASH ROM."
     }
 
+    cdl_option CYGBLD_ROM_SLOT {
+        display          "ROM startup slot"
+        flavor data
+        legal_values     {"ROM" "SRAM1"}
+        default_value    {"ROM"}
+        description      "
+           This option can be used to request that the image is to be
+           linked to be run from the SRAM1 SLOT (0x82400000) rather than
+           the system boot ROM slot (0x40000000).
+	   "
+   }
+
     cdl_option CYGHWR_HAL_MN10300_AM33_STB_DIAG_PORT {
         display          "Diagnostic Serial Port"
         flavor data
@@ -213,12 +228,50 @@ cdl_package CYGPKG_HAL_MN10300_AM33_STB 
         }
     }
 
+    cdl_option CYGNUM_HAL_BREAKPOINT_LIST_SIZE {
+        display       "Number of breakpoints supported by the HAL."
+        flavor        data
+        default_value 25
+        description   "
+            This option determines the number of breakpoints supported by the HAL."
+    }
+
+    cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS {
+        display      "Number of communication channels on the board"
+        flavor       data
+        calculated   1
+    }
+
+    cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL {
+        display          "Debug serial port"
+        flavor data
+        legal_values     0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1
+        default_value    0
+        description      "
+           The STB board has two serial ports.  Currently,
+           only the first serial port is supported. This option
+           chooses which port will be used to connect to a host
+           running GDB."
+    }
+ 
+     cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL {
+        display          "Diagnostic serial port"
+        flavor data
+        legal_values     0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1
+        default_value    0
+        description      "
+           The STB board has two serial ports. Currently,
+           only the first serial port is supported. This option
+           chooses which port will be used for diagnostic output."
+     }
+
     cdl_component CYGHWR_MEMORY_LAYOUT {
         display "Memory layout"
         flavor data
         no_define
         calculated { CYG_HAL_STARTUP == "RAM" ? "mn10300_am33_stb_ram" : \
-	                                        "mn10300_am33_stb_rom" }
+                     CYGBLD_ROM_SLOT == "ROM" ? "mn10300_am33_stb_rom" : \
+                                                "mn10300_am33_stb_sram1" }
 
         cdl_option CYGHWR_MEMORY_LAYOUT_LDI {
             display "Memory layout linker script fragment"
@@ -226,7 +279,8 @@ cdl_package CYGPKG_HAL_MN10300_AM33_STB 
             no_define
             define -file system.h CYGHWR_MEMORY_LAYOUT_LDI
             calculated { CYG_HAL_STARTUP == "RAM" ? "<pkgconf/mlt_mn10300_am33_stb_ram.ldi>" : \
-                                                    "<pkgconf/mlt_mn10300_am33_stb_rom.ldi>" }
+                         CYGBLD_ROM_SLOT == "ROM" ? "<pkgconf/mlt_mn10300_am33_stb_rom.ldi>" : \
+                                                    "<pkgconf/mlt_mn10300_am33_stb_sram1.ldi>" }
         }
 
         cdl_option CYGHWR_MEMORY_LAYOUT_H {
@@ -235,7 +289,8 @@ cdl_package CYGPKG_HAL_MN10300_AM33_STB 
             no_define
             define -file system.h CYGHWR_MEMORY_LAYOUT_H
             calculated { CYG_HAL_STARTUP == "RAM" ? "<pkgconf/mlt_mn10300_am33_stb_ram.h>" : \
-                                                    "<pkgconf/mlt_mn10300_am33_stb_rom.h>" }
+                         CYGBLD_ROM_SLOT == "ROM" ? "<pkgconf/mlt_mn10300_am33_stb_rom.h>" : \
+                                                    "<pkgconf/mlt_mn10300_am33_stb_sram1.h>" }
         }
     }
 
--- a/packages/hal/mn10300/stb/current/include/pkgconf/mlt_mn10300_am33_stb_rom.h
+++ b/packages/hal/mn10300/stb/current/include/pkgconf/mlt_mn10300_am33_stb_rom.h
@@ -11,7 +11,7 @@
 #define CYGMEM_REGION_rom_SIZE (0x400000)
 #define CYGMEM_REGION_rom_ATTR (CYGMEM_REGION_ATTR_R)
 #define CYGMEM_REGION_ram (0x50000400)
-#define CYGMEM_REGION_ram_SIZE (0x800000)
+#define CYGMEM_REGION_ram_SIZE (0x7ffc00)
 #define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W)
 #ifndef __ASSEMBLER__
 extern char CYG_LABEL_NAME (__heap1) [];
--- a/packages/hal/mn10300/stb/current/include/pkgconf/mlt_mn10300_am33_stb_rom.mlt
+++ b/packages/hal/mn10300/stb/current/include/pkgconf/mlt_mn10300_am33_stb_rom.mlt
@@ -1,13 +1,13 @@
 version 0
-region rom 40000000 400000 1 !
-region ram 50000400 800000 0 !
-section rom_vectors 0 1 0 1 1 1 1 1 40000000 40000000 text text !
+region rom 82400000 400000 1 !
+region ram 90000400 7ffc00 0 !
+section rom_vectors 0 1 0 1 1 1 1 1 82400000 82400000 text text !
 section text 0 1 0 1 0 1 0 1 fini fini !
 section fini 0 1 0 1 0 1 0 1 rodata rodata !
 section rodata 0 1 0 1 0 1 0 1 rodata1 rodata1 !
 section rodata1 0 1 0 1 0 1 0 1 fixup fixup !
 section fixup 0 1 0 1 0 1 0 1 gcc_except_table gcc_except_table !
 section gcc_except_table 0 1 0 1 0 0 0 1 data !
-section data 0 1 1 1 1 1 0 0 50000400 bss !
+section data 0 1 1 1 1 1 0 0 90000400 bss !
 section bss 0 4 0 1 0 1 0 1 heap1 heap1 !
 section heap1 0 8 0 0 0 0 0 0 !
new file mode 100644
--- /dev/null
+++ b/packages/hal/mn10300/stb/current/include/pkgconf/mlt_mn10300_am33_stb_sram1.h
@@ -0,0 +1,20 @@
+// eCos memory layout - Fri Oct 20 09:14:22 2000
+
+// This is a generated file - do not edit
+
+#ifndef __ASSEMBLER__
+#include <cyg/infra/cyg_type.h>
+#include <stddef.h>
+
+#endif
+#define CYGMEM_REGION_rom (0x80400000)
+#define CYGMEM_REGION_rom_SIZE (0x400000)
+#define CYGMEM_REGION_rom_ATTR (CYGMEM_REGION_ATTR_R)
+#define CYGMEM_REGION_ram (0x50000400)
+#define CYGMEM_REGION_ram_SIZE (0x7ffc00)
+#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W)
+#ifndef __ASSEMBLER__
+extern char CYG_LABEL_NAME (__heap1) [];
+#endif
+#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1))
+#define CYGMEM_SECTION_heap1_SIZE (0x50800000 - (size_t) CYG_LABEL_NAME (__heap1))
new file mode 100644
--- /dev/null
+++ b/packages/hal/mn10300/stb/current/include/pkgconf/mlt_mn10300_am33_stb_sram1.ldi
@@ -0,0 +1,27 @@
+// eCos memory layout - Fri Oct 20 09:14:22 2000
+
+// This is a generated file - do not edit
+
+#include <cyg/infra/cyg_type.inc>
+
+MEMORY
+{
+    sram1 : ORIGIN = 0x80400000, LENGTH = 0x400000
+    ram   : ORIGIN = 0x50000000, LENGTH = 0x800000
+}
+
+SECTIONS
+{
+    SECTIONS_BEGIN
+    SECTION_rom_vectors (sram1, 0x80400000, LMA_EQ_VMA)
+    SECTION_text (sram1, ALIGN (0x1), LMA_EQ_VMA)
+    SECTION_fini (sram1, ALIGN (0x1), LMA_EQ_VMA)
+    SECTION_rodata (sram1, ALIGN (0x1), LMA_EQ_VMA)
+    SECTION_rodata1 (sram1, ALIGN (0x1), LMA_EQ_VMA)
+    SECTION_fixup (sram1, ALIGN (0x1), LMA_EQ_VMA)
+    SECTION_gcc_except_table (sram1, ALIGN (0x1), LMA_EQ_VMA)
+    SECTION_data (sram1, ALIGN (0x1), LMA_EQ_VMA)
+    SECTION_bss (ram, 0x50000400, FOLLOWING (.data))
+    CYG_LABEL_DEFN(__heap1) = ALIGN (0x8);
+    SECTIONS_END
+}
new file mode 100644
--- /dev/null
+++ b/packages/hal/mn10300/stb/current/include/pkgconf/mlt_mn10300_am33_stb_sram1.mlt
@@ -0,0 +1,13 @@
+version 0
+region rom 82400000 400000 1 !
+region ram 50000400 7ffc00 0 !
+section rom_vectors 0 1 0 1 1 1 1 1 82400000 82400000 text text !
+section text 0 1 0 1 0 1 0 1 fini fini !
+section fini 0 1 0 1 0 1 0 1 rodata rodata !
+section rodata 0 1 0 1 0 1 0 1 rodata1 rodata1 !
+section rodata1 0 1 0 1 0 1 0 1 fixup fixup !
+section fixup 0 1 0 1 0 1 0 1 gcc_except_table gcc_except_table !
+section gcc_except_table 0 1 0 1 0 0 0 1 data !
+section data 0 1 1 1 1 1 0 0 50000400 bss !
+section bss 0 4 0 1 0 1 0 1 heap1 heap1 !
+section heap1 0 8 0 0 0 0 0 0 !
--- a/packages/hal/mn10300/stb/current/include/plf_intr.h
+++ b/packages/hal/mn10300/stb/current/include/plf_intr.h
@@ -26,7 +26,7 @@
 //                                                                          
 // The Initial Developer of the Original Code is Red Hat.                   
 // Portions created by Red Hat are                                          
-// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.                             
 // All Rights Reserved.                                                     
 // -------------------------------------------                              
 //                                                                          
@@ -71,8 +71,15 @@ externC cyg_uint32 hal_ctrlc_isr(CYG_ADD
 
 //----------------------------------------------------------------------------
 // Reset.
+#ifndef CYGHWR_HAL_RESET_DEFINED
+extern void hal_stb_reset( void );
+#define CYGHWR_HAL_RESET_DEFINED
 #define HAL_PLATFORM_RESET()             CYG_EMPTY_STATEMENT
 
+#define HAL_PLATFORM_RESET_ENTRY           0x40000000
+
+#endif // CYGHWR_HAL_RESET_DEFINED
+
 //--------------------------------------------------------------------------
 #endif // ifndef CYGONCE_HAL_PLF_INTR_H
 // End of plf_intr.h
new file mode 100644
--- /dev/null
+++ b/packages/hal/mn10300/stb/current/include/plf_io.h
@@ -0,0 +1,132 @@
+#ifndef CYGONCE_PLF_IO_H
+#define CYGONCE_PLF_IO_H
+
+//=============================================================================
+//
+//      plf_io.h
+//
+//      Platform specific IO support
+//
+//=============================================================================
+//####COPYRIGHTBEGIN####
+//
+// -------------------------------------------
+// The contents of this file are subject to the Red Hat eCos Public License
+// Version 1.1 (the "License"); you may not use this file except in
+// compliance with the License.  You may obtain a copy of the License at
+// http://www.redhat.com/
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the
+// License for the specific language governing rights and limitations under
+// the License.
+//
+// The Original Code is eCos - Embedded Configurable Operating System,
+// released September 30, 1998.
+//
+// The Initial Developer of the Original Code is Red Hat.
+// Portions created by Red Hat are
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.
+// All Rights Reserved.
+// -------------------------------------------
+//
+//####COPYRIGHTEND####
+//=============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    nickg
+// Contributors: dhowells
+// Date:         2001-08-02
+// Purpose:      STB platform IO support
+// Description:
+// Usage:        #include <cyg/hal/plf_io.h>
+//
+//####DESCRIPTIONEND####
+//
+//=============================================================================
+
+#include <pkgconf/hal.h>
+
+#ifdef __ASSEMBLER__
+#define HAL_REG_8(x)              x
+#define HAL_REG_16(x)             x
+#define HAL_REG_32(x)             x
+#else
+#define HAL_REG_8(x)              (volatile cyg_uint8*)(x)
+#define HAL_REG_16(x)             (volatile cyg_uint16*)(x)
+#define HAL_REG_32(x)             (volatile cyg_uint32*)(x)
+#endif
+
+//-----------------------------------------------------------------------------
+
+/* STB GPIO Registers */
+#define HAL_GPIO_BASE                           0xDB000000
+
+#define HAL_GPIO_0_MODE_OFFSET                  0x0000
+#define HAL_GPIO_0_IN_OFFSET                    0x0004
+#define HAL_GPIO_0_OUT_OFFSET                   0x0008
+#define HAL_GPIO_1_MODE_OFFSET                  0x0100
+#define HAL_GPIO_1_IN_OFFSET                    0x0104
+#define HAL_GPIO_1_OUT_OFFSET                   0x0108
+#define HAL_GPIO_2_MODE_OFFSET                  0x0200
+#define HAL_GPIO_2_IN_OFFSET                    0x0204
+#define HAL_GPIO_2_OUT_OFFSET                   0x0208
+#define HAL_GPIO_3_MODE_OFFSET                  0x0300
+#define HAL_GPIO_3_IN_OFFSET                    0x0304
+#define HAL_GPIO_3_OUT_OFFSET                   0x0308
+#define HAL_GPIO_4_MODE_OFFSET                  0x0400
+#define HAL_GPIO_4_IN_OFFSET                    0x0404
+#define HAL_GPIO_4_OUT_OFFSET                   0x0408
+#define HAL_GPIO_5_MODE_OFFSET                  0x0500
+#define HAL_GPIO_5_IN_OFFSET                    0x0504
+#define HAL_GPIO_5_OUT_OFFSET                   0x0508
+
+#define HAL_GPIO_0_MODE                         HAL_REG_16 (HAL_GPIO_BASE + HAL_GPIO_0_MODE_OFFSET)
+#define HAL_GPIO_0_IN                           HAL_REG_8  (HAL_GPIO_BASE + HAL_GPIO_0_IN_OFFSET)
+#define HAL_GPIO_0_OUT                          HAL_REG_8  (HAL_GPIO_BASE + HAL_GPIO_0_OUT_OFFSET)
+#define HAL_GPIO_1_MODE                         HAL_REG_16 (HAL_GPIO_BASE + HAL_GPIO_1_MODE_OFFSET)
+#define HAL_GPIO_1_IN                           HAL_REG_8  (HAL_GPIO_BASE + HAL_GPIO_1_IN_OFFSET)
+#define HAL_GPIO_1_OUT                          HAL_REG_8  (HAL_GPIO_BASE + HAL_GPIO_1_OUT_OFFSET)
+#define HAL_GPIO_2_MODE                         HAL_REG_16 (HAL_GPIO_BASE + HAL_GPIO_2_MODE_OFFSET)
+#define HAL_GPIO_2_IN                           HAL_REG_8  (HAL_GPIO_BASE + HAL_GPIO_2_IN_OFFSET)
+#define HAL_GPIO_2_OUT                          HAL_REG_8  (HAL_GPIO_BASE + HAL_GPIO_2_OUT_OFFSET)
+#define HAL_GPIO_3_MODE                         HAL_REG_16 (HAL_GPIO_BASE + HAL_GPIO_3_MODE_OFFSET)
+#define HAL_GPIO_3_IN                           HAL_REG_8  (HAL_GPIO_BASE + HAL_GPIO_3_IN_OFFSET)
+#define HAL_GPIO_3_OUT                          HAL_REG_8  (HAL_GPIO_BASE + HAL_GPIO_3_OUT_OFFSET)
+#define HAL_GPIO_4_MODE                         HAL_REG_16 (HAL_GPIO_BASE + HAL_GPIO_4_MODE_OFFSET)
+#define HAL_GPIO_4_IN                           HAL_REG_8  (HAL_GPIO_BASE + HAL_GPIO_4_IN_OFFSET)
+#define HAL_GPIO_4_OUT                          HAL_REG_8  (HAL_GPIO_BASE + HAL_GPIO_4_OUT_OFFSET)
+#define HAL_GPIO_5_MODE                         HAL_REG_16 (HAL_GPIO_BASE + HAL_GPIO_5_MODE_OFFSET)
+#define HAL_GPIO_5_IN                           HAL_REG_8  (HAL_GPIO_BASE + HAL_GPIO_5_IN_OFFSET)
+#define HAL_GPIO_5_OUT                          HAL_REG_8  (HAL_GPIO_BASE + HAL_GPIO_5_OUT_OFFSET)
+
+//-----------------------------------------------------------------------------
+#define HAL_LED_ADDRESS                         0x83f90000
+#define HAL_GPIO_MODE_ALL_OUTPUT                0x5555
+
+
+#ifdef __ASSEMBLER__
+
+#  include <cyg/hal/platform.inc>
+#  define DEBUG_DISPLAY(hexdig)   hal_diag_led hexdig
+#  define DEBUG_DELAY()                                        \
+     mov    0x20000, d0;                                       \
+0:   sub    1, d0;                                             \
+     bne    0b;                                                \
+     nop
+
+#else
+
+extern cyg_uint8 cyg_hal_plf_led_val(CYG_WORD hexdig);
+#  define DEBUG_DISPLAY(hexdig) HAL_WRITE_UINT8(HAL_LED_ADDRESS, cyg_hal_plf_led_val(hexdig))
+#  define DEBUG_DELAY()                                        \
+   {                                                           \
+     volatile int i = 0x80000;                                 \
+     while (--i) ;                                             \
+   }
+
+#endif
+
+//-----------------------------------------------------------------------------
+// end of plf_io.h
+#endif // CYGONCE_PLF_IO_H
--- a/packages/hal/mn10300/stb/current/include/plf_stub.h
+++ b/packages/hal/mn10300/stb/current/include/plf_stub.h
@@ -26,7 +26,7 @@
 //                                                                          
 // The Initial Developer of the Original Code is Red Hat.                   
 // Portions created by Red Hat are                                          
-// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.                             
 // All Rights Reserved.                                                     
 // -------------------------------------------                              
 //                                                                          
@@ -54,19 +54,18 @@
 #include <cyg/hal/mn10300_stub.h>       // architecture stub support
 
 //----------------------------------------------------------------------------
-// Define serial stuff.
-extern void hal_stb_init_serial( void );
-extern int  hal_stb_get_char( void );
-extern void hal_stb_put_char( int c );
-extern int  hal_stb_interruptible(int state);
-extern void hal_stb_init_break_irq( void );
+// Define some platform specific communication details. This is mostly
+// handled by hal_if now, but we need to make sure the comms tables are
+// properly initialized.
+
+externC void cyg_hal_plf_comms_init(void);
 
-#define HAL_STUB_PLATFORM_INIT_SERIAL()       hal_stb_init_serial()
-#define HAL_STUB_PLATFORM_GET_CHAR()          hal_stb_get_char()
-#define HAL_STUB_PLATFORM_PUT_CHAR(c)         hal_stb_put_char((c))
-#define HAL_STUB_PLATFORM_SET_BAUD_RATE(baud) CYG_UNUSED_PARAM(int, (baud))
+#define HAL_STUB_PLATFORM_INIT_SERIAL()       cyg_hal_plf_comms_init()
+#define HAL_STUB_PLATFORM_GET_CHAR()          cyg_hal_plf_serial_getc(0)
+#define HAL_STUB_PLATFORM_PUT_CHAR(c)         cyg_hal_plf_serial_putc(0, (c))
+#define HAL_STUB_PLATFORM_SET_BAUD_RATE(baud) cyg_hal_plf_serial_setbaud(0, (baud))
 #define HAL_STUB_PLATFORM_INTERRUPTIBLE       (&hal_stb_interruptible)
-#define HAL_STUB_PLATFORM_INIT_BREAK_IRQ()    hal_stb_init_break_irq()
+#define HAL_STUB_PLATFORM_INIT_BREAK_IRQ()    CYG_EMPTY_STATEMENT
 
 //----------------------------------------------------------------------------
 // Stub initializer.
new file mode 100644
--- /dev/null
+++ b/packages/hal/mn10300/stb/current/misc/redboot_RAM.ecm
@@ -0,0 +1,61 @@
+cdl_savefile_version 1;
+cdl_savefile_command cdl_savefile_version {};
+cdl_savefile_command cdl_savefile_command {};
+cdl_savefile_command cdl_configuration { description hardware template package };
+cdl_savefile_command cdl_package { value_source user_value wizard_value inferred_value };
+cdl_savefile_command cdl_component { value_source user_value wizard_value inferred_value };
+cdl_savefile_command cdl_option { value_source user_value wizard_value inferred_value };
+cdl_savefile_command cdl_interface { value_source user_value wizard_value inferred_value };
+
+cdl_configuration eCos {
+    description "" ;
+    hardware    stb ;
+    template    redboot ;
+    package -hardware CYGPKG_HAL_MN10300 current ;
+    package -hardware CYGPKG_HAL_MN10300_AM33_STB current ;
+    package -hardware CYGPKG_HAL_MN10300_AM33 current ;
+    package -hardware CYGPKG_IO_SERIAL_MN10300 current ;
+    package -hardware CYGPKG_DEVICES_WATCHDOG_MN10300_MN10300 current ;
+    package -template CYGPKG_HAL current ;
+    package -template CYGPKG_INFRA current ;
+    package -template CYGPKG_REDBOOT current ;
+
+#    package CYGPKG_IO_ETH_DRIVERS current ;
+#    package CYGPKG_DEVS_ETH_CF current ;
+    package CYGPKG_IO_FLASH current ;
+    package CYGPKG_DEVS_FLASH_AMD_AM29XXXXX current ;
+};
+
+cdl_option CYGBLD_BUILD_GDB_STUBS {
+    user_value 0
+};
+
+cdl_option CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT {
+    user_value 0
+};
+
+cdl_option CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM {
+    inferred_value 0
+};
+
+cdl_option CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS {
+    inferred_value 1
+};
+
+cdl_option CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT {
+    inferred_value 1
+};
+
+cdl_option CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT {
+    inferred_value 0
+};
+
+cdl_option CYGSEM_HAL_USE_ROM_MONITOR {
+    inferred_value 0 0
+};
+
+cdl_component CYGBLD_BUILD_REDBOOT {
+    user_value 1
+};
+
+
new file mode 100644
--- /dev/null
+++ b/packages/hal/mn10300/stb/current/misc/redboot_ROM.ecm
@@ -0,0 +1,70 @@
+cdl_savefile_version 1;
+cdl_savefile_command cdl_savefile_version {};
+cdl_savefile_command cdl_savefile_command {};
+cdl_savefile_command cdl_configuration { description hardware template package };
+cdl_savefile_command cdl_package { value_source user_value wizard_value inferred_value };
+cdl_savefile_command cdl_component { value_source user_value wizard_value inferred_value };
+cdl_savefile_command cdl_option { value_source user_value wizard_value inferred_value };
+cdl_savefile_command cdl_interface { value_source user_value wizard_value inferred_value };
+
+cdl_configuration eCos {
+    description "" ;
+    hardware    stb ;
+    template    redboot ;
+    package -hardware CYGPKG_HAL_MN10300 current ;
+    package -hardware CYGPKG_HAL_MN10300_AM33_STB current ;
+    package -hardware CYGPKG_HAL_MN10300_AM33 current ;
+    package -hardware CYGPKG_IO_SERIAL_MN10300 current ;
+    package -hardware CYGPKG_DEVICES_WATCHDOG_MN10300_MN10300 current ;
+    package -template CYGPKG_HAL current ;
+    package -template CYGPKG_INFRA current ;
+    package -template CYGPKG_REDBOOT current ;
+
+#    package CYGPKG_IO_ETH_DRIVERS current ;
+#    package CYGPKG_DEVS_ETH_CF current ;
+    package CYGPKG_IO_FLASH current ;
+    package -hardware CYGPKG_DEVS_FLASH_MN10300_STB current ;
+    package CYGPKG_DEVS_FLASH_AMD_AM29XXXXX current ;
+};
+
+cdl_option CYGBLD_BUILD_GDB_STUBS {
+    user_value 0
+};
+
+cdl_option CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT {
+    user_value 0
+};
+
+cdl_option CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM {
+    inferred_value 0
+};
+
+cdl_option CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS {
+    inferred_value 1
+};
+
+cdl_option CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT {
+    inferred_value 1
+};
+
+cdl_option CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT {
+    inferred_value 0
+};
+
+cdl_option CYGSEM_HAL_USE_ROM_MONITOR {
+    inferred_value 0 0
+};
+
+cdl_option CYGSEM_HAL_ROM_MONITOR {
+    inferred_value 1
+};
+
+cdl_component CYG_HAL_STARTUP {
+    user_value ROM
+};
+
+cdl_component CYGBLD_BUILD_REDBOOT {
+    user_value 1
+};
+
+
new file mode 100644
--- /dev/null
+++ b/packages/hal/mn10300/stb/current/misc/redboot_SRAM1.ecm
@@ -0,0 +1,74 @@
+cdl_savefile_version 1;
+cdl_savefile_command cdl_savefile_version {};
+cdl_savefile_command cdl_savefile_command {};
+cdl_savefile_command cdl_configuration { description hardware template package };
+cdl_savefile_command cdl_package { value_source user_value wizard_value inferred_value };
+cdl_savefile_command cdl_component { value_source user_value wizard_value inferred_value };
+cdl_savefile_command cdl_option { value_source user_value wizard_value inferred_value };
+cdl_savefile_command cdl_interface { value_source user_value wizard_value inferred_value };
+
+cdl_configuration eCos {
+    description "" ;
+    hardware    stb ;
+    template    redboot ;
+    package -hardware CYGPKG_HAL_MN10300 current ;
+    package -hardware CYGPKG_HAL_MN10300_AM33_STB current ;
+    package -hardware CYGPKG_HAL_MN10300_AM33 current ;
+    package -hardware CYGPKG_IO_SERIAL_MN10300 current ;
+    package -hardware CYGPKG_DEVICES_WATCHDOG_MN10300_MN10300 current ;
+    package -template CYGPKG_HAL current ;
+    package -template CYGPKG_INFRA current ;
+    package -template CYGPKG_REDBOOT current ;
+
+#    package CYGPKG_IO_ETH_DRIVERS current ;
+#    package CYGPKG_DEVS_ETH_CF current ;
+    package CYGPKG_IO_FLASH current ;
+    package -hardware CYGPKG_DEVS_FLASH_MN10300_STB current ;
+    package CYGPKG_DEVS_FLASH_AMD_AM29XXXXX current ;
+ };
+
+cdl_option CYGBLD_BUILD_GDB_STUBS {
+    user_value 0
+};
+
+cdl_option CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT {
+    user_value 0
+};
+
+cdl_option CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM {
+    inferred_value 0
+};
+
+cdl_option CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS {
+    inferred_value 1
+};
+
+cdl_option CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT {
+    inferred_value 1
+};
+
+cdl_option CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT {
+    inferred_value 0
+};
+
+cdl_option CYGSEM_HAL_USE_ROM_MONITOR {
+    inferred_value 0 0
+};
+
+cdl_option CYGSEM_HAL_ROM_MONITOR {
+    inferred_value 1
+};
+
+cdl_component CYG_HAL_STARTUP {
+    user_value ROM
+};
+
+cdl_option CYGBLD_ROM_SLOT {
+    user_value SRAM1
+};
+
+cdl_component CYGBLD_BUILD_REDBOOT {
+    user_value 1
+};
+
+
--- a/packages/hal/mn10300/stb/current/src/plf_misc.c
+++ b/packages/hal/mn10300/stb/current/src/plf_misc.c
@@ -23,7 +23,7 @@
 //                                                                          
 // The Initial Developer of the Original Code is Red Hat.                   
 // Portions created by Red Hat are                                          
-// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.                             
 // All Rights Reserved.                                                     
 // -------------------------------------------                              
 //                                                                          
@@ -32,7 +32,7 @@
 //#####DESCRIPTIONBEGIN####
 //
 // Author(s):    nickg
-// Contributors: nickg, jlarmour
+// Contributors: nickg, jlarmour, dhowells
 // Date:         1999-01-21
 // Purpose:      HAL miscellaneous functions
 // Description:  This file contains miscellaneous functions provided by the
@@ -54,10 +54,41 @@
 
 #include <cyg/hal/hal_cache.h>          // Cache handling
 
+#include <cyg/hal/hal_if.h>
+
+#include <cyg/hal/plf_io.h>
+
+/*------------------------------------------------------------------------*/
+/* LED support                                                            */
+cyg_uint8 cyg_hal_plf_led_val(CYG_WORD hexdig)
+{
+    static cyg_uint8 map[] = {
+        0x81, // 0
+        0xf3, // 1
+        0x49, // 2
+        0x61, // 3
+        0x33, // 4
+        0x25, // 5
+        0x05, // 6
+        0xf1, // 7
+        0x01, // 8
+        0x21, // 9
+        0x11, // A
+        0x07, // B
+        0x8d, // C
+        0x43, // D
+        0x0d, // E
+        0x1d  // F
+    };
+    return map[(hexdig & 0xF)];
+}
+
 /*------------------------------------------------------------------------*/
 
 void hal_platform_init(void)
 {
+    HAL_WRITE_UINT8(HAL_LED_ADDRESS, cyg_hal_plf_led_val(8));
+
 #if defined(CYG_HAL_STARTUP_ROM)
     // Note that the hardware seems to come up with the
     // caches containing random data. Hence they must be
@@ -68,11 +99,14 @@ void hal_platform_init(void)
     // is not expecting it, we can end up breaking things if the
     // monitor is not doing cache flushes.
 
-    HAL_ICACHE_INVALIDATE_ALL();    
-    HAL_ICACHE_ENABLE();
-    HAL_DCACHE_INVALIDATE_ALL();
-    HAL_DCACHE_ENABLE();
+    //HAL_ICACHE_INVALIDATE_ALL();    
+    //HAL_ICACHE_ENABLE();
+    //HAL_DCACHE_INVALIDATE_ALL();
+    //HAL_DCACHE_ENABLE();
 #endif
+
+    // Set up eCos/ROM interfaces
+    hal_if_init();
     
 #if defined(CYGPKG_KERNEL)                      && \
     defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT)   && \
@@ -92,50 +126,6 @@ void hal_platform_init(void)
 }
 
 /*------------------------------------------------------------------------*/
-/* Functions to support the detection and execution of a user provoked    */
-/* program break. These are usually called from interrupt routines.       */
-
-cyg_bool cyg_hal_is_break(char *buf, int size)
-{
-    while( size )
-        if( buf[--size] == 0x03 ) return true;
-
-    return false;
-}
-
-void cyg_hal_user_break( CYG_ADDRWORD *regs )
-{
-#if defined(CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs)
-
-        {
-            extern CYG_ADDRESS hal_virtual_vector_table[64];        
-            typedef void install_bpt_fn(void *pc);
-            CYG_WORD32 retpc = ((CYG_WORD32 *)(&regs))[-1];
-            CYG_WORD32 pc;
-            HAL_SavedRegisters *sreg = (HAL_SavedRegisters *)regs;
-            install_bpt_fn *ibp = (install_bpt_fn *)hal_virtual_vector_table[35];
-
-            if( regs == NULL ) pc = retpc;
-            else pc = sreg->pc;
-
-            if( ibp != NULL ) ibp((void *)pc);
-        }
-    
-#elif defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
-
-        {
-            extern void breakpoint(void);
-            breakpoint();
-        }
-    
-#else
-
-        HAL_BREAKPOINT(breakinst);
-
-#endif
-}
-
-/*------------------------------------------------------------------------*/
 /* Control C ISR support                                                  */
 
 #if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT)
--- a/packages/hal/mn10300/stb/current/src/plf_stub.c
+++ b/packages/hal/mn10300/stb/current/src/plf_stub.c
@@ -23,7 +23,7 @@
 //                                                                          
 // The Initial Developer of the Original Code is Red Hat.                   
 // Portions created by Red Hat are                                          
-// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.                             
 // All Rights Reserved.                                                     
 // -------------------------------------------                              
 //                                                                          
@@ -32,7 +32,7 @@
 //#####DESCRIPTIONBEGIN####
 //
 // Author(s):   nickg, jskov (based on the old mn10300 hal_stub.c)
-// Contributors:nickg, jskov
+// Contributors:nickg, jskov, dhowells
 // Date:        1999-02-12
 // Purpose:     Platform specific code for GDB stub support.
 //              
@@ -122,50 +122,6 @@ void hal_stb_init_break_irq( void )
 }
 #endif
 
-// Initialize the current serial port.
-void hal_stb_init_serial( void )
-{
-    // 99 translates to 38400 baud.
-    HAL_WRITE_UINT8 (TIMER0_BR, 99);
-
-    // Timer0 sourced from IOCLK
-    HAL_WRITE_UINT8 (TIMER0_MD, 0x80);
-
-    // No interrupts for now.
-    HAL_WRITE_UINT8 (SERIAL0_ICR, 0x00);
-
-    // Source from timer 1, 8bit chars, enable tx and rx
-    HAL_WRITE_UINT16 (SERIAL0_CR, 0xc085);
-
-}
-
-// Write C to the current serial port.
-void hal_stb_put_char( int c )
-{
-    cyg_uint16 sr;
-
-    do {
-        HAL_READ_UINT16 (SERIAL0_SR, sr);
-    } while ((sr & SIO1_LSTAT_TRDY) != 0);
-
-    HAL_WRITE_UINT8 (SERIAL0_TXR, c);
-}
-
-// Read one character from the current serial port.
-int hal_stb_get_char( void )
-{
-    char c;
-    cyg_uint16 sr;
-
-    do {
-        HAL_READ_UINT16 (SERIAL0_SR, sr);
-    } while ((sr & SIO1_LSTAT_RRDY) == 0);
-
-    HAL_READ_UINT8 (SERIAL0_RXR, c);
-
-    return c;
-}
-
 //-----------------------------------------------------------------------------
 
 void hal_stb_platform_init(void)
new file mode 100644
--- /dev/null
+++ b/packages/hal/mn10300/stb/current/src/ser_stb.c
@@ -0,0 +1,587 @@
+//=============================================================================
+//
+//      ser_stb.c
+//
+//      Simple driver for the serial controllers on the AM33 STB board
+//
+//=============================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.                             
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//=============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):   dhowells
+// Contributors:dmoseley
+// Date:        2000-08-11
+// Description: Simple driver for the 16c550c serial controller
+//
+//####DESCRIPTIONEND####
+//
+//=============================================================================
+
+#include <pkgconf/hal.h>
+
+#include <cyg/hal/hal_arch.h>           // SAVE/RESTORE GP macros
+#include <cyg/hal/hal_io.h>             // IO macros
+#include <cyg/hal/hal_if.h>             // interface API
+#include <cyg/hal/hal_intr.h>           // HAL_ENABLE/MASK/UNMASK_INTERRUPTS
+#include <cyg/hal/hal_misc.h>           // Helper functions
+#include <cyg/hal/drv_api.h>            // CYG_ISR_HANDLED
+
+//-----------------------------------------------------------------------------
+// Base Registers
+#define STB_SER0_BASE      0xD4002000
+#define STB_SER1_BASE      0xD4002010
+
+/*---------------------------------------------------------------------------*/
+// MN10300 Serial line
+
+#define _SERIAL_CR       0x00
+#define _SERIAL_ICR      0x04
+#define _SERIAL_TXR      0x08
+#define _SERIAL_RXR      0x09
+#define _SERIAL_SR       0x0c
+
+#define SERIAL0_CR       ((volatile cyg_uint16 *)(STB_SER0_BASE + _SERIAL_CR))
+#define SERIAL0_ICR      ((volatile cyg_uint8 *) (STB_SER0_BASE + _SERIAL_ICR))
+#define SERIAL0_TXR      ((volatile cyg_uint8 *) (STB_SER0_BASE + _SERIAL_TXR))
+#define SERIAL0_RXR      ((volatile cyg_uint8 *) (STB_SER0_BASE + _SERIAL_RXR))
+#define SERIAL0_SR       ((volatile cyg_uint16 *)(STB_SER0_BASE + _SERIAL_SR))
+
+#define SERIAL1_CR       ((volatile cyg_uint16 *)(STB_SER1_BASE + _SERIAL_CR))
+#define SERIAL1_ICR      ((volatile cyg_uint8 *) (STB_SER1_BASE + _SERIAL_ICR))
+#define SERIAL1_TXR      ((volatile cyg_uint8 *) (STB_SER1_BASE + _SERIAL_TXR))
+#define SERIAL1_RXR      ((volatile cyg_uint8 *) (STB_SER1_BASE + _SERIAL_RXR))
+#define SERIAL1_SR       ((volatile cyg_uint16 *)(STB_SER1_BASE + _SERIAL_SR))
+
+// Timer 0 provides a prescaler for lower baud rates
+#define TIMER0_MD       ((volatile cyg_uint8 *)0xd4003000)
+#define TIMER0_BR       ((volatile cyg_uint8 *)0xd4003010)
+
+// Timer 2 provides baud rate divisor
+#define TIMER2_MD       ((volatile cyg_uint8 *)0xd4003002)
+#define TIMER2_BR       ((volatile cyg_uint8 *)0xd4003012)
+
+// Timer 1 provides a prescaler for lower baud rates
+#define TIMER1_MD       ((volatile cyg_uint8 *)0xd4003001)
+#define TIMER1_BR       ((volatile cyg_uint8 *)0xd4003011)
+
+// Timer 3 provides baud rate divisor
+#define TIMER3_MD       ((volatile cyg_uint8 *)0xd4003003)
+#define TIMER3_BR       ((volatile cyg_uint8 *)0xd4003013)
+
+#define SIO_LSTAT_TRDY  0x20
+#define SIO_LSTAT_RRDY  0x10
+
+#define SIO_INT_ENABLE  0x11
+
+// These values are calculated based on the MN103E010 LSI Manual
+#define PRESCALAR_BASE_1200          198
+#define PRESCALAR_BASE_2400          198
+#define PRESCALAR_BASE_4800          198
+#define PRESCALAR_BASE_9600          198
+#define PRESCALAR_BASE_96002         198
+#define PRESCALAR_BASE_14400         66
+#define PRESCALAR_BASE_19200         0
+#define PRESCALAR_BASE_38400         0
+#define PRESCALAR_BASE_56000         0
+#define PRESCALAR_BASE_57600         0
+#define PRESCALAR_BASE_115200        0
+#define PRESCALAR_BASE_230400        0
+
+#define TIMER_BASE_1200              15
+#define TIMER_BASE_2400              7
+#define TIMER_BASE_4800              3
+#define TIMER_BASE_9600              1
+#define TIMER_BASE_96002             2
+#define TIMER_BASE_14400             3
+#define TIMER_BASE_19200             198
+#define TIMER_BASE_38400             99
+#define TIMER_BASE_56000             68
+#define TIMER_BASE_57600             66
+#define TIMER_BASE_115200            33
+#define TIMER_BASE_230400            16
+
+#define TMR_ENABLE                   0x80
+#define TMR_SRC_IOCLOCK              0x00
+#define TMR_SRC_TMR0_UNDERFLOW       0x04
+
+#define PRESCALAR_MODE_1200          (TMR_ENABLE | TMR_SRC_IOCLOCK)
+#define PRESCALAR_MODE_2400          (TMR_ENABLE | TMR_SRC_IOCLOCK)
+#define PRESCALAR_MODE_4800          (TMR_ENABLE | TMR_SRC_IOCLOCK)
+#define PRESCALAR_MODE_9600          (TMR_ENABLE | TMR_SRC_IOCLOCK)
+#define PRESCALAR_MODE_96002         (TMR_ENABLE | TMR_SRC_IOCLOCK)
+#define PRESCALAR_MODE_14400         (TMR_ENABLE | TMR_SRC_IOCLOCK)
+#define PRESCALAR_MODE_19200         0
+#define PRESCALAR_MODE_38400         0
+#define PRESCALAR_MODE_56000         0
+#define PRESCALAR_MODE_57600         0
+#define PRESCALAR_MODE_115200        0
+#define PRESCALAR_MODE_230400        0
+
+#define TIMER_MODE_1200              (TMR_ENABLE | TMR_SRC_TMR0_UNDERFLOW)
+#define TIMER_MODE_2400              (TMR_ENABLE | TMR_SRC_TMR0_UNDERFLOW)
+#define TIMER_MODE_4800              (TMR_ENABLE | TMR_SRC_TMR0_UNDERFLOW)
+#define TIMER_MODE_9600              (TMR_ENABLE | TMR_SRC_TMR0_UNDERFLOW)
+#define TIMER_MODE_96002             (TMR_ENABLE | TMR_SRC_TMR0_UNDERFLOW)
+#define TIMER_MODE_14400             (TMR_ENABLE | TMR_SRC_TMR0_UNDERFLOW)
+#define TIMER_MODE_19200             (TMR_ENABLE | TMR_SRC_IOCLOCK)
+#define TIMER_MODE_38400             (TMR_ENABLE | TMR_SRC_IOCLOCK)
+#define TIMER_MODE_56000             (TMR_ENABLE | TMR_SRC_IOCLOCK)
+#define TIMER_MODE_57600             (TMR_ENABLE | TMR_SRC_IOCLOCK)
+#define TIMER_MODE_115200            (TMR_ENABLE | TMR_SRC_IOCLOCK)
+#define TIMER_MODE_230400            (TMR_ENABLE | TMR_SRC_IOCLOCK)
+
+#define BAUD_CASE(num)                                   \
+    case num:                                            \
+        prescalar_base_value = PRESCALAR_BASE_ ## num;   \
+        prescalar_mode_value = PRESCALAR_MODE_ ## num;   \
+        timer_base_value = TIMER_BASE_ ## num;           \
+        timer_mode_value = TIMER_MODE_ ## num;           \
+        break;
+
+//-----------------------------------------------------------------------------
+typedef struct {
+    cyg_uint8* base;
+    cyg_int32 msec_timeout;
+    int isr_vector;
+} channel_data_t;
+
+static const channel_data_t channels[2] = {
+    { (cyg_uint8*)STB_SER0_BASE, 1000, CYGNUM_HAL_INTERRUPT_SERIAL_0_RX },
+    { (cyg_uint8*)STB_SER1_BASE, 1000, CYGNUM_HAL_INTERRUPT_SERIAL_1_RX },
+};
+
+//-----------------------------------------------------------------------------
+// Set the baud rate
+
+static int
+cyg_hal_plf_serial_set_baud(cyg_uint8* port, cyg_uint32 baud_rate)
+{
+    volatile cyg_uint8 *prescalar_base_reg = 0, prescalar_base_value = 0;
+    volatile cyg_uint8 *prescalar_mode_reg = 0, prescalar_mode_value = 0;
+    volatile cyg_uint8 *timer_base_reg = 0,     timer_base_value = 0;
+    volatile cyg_uint8 *timer_mode_reg = 0,     timer_mode_value = 0;
+
+    // Always use TMR0 as the prescalar
+    prescalar_base_reg = TIMER0_BR;
+    prescalar_mode_reg = TIMER0_MD;
+
+    if (port == (cyg_uint8*)STB_SER0_BASE)
+    {
+        // SER0 uses TMR2
+        timer_base_reg = TIMER2_BR;
+        timer_mode_reg = TIMER2_MD;
+    } else if (port == (cyg_uint8*)STB_SER1_BASE) {
+        // SER1 uses TMR3
+        timer_base_reg = TIMER3_BR;
+        timer_mode_reg = TIMER3_MD;
+    } else {
+        // Unknown port.
+        return -1;
+    }
+
+    switch (baud_rate)
+    {
+        BAUD_CASE(1200);
+        BAUD_CASE(2400);
+        BAUD_CASE(4800);
+        BAUD_CASE(9600);
+        BAUD_CASE(96002);
+        BAUD_CASE(14400);
+        BAUD_CASE(19200);
+        BAUD_CASE(38400);
+        BAUD_CASE(56000);
+        BAUD_CASE(57600);
+        BAUD_CASE(115200);
+        BAUD_CASE(230400);
+
+    default:
+        // Unknown baud.  Don't change anything
+        return -1;
+    }
+
+    HAL_WRITE_UINT8(prescalar_base_reg, prescalar_base_value);
+    HAL_WRITE_UINT8(prescalar_mode_reg, prescalar_mode_value);
+    HAL_WRITE_UINT8(timer_base_reg,     timer_base_value);
+    HAL_WRITE_UINT8(timer_mode_reg,     timer_mode_value);
+
+    return 0;
+}
+
+//-----------------------------------------------------------------------------
+// The minimal init, get and put functions. All by polling.
+
+void
+cyg_hal_plf_serial_init_channel(void* __ch_data)
+{
+    cyg_uint8* port;
+
+    // Some of the diagnostic print code calls through here with no idea what the ch_data is.
+    // Go ahead and assume it is channels[0].
+    if (__ch_data == 0)
+      __ch_data = (void*)&channels[0];
+
+    port = ((channel_data_t*)__ch_data)->base;
+
+    // No interrupts for now.
+    HAL_WRITE_UINT8(port + _SERIAL_ICR, 0x00);
+
+    // Source from timer 2 or 3, 8bit chars, enable tx and rx
+    HAL_WRITE_UINT16(port + _SERIAL_CR, 0xc085);
+}
+
+void
+cyg_hal_plf_serial_putc(void* __ch_data, cyg_uint8 __ch)
+{
+    cyg_uint8* port;
+    cyg_uint16 _status;
+
+    // Some of the diagnostic print code calls through here with no idea what the ch_data is.
+    // Go ahead and assume it is channels[0].
+    if (__ch_data == 0)
+      __ch_data = (void*)&channels[0];
+
+    port = ((channel_data_t*)__ch_data)->base;
+
+    do {
+        HAL_READ_UINT16(port + _SERIAL_SR, _status);
+    } while ((_status & SIO_LSTAT_TRDY) != 0);
+
+    HAL_WRITE_UINT8(port + _SERIAL_TXR, __ch);
+}
+
+static cyg_bool
+cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch)
+{
+    cyg_uint8* port;
+    cyg_uint8 _status;
+
+    // Some of the diagnostic print code calls through here with no idea what the ch_data is.
+    // Go ahead and assume it is channels[0].
+    if (__ch_data == 0)
+      __ch_data = (void*)&channels[0];
+
+    port = ((channel_data_t*)__ch_data)->base;
+
+    HAL_READ_UINT8(port + _SERIAL_SR, _status);
+    if ((_status & SIO_LSTAT_RRDY) == 0)
+        return false;
+
+    HAL_READ_UINT8(port + _SERIAL_RXR, *ch);
+
+    // We must ack the interrupt caused by that read to avoid
+    // confusing the GDB stub ROM.
+    HAL_INTERRUPT_ACKNOWLEDGE( CYGNUM_HAL_INTERRUPT_SERIAL_0_RX );    
+
+    return true;
+}
+
+cyg_uint8
+cyg_hal_plf_serial_getc(void* __ch_data)
+{
+    cyg_uint8 ch;
+    CYGARC_HAL_SAVE_GP();
+
+    // Some of the diagnostic print code calls through here with no idea what the ch_data is.
+    // Go ahead and assume it is channels[0].
+    if (__ch_data == 0)
+      __ch_data = (void*)&channels[0];
+
+    while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch));
+
+    CYGARC_HAL_RESTORE_GP();
+    return ch;
+}
+
+void
+cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, 
+                         cyg_uint32 __len)
+{
+    CYGARC_HAL_SAVE_GP();
+
+    // Some of the diagnostic print code calls through here with no idea what the ch_data is.
+    // Go ahead and assume it is channels[0].
+    if (__ch_data == 0)
+      __ch_data = (void*)&channels[0];
+
+    while(__len-- > 0)
+        cyg_hal_plf_serial_putc(__ch_data, *__buf++);
+
+    CYGARC_HAL_RESTORE_GP();
+}
+
+static void
+cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
+{
+    CYGARC_HAL_SAVE_GP();
+
+    // Some of the diagnostic print code calls through here with no idea what the ch_data is.
+    // Go ahead and assume it is channels[0].
+    if (__ch_data == 0)
+      __ch_data = (void*)&channels[0];
+
+    while(__len-- > 0)
+        *__buf++ = cyg_hal_plf_serial_getc(__ch_data);
+
+    CYGARC_HAL_RESTORE_GP();
+}
+
+#if 1
+cyg_bool
+cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch)
+{
+    int delay_count;
+    channel_data_t* chan;
+    cyg_bool res;
+    CYGARC_HAL_SAVE_GP();
+
+    // Some of the diagnostic print code calls through here with no idea what the ch_data is.
+    // Go ahead and assume it is channels[0].
+    if (__ch_data == 0)
+      __ch_data = (void*)&channels[0];
+
+    chan = (channel_data_t*)__ch_data;
+
+    delay_count = chan->msec_timeout * 10; // delay in .1 ms steps
+
+    for(;;) {
+        res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch);
+        if (res || 0 == delay_count--)
+            break;
+        CYGACC_CALL_IF_DELAY_US(100);
+    }
+
+    CYGARC_HAL_RESTORE_GP();
+    return res;
+}
+#endif
+
+static int
+cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...)
+{
+    static int irq_state = 0;
+    channel_data_t* chan;
+    cyg_uint8 icr;
+    int ret = 0;
+    CYGARC_HAL_SAVE_GP();
+
+    // Some of the diagnostic print code calls through here with no idea what the ch_data is.
+    // Go ahead and assume it is channels[0].
+    if (__ch_data == 0)
+      __ch_data = (void*)&channels[0];
+
+    chan = (channel_data_t*)__ch_data;
+
+    switch (__func) {
+    case __COMMCTL_IRQ_ENABLE:
+        irq_state = 1;
+
+        HAL_READ_UINT8(chan->base + _SERIAL_ICR, icr);
+        icr |= SIO_INT_ENABLE;
+        HAL_WRITE_UINT8(chan->base + _SERIAL_ICR, icr);
+
+        HAL_INTERRUPT_SET_LEVEL(chan->isr_vector, 1);
+        HAL_INTERRUPT_UNMASK(chan->isr_vector);
+        break;
+
+    case __COMMCTL_IRQ_DISABLE:
+        ret = irq_state;
+        irq_state = 0;
+
+        HAL_READ_UINT8(chan->base + _SERIAL_ICR, icr);
+        icr &= ~SIO_INT_ENABLE;
+        HAL_WRITE_UINT8(chan->base + _SERIAL_ICR, icr);
+
+        HAL_INTERRUPT_MASK(chan->isr_vector);
+        break;
+
+    case __COMMCTL_DBG_ISR_VECTOR:
+        ret = chan->isr_vector;
+        break;
+
+    case __COMMCTL_SET_TIMEOUT:
+    {
+        va_list ap;
+
+        va_start(ap, __func);
+
+        ret = chan->msec_timeout;
+        chan->msec_timeout = va_arg(ap, cyg_uint32);
+
+        va_end(ap);
+    }        
+    break;
+
+    case __COMMCTL_SETBAUD:
+    {
+        cyg_uint32 baud_rate;
+        cyg_uint8* port = chan->base;
+        va_list ap;
+
+        va_start(ap, __func);
+        baud_rate = va_arg(ap, cyg_uint32);
+        va_end(ap);
+
+        // Disable port interrupts while changing hardware
+        HAL_READ_UINT8(port + _SERIAL_ICR, icr);
+        HAL_WRITE_UINT8(port + _SERIAL_ICR, 0);
+
+        // Set baud rate.
+        ret = cyg_hal_plf_serial_set_baud(port, baud_rate);
+
+        // Reenable interrupts if necessary
+        HAL_WRITE_UINT8(port + _SERIAL_ICR, icr);
+    }
+    break;
+
+    case __COMMCTL_GETBAUD:
+        break;
+
+    default:
+        break;
+    }
+
+    CYGARC_HAL_RESTORE_GP();
+    return ret;
+}
+
+static int
+cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, 
+                       CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
+{
+    int res = 0;
+    channel_data_t* chan;
+    CYGARC_HAL_SAVE_GP();
+
+    // Some of the diagnostic print code calls through here with no idea what the ch_data is.
+    // Go ahead and assume it is channels[0].
+    if (__ch_data == 0)
+      __ch_data = (void*)&channels[0];
+
+    chan = (channel_data_t*)__ch_data;
+
+    HAL_INTERRUPT_ACKNOWLEDGE(chan->isr_vector);
+
+#if 0
+    HAL_READ_UINT8(chan->base + SER_16550_IIR, _iir);
+    _iir &= SIO_IIR_ID_MASK;
+
+    *__ctrlc = 0;
+    if ((_iir == ISR_Rx_Avail) || (_iir == ISR_Rx_Char_Timeout)) {
+
+        HAL_READ_UINT8(chan->base + SER_16550_RBR, c);
+    
+        if( cyg_hal_is_break( &c , 1 ) )
+            *__ctrlc = 1;
+
+        res = CYG_ISR_HANDLED;
+    }
+#endif
+
+    CYGARC_HAL_RESTORE_GP();
+    return res;
+}
+
+static void
+cyg_hal_plf_serial_init(void)
+{
+    hal_virtual_comm_table_t* comm;
+    int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
+
+    // Disable interrupts.
+    HAL_INTERRUPT_MASK(channels[0].isr_vector);
+    HAL_INTERRUPT_MASK(channels[1].isr_vector);
+
+    // Init channels
+    cyg_hal_plf_serial_init_channel((void*)&channels[0]);
+    cyg_hal_plf_serial_set_baud(channels[0].base, CYGHWR_HAL_MN10300_AM33_STB_DIAG_BAUD);
+
+    cyg_hal_plf_serial_init_channel((void*)&channels[1]);
+    cyg_hal_plf_serial_set_baud(channels[1].base, CYGHWR_HAL_MN10300_AM33_STB_GDB_BAUD);
+    
+    // Setup procs in the vector table
+
+    // Set channel 0
+    CYGACC_CALL_IF_SET_CONSOLE_COMM(0);
+    comm = CYGACC_CALL_IF_CONSOLE_PROCS();
+    CYGACC_COMM_IF_CH_DATA_SET(*comm, &channels[0]);
+    CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
+    CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
+    CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
+    CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
+    CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
+    CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
+#if 1
+    CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
+#endif
+
+    // Set channel 1
+    CYGACC_CALL_IF_SET_CONSOLE_COMM(1);
+    comm = CYGACC_CALL_IF_CONSOLE_PROCS();
+    CYGACC_COMM_IF_CH_DATA_SET(*comm, &channels[1]);
+    CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
+    CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
+    CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
+    CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
+    CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
+    CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
+#if 1
+    CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
+#endif
+
+    // Restore original console
+    CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
+}
+
+void
+cyg_hal_plf_comms_init(void)
+{
+    static int initialized = 0;
+
+    if (initialized)
+        return;
+
+    initialized = 1;
+
+    cyg_hal_plf_serial_init();
+}
+
+void
+cyg_hal_plf_serial_setbaud(void *__ch_data, cyg_uint32 baud_rate)
+{
+    cyg_uint8* port;
+
+    // Some of the diagnostic print code calls through here with no idea what the ch_data is.
+    // Go ahead and assume it is channels[0].
+    if (__ch_data == 0)
+      __ch_data = (void*)&channels[0];
+
+    port = ((channel_data_t*)__ch_data)->base;
+
+    cyg_hal_plf_serial_set_baud(port, baud_rate);
+}
+
+/*---------------------------------------------------------------------------*/
+/* End of ser_stb.c */
--- a/packages/hal/mn10300/stdeval1/current/ChangeLog
+++ b/packages/hal/mn10300/stdeval1/current/ChangeLog
@@ -1,3 +1,9 @@
+2001-08-02  Nick Garnett  <nickg@redhat.com>
+
+	* include/plf_io.h:
+	Added this file to match assumption now made in arch files that it
+	exists.	
+
 2001-01-26  Jesper Skov  <jskov@redhat.com>
 
 	* include/plf_stub.h: Reset macros moved
new file mode 100644
--- /dev/null
+++ b/packages/hal/mn10300/stdeval1/current/include/plf_io.h
@@ -0,0 +1,56 @@
+#ifndef CYGONCE_PLF_IO_H
+#define CYGONCE_PLF_IO_H
+
+//=============================================================================
+//
+//      plf_io.h
+//
+//      Platform specific IO support
+//
+//=============================================================================
+//####COPYRIGHTBEGIN####
+//
+// -------------------------------------------
+// The contents of this file are subject to the Red Hat eCos Public License
+// Version 1.1 (the "License"); you may not use this file except in
+// compliance with the License.  You may obtain a copy of the License at
+// http://www.redhat.com/
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the
+// License for the specific language governing rights and limitations under
+// the License.
+//
+// The Original Code is eCos - Embedded Configurable Operating System,
+// released September 30, 1998.
+//
+// The Initial Developer of the Original Code is Red Hat.
+// Portions created by Red Hat are
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.
+// All Rights Reserved.
+// -------------------------------------------
+//
+//####COPYRIGHTEND####
+//=============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    nickg
+// Contributors:
+// Date:         2001-08-02
+// Purpose:      Stdeval1 platform IO support
+// Description:
+// Usage:        #include <cyg/hal/plf_io.h>
+//
+//####DESCRIPTIONEND####
+//
+//=============================================================================
+
+#include <pkgconf/hal.h>
+
+//-----------------------------------------------------------------------------
+
+// Nothing here
+
+//-----------------------------------------------------------------------------
+// end of plf_io.h
+#endif // CYGONCE_PLF_IO_H
--- a/packages/hal/sh/cq7750/current/ChangeLog
+++ b/packages/hal/sh/cq7750/current/ChangeLog
@@ -1,3 +1,9 @@
+2001-08-08  Jesper Skov  <jskov@redhat.com>
+
+	* misc/redboot_ROM.ecm: Added.
+
+	* cdl/hal_sh_sh7750_cq7750.cdl: Added RedBoot build rule.
+
 2001-07-13  Jesper Skov  <jskov@redhat.com>
 
 	* include/platform.inc (BSC_settings_table): Replaced
--- a/packages/hal/sh/cq7750/current/cdl/hal_sh_sh7750_cq7750.cdl
+++ b/packages/hal/sh/cq7750/current/cdl/hal_sh_sh7750_cq7750.cdl
@@ -312,4 +312,31 @@ cdl_package CYGPKG_HAL_SH_SH7750_CQ7750 
             application. This enables features such as utilizing a separate
             interrupt stack when exceptions are generated."
     }
+
+    cdl_component CYGPKG_REDBOOT_HAL_OPTIONS {
+        display       "Redboot HAL options"
+        flavor        none
+        no_define
+        parent        CYGPKG_REDBOOT
+        active_if     CYGPKG_REDBOOT
+        description   "
+            This option lists the target's requirements for a valid Redboot
+            configuration."
+    
+        cdl_option CYGBLD_BUILD_REDBOOT_BIN {
+            display       "Build Redboot ROM binary image"
+            active_if     CYGBLD_BUILD_REDBOOT
+            default_value 1
+            no_define
+            description "This option enables the conversion of the Redboot ELF
+                         image to a binary image suitable for ROM programming."
+    
+            make -priority 325 {
+                <PREFIX>/bin/redboot.bin : <PREFIX>/bin/redboot.elf
+                $(OBJCOPY) --strip-debug $< $(@:.bin=.img) 
+                $(OBJCOPY) -O srec $< $(@:.bin=.srec)
+                $(OBJCOPY) -O binary $< $@
+            }
+        }
+    }
 }
new file mode 100644
--- /dev/null
+++ b/packages/hal/sh/cq7750/current/misc/redboot_ROM.ecm
@@ -0,0 +1,59 @@
+cdl_savefile_version 1;
+cdl_savefile_command cdl_savefile_version {};
+cdl_savefile_command cdl_savefile_command {};
+cdl_savefile_command cdl_configuration { description hardware template package };
+cdl_savefile_command cdl_package { value_source user_value wizard_value inferred_value };
+cdl_savefile_command cdl_component { value_source user_value wizard_value inferred_value };
+cdl_savefile_command cdl_option { value_source user_value wizard_value inferred_value };
+cdl_savefile_command cdl_interface { value_source user_value wizard_value inferred_value };
+
+cdl_configuration eCos {
+    description "" ;
+    hardware    cq7750 ;
+    template    redboot ;
+    package -hardware CYGPKG_HAL_SH current ;
+    package -hardware CYGPKG_HAL_SH_SH4 current ;
+    package -hardware CYGPKG_HAL_SH_SH7750_CQ7750 current ;
+    package -hardware CYGPKG_IO_SERIAL_SH_SCIF current ;
+    package -template CYGPKG_HAL current ;
+    package -template CYGPKG_INFRA current ;
+    package -template CYGPKG_REDBOOT current ;
+};
+
+cdl_option CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE {
+    user_value 6144
+};
+
+cdl_option CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT {
+    user_value 0
+};
+
+cdl_option CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM {
+    inferred_value 0
+};
+
+cdl_option CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS {
+    inferred_value 1
+};
+
+cdl_option CYGSEM_HAL_USE_ROM_MONITOR {
+    inferred_value 0 0
+};
+
+cdl_option CYGSEM_HAL_ROM_MONITOR {
+    inferred_value 1
+};
+
+cdl_component CYGPKG_HAL_SH_7750 {
+    inferred_value 1
+};
+
+cdl_component CYG_HAL_STARTUP {
+    user_value ROM
+};
+
+cdl_component CYGBLD_BUILD_REDBOOT {
+    user_value 1
+};
+
+
--- a/packages/hal/sh/dreamcast/current/ChangeLog
+++ b/packages/hal/sh/dreamcast/current/ChangeLog
@@ -1,3 +1,7 @@
+2001-08-06  Jesper Skov  <jskov@redhat.com>
+
+	* cdl/hal_sh_sh7750_dreamcast.cdl: Set linux boot parameters.
+
 2001-07-30  Jesper Skov  <jskov@redhat.com>
 
 	* New platform HAL, contributed by Takeshi Yaegashi (t@keshi.org)
--- a/packages/hal/sh/dreamcast/current/cdl/hal_sh_sh7750_dreamcast.cdl
+++ b/packages/hal/sh/dreamcast/current/cdl/hal_sh_sh7750_dreamcast.cdl
@@ -50,6 +50,10 @@ cdl_package CYGPKG_HAL_SH_SH7750_DREAMCA
         The HAL package provides the support needed to run
         eCos on SEGA Dreamcast."
 
+    requires      { CYGDAT_REDBOOT_SH_LINUX_BOOT_ENTRY == 0x8c210000 }
+    requires      { CYGDAT_REDBOOT_SH_LINUX_BOOT_BASE_ADDR == 0x8c001000 }
+    requires      { CYGDAT_REDBOOT_SH_LINUX_BOOT_COMMAND_LINE == "mem=16M" }
+
     compile       hal_diag.c plf_misc.c dreamcast_pci.c fb_support.c
 
     implements    CYGINT_HAL_DEBUG_GDB_STUBS
--- a/packages/hal/sh/sh4/current/ChangeLog
+++ b/packages/hal/sh/sh4/current/ChangeLog
@@ -1,3 +1,7 @@
+2001-08-08  Jesper Skov  <jskov@redhat.com>
+
+	* include/mod_7750.h: Don't use UBC as handling of it is broken.
+
 2001-07-26  Jesper Skov  <jskov@redhat.com>
 
 	* include/var_cache.h: Define flash cache macros that also disable
--- a/packages/hal/sh/sh4/current/include/mod_7750.h
+++ b/packages/hal/sh/sh4/current/include/mod_7750.h
@@ -50,7 +50,7 @@
 
 #define CYGARC_SH_MOD_CPG  1
 #define CYGARC_SH_MOD_SCIF 1
-#define CYGARC_SH_MOD_UBC  1
+//#define CYGARC_SH_MOD_UBC  1
 #define CYGARC_SH_MOD_INTC 1
 
 
--- a/packages/infra/current/ChangeLog
+++ b/packages/infra/current/ChangeLog
@@ -1,3 +1,25 @@
+2001-08-03  Nick Garnett  <nickg@cygnus.co.uk>
+
+	Imported from a development branch:
+	
+	2001-06-27  Nick Garnett  <nickg@cygnus.co.uk>
+
+		* src/diag.cxx: 
+		* src/tcdiag.cxx:
+		Added use of CYG_HAL_DIAG_LOCK() and CYG_HAL_DIAG_UNLOCK() to
+		diag_printf(), cyg_assert_msg() and cyg_test_output() to prevent
+		messages from different CPUs being mingled.
+
+	2001-05-22  Nick Garnett  <nickg@cygnus.co.uk>
+
+		* include/cyg_type.h (CYGBLD_ANNOTATE_VARIABLE_*):
+		Added better way of supplying default definitions for these.
+
+	2001-04-27  Nick Garnett  <nickg@cygnus.co.uk>
+
+		* include/cyg_type.h:
+		Added default variable annotation macros.
+
 2001-07-18  Jonathan Larmour  <jlarmour@redhat.com>
 
 	* include/cyg_type.h (CYG_INIT_MEMALLOC): Add.
--- a/packages/infra/current/include/cyg_type.h
+++ b/packages/infra/current/include/cyg_type.h
@@ -363,6 +363,26 @@ typedef cyg_haladdrword CYG_ADDRWORD;
         CYGBLD_ATTRIB_WEAK CYGBLD_ATTRIB_ALIAS(__symbol__)
 
 // -------------------------------------------------------------------------
+// Variable annotations
+// These annotations may be added to various static variables in the
+// HAL and kernel to indicate which component they belong to. These
+// are used by some targets to optimize memory placement of these
+// variables.
+
+#ifndef CYGBLD_ANNOTATE_VARIABLE_HAL
+#define CYGBLD_ANNOTATE_VARIABLE_HAL
+#endif
+#ifndef CYGBLD_ANNOTATE_VARIABLE_SCHED
+#define CYGBLD_ANNOTATE_VARIABLE_SCHED
+#endif
+#ifndef CYGBLD_ANNOTATE_VARIABLE_CLOCK
+#define CYGBLD_ANNOTATE_VARIABLE_CLOCK
+#endif
+#ifndef CYGBLD_ANNOTATE_VARIABLE_INTR
+#define CYGBLD_ANNOTATE_VARIABLE_INTR
+#endif
+
+// -------------------------------------------------------------------------
 // Various "flavours" of memory regions that can be described by the 
 // Memory Layout Tool (MLT).
 
--- a/packages/infra/current/src/diag.cxx
+++ b/packages/infra/current/src/diag.cxx
@@ -62,6 +62,10 @@
 #include <cyg/io/io_diag.h>
 #endif
 
+#ifdef CYG_HAL_DIAG_LOCK_DATA_DEFN
+CYG_HAL_DIAG_LOCK_DATA_DEFN;
+#endif
+
 /*----------------------------------------------------------------------*/
 
 externC void diag_write_num(
@@ -454,8 +458,17 @@ externC void diag_printf(const char *fmt
     args[7] = va_arg(a,CYG_ADDRWORD);
 
     va_end(a);
+
+#ifdef CYG_HAL_DIAG_LOCK
+    CYG_HAL_DIAG_LOCK();
+#endif    
     
     diag_vprintf( fmt, args);
+
+#ifdef CYG_HAL_DIAG_UNLOCK
+    CYG_HAL_DIAG_UNLOCK();
+#endif    
+    
 }
 
 #else
@@ -484,8 +497,18 @@ externC void diag_printf(const char *fmt
     args[5] = a6;
     args[6] = a7;
     args[7] = a8;
+
+
+#ifdef CYG_HAL_DIAG_LOCK
+    CYG_HAL_DIAG_LOCK();
+#endif    
     
     diag_vprintf( fmt, args);
+
+#ifdef CYG_HAL_DIAG_UNLOCK
+    CYG_HAL_DIAG_UNLOCK();
+#endif    
+
 }
 
 #endif
--- a/packages/infra/current/src/tcdiag.cxx
+++ b/packages/infra/current/src/tcdiag.cxx
@@ -94,6 +94,10 @@ cyg_test_output(Cyg_test_code status, co
         break;
     }
 
+#ifdef CYG_HAL_DIAG_LOCK
+    CYG_HAL_DIAG_LOCK();
+#endif    
+    
     diag_write_string(st);
     diag_write_char('<');
     diag_write_string(msg);
@@ -105,6 +109,12 @@ cyg_test_output(Cyg_test_code status, co
         diag_write_string(file);
     }
     diag_write_char('\n');
+
+#ifdef CYG_HAL_DIAG_UNLOCK
+    CYG_HAL_DIAG_UNLOCK();
+#endif    
+    
+    
 }
 
 // This is an appropriate function to set a breakpoint on
--- a/packages/io/eth/current/ChangeLog
+++ b/packages/io/eth/current/ChangeLog
@@ -1,3 +1,19 @@
+2001-08-09  Hugo Tyson  <hmt@redhat.com>
+
+	* src/net/eth_drv.c (eth_drv_recv): Add a pair of
+	CYGARC_HAL_SAVE_GP()/CYGARC_HAL_RESTORE_GP() on entry and exit;
+	this function is intercalled between RedBoot and the application.
+	A minor re-org at the ending to accommodate these macros' nesting.
+	(eth_drv_tx_done): CYGARC_HAL_SAVE_GP()/CYGARC_HAL_RESTORE_GP().
+
+	* src/stand_alone/eth_drv.c (eth_drv_tx_done): Add a pair of
+	CYGARC_HAL_SAVE_GP()/CYGARC_HAL_RESTORE_GP() on entry and exit;
+	this function is intercalled between RedBoot and the application.
+	Also make printing message about "tx_done for other key" also
+	conditional on net_debug variable - it's commonplace.
+	(eth_drv_recv): CYGARC_HAL_SAVE_GP()/CYGARC_HAL_RESTORE_GP().
+	(eth_drv_copy_recv): CYGARC_HAL_SAVE_GP()/CYGARC_HAL_RESTORE_GP().
+
 2001-07-03  Gary Thomas  <gthomas@redhat.com>
 
 	* src/net/eth_drv.c (eth_drv_recv): Better cleanup when running
--- a/packages/io/eth/current/src/net/eth_drv.c
+++ b/packages/io/eth/current/src/net/eth_drv.c
@@ -557,6 +557,7 @@ eth_drv_tx_done(struct eth_drv_sc *sc, C
 {
     struct ifnet *ifp = &sc->sc_arpcom.ac_if;
     struct mbuf *m0 = (struct mbuf *)key;
+    CYGARC_HAL_SAVE_GP();
 
     // Check for errors here (via 'status')
     ifp->if_opackets++;
@@ -565,6 +566,7 @@ eth_drv_tx_done(struct eth_drv_sc *sc, C
     m_freem(m0);
     // Start another if possible
     eth_drv_send(ifp);
+    CYGARC_HAL_RESTORE_GP();
 }
 
 //
@@ -605,6 +607,8 @@ eth_drv_recv(struct eth_drv_sc *sc, int 
     }
 #endif
 
+    CYGARC_HAL_SAVE_GP();  // This is down here to make matching restore neat
+
     /* Pull packet off interface. */
     MGETHDR(m, M_DONTWAIT, MT_DATA);
     if (m == 0) {
@@ -701,24 +705,24 @@ eth_drv_recv(struct eth_drv_sc *sc, int 
     m = top;
     if (m == 0) {
         ifp->if_ierrors++;
-        return;
     }
-
-    ifp->if_ipackets++;
-
+    else {
+        ifp->if_ipackets++;
 
 #if NBPFILTER > 0
 #error FIXME - Need mbuf with ethernet header attached
-    /*
-     * Check if there's a BPF listener on this interface.
-     * If so, hand off the raw packet to bpf.
-     */
-    if (ifp->if_bpf)
-        bpf_mtap(ifp->if_bpf, m);
+        /*
+         * Check if there's a BPF listener on this interface.
+         * If so, hand off the raw packet to bpf.
+         */
+        if (ifp->if_bpf)
+            bpf_mtap(ifp->if_bpf, m);
 #endif
 
-    // Push data into protocol stacks
-    ether_input(ifp, eh, m);
+        // Push data into protocol stacks
+        ether_input(ifp, eh, m);
+    }
+    CYGARC_HAL_RESTORE_GP();
 }
 
 
--- a/packages/io/eth/current/src/stand_alone/eth_drv.c
+++ b/packages/io/eth/current/src/stand_alone/eth_drv.c
@@ -279,19 +279,23 @@ eth_drv_write(char *eth_hdr, char *buf, 
 static void
 eth_drv_tx_done(struct eth_drv_sc *sc, CYG_ADDRWORD key, int status)
 {
+    CYGARC_HAL_SAVE_GP();
     if ((int *)key == &packet_sent) {
         *(int *)key = 1;
     } else {
         // It's possible that this acknowledgement is for a different
         // [logical] driver.  Try and pass it on.
 #ifdef CYGSEM_IO_ETH_DRIVERS_DEBUG
-        int old_console;
-        old_console = start_console();
-        printf("tx_done for other key: %x\n", key);
-        end_console(old_console);
+        if (net_debug) {
+            int old_console;
+            old_console = start_console();
+            printf("tx_done for other key: %x\n", key);
+            end_console(old_console);
+        }
 #endif
         (sc->funs->eth_drv_old->tx_done)(sc, key, status);
     }
+    CYGARC_HAL_RESTORE_GP();
 }
 
 //
@@ -352,12 +356,13 @@ eth_drv_copy_recv(struct eth_drv_sc *sc,
                   int sg_len)
 {
     int i;   
-
+    CYGARC_HAL_SAVE_GP();
     for (i = 0;  i < sg_len;  i++) {
         memcpy((unsigned char *)sg_list[i].buf, 
                eth_drv_copy_recv_buf, sg_list[i].len);
         eth_drv_copy_recv_buf += sg_list[i].len;
     }
+    CYGARC_HAL_RESTORE_GP();
 }
 #endif
 
@@ -373,6 +378,7 @@ eth_drv_recv(struct eth_drv_sc *sc, int 
     int               sg_len = 0;
     struct eth_msg *msg;
     unsigned char *buf;
+    CYGARC_HAL_SAVE_GP();
 
     msg = eth_drv_msg_get(&eth_msg_free);
     if (msg) {
@@ -427,6 +433,7 @@ eth_drv_recv(struct eth_drv_sc *sc, int 
         dump_buf(sg_list[0].buf, sg_list[0].len);
 #endif
     }
+    CYGARC_HAL_RESTORE_GP();
 }
 
 //
--- a/packages/io/flash/current/ChangeLog
+++ b/packages/io/flash/current/ChangeLog
@@ -1,3 +1,10 @@
+2001-08-10  Jesper Skov  <jskov@redhat.com>
+
+	* cdl/io_flash.cdl: Changed flavor of
+	CYGHWR_IO_FLASH_BLOCK_LOCKING to booldata.
+	* include/flash.h: Matching changes.
+	* src/flash.c: Matching changes.
+
 2001-07-23  David Howells  <dhowells@redhat.com>
 
 	* cdl/io_flash.cdl: Added software write protect option.
--- a/packages/io/flash/current/cdl/io_flash.cdl
+++ b/packages/io/flash/current/cdl/io_flash.cdl
@@ -89,6 +89,7 @@ cdl_package CYGPKG_IO_FLASH {
 
     cdl_interface CYGHWR_IO_FLASH_BLOCK_LOCKING {
         display       "Hardware can support block locking"
+        flavor        booldata
         description   "
             This option will be enabled by devices which can support
             locking (write-protection) of individual blocks."
--- a/packages/io/flash/current/include/flash.h
+++ b/packages/io/flash/current/include/flash.h
@@ -55,7 +55,7 @@ externC int flash_init(void *work_space,
 externC int flash_erase(void *base, int len, void **err_address);
 externC int flash_program(void *flash_base, void *ram_base, int len, void **err_address);
 externC void flash_dev_query(void *data);
-#if 0 < CYGHWR_IO_FLASH_BLOCK_LOCKING // This is an *interface*
+#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
 externC int flash_lock(void *base, int len, void **err_address);
 externC int flash_unlock(void *base, int len, void **err_address);
 #endif
--- a/packages/io/flash/current/src/flash.c
+++ b/packages/io/flash/current/src/flash.c
@@ -294,7 +294,7 @@ flash_program(void *_addr, void *_data, 
     return (stat);
 }
 
-#if 0 < CYGHWR_IO_FLASH_BLOCK_LOCKING // This is an *interface*
+#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
 
 int
 flash_lock(void *addr, int len, void **err_addr)
--- a/packages/io/usb/slave/current/ChangeLog
+++ b/packages/io/usb/slave/current/ChangeLog
@@ -1,3 +1,8 @@
+2001-08-06  Bart Veer  <bartv@redhat.com>
+
+	* include/usbs.h:
+	Define additional data structures required for USB testing.
+
 2001-06-19  Bart Veer  <bartv@redhat.com>
 
 	* src/usbs.c, include/usbs.h (usbs_devtab_cread):
--- a/packages/io/usb/slave/current/include/usbs.h
+++ b/packages/io/usb/slave/current/include/usbs.h
@@ -345,6 +345,68 @@ extern Cyg_ErrNo usbs_devtab_get_config(
 extern Cyg_ErrNo usbs_devtab_set_config(cyg_io_handle_t, cyg_uint32, const void*, cyg_uint32*);
 #endif
 
+// Additional support for testing.
+// Test cases need to have some way of finding out about what support is
+// actually provided by the USB device driver, for example what endpoints
+// are available. There is no perfect way of achieving this. One approach
+// would be to scan through the devtab table looking for devices of the
+// form /dev/usbs1r. That is not reliable: the devtab entries may have been
+// configured out if higher-level code uses the usb-specific API; or the
+// devtab entries may have been renamed. Also having a devtab entry does not
+// really give the kind of information a general-purpose testcase needs,
+// for example upper bounds on transfer size.    
+// 
+// An alternative approach is to have a data structure that somehow
+// defines the USB hardware, and the USB device driver then creates an
+// instance of this. This is the approach actually taken. The problem
+// now is how the test code can access this instance. Accessing by
+// unique name is simple, as long as there is only one USB device in
+// the system (which of course will usually be the case on the USB
+// slave side). Alternative approaches such as creating a table at
+// link time or a list during static construction time are vulnerable
+// either to selective linking or to having these structures present
+// in applications other than the test cases. In future it might be
+// possible to address the latter issue by extending the build system
+// support, e.g. a new library libtesting.a and a new object file
+// testing.o.
+//
+// Note that a given endpoint could be used for bulk transfers some
+// of the time, then for isochronous transfers, etc. It is the
+// responsibility of the host to only perform one type of IN operation
+// for a given endpoint number, and ditto for OUT.    
+
+typedef struct usbs_testing_endpoint {
+    int         endpoint_type;          // One of ATTR_CONTROL, ATTR_BULK, ...
+    int         endpoint_number;        // Between 0 and 15
+    cyg_bool    in_endpoint;            // host->slave?
+    void*       endpoint;               // pointer to the usbs_control_endpoint, usbs_rx_endpoint, ...
+    const char* devtab_entry;           // e.g. "/dev/usbs1r", or 0 if inaccessible via devtab
+    int         min_size;               // Minimum transfer size
+    int         max_size;               // -1 indicates no specific upper bound
+    int         max_in_padding;         // extra bytes that the target may send, usually 0.
+                                        // Primarily for SA11x0 hardware. It is assumed
+                                        // for now that no other hardware will exhibit
+                                        // comparable problems.
+} usbs_testing_endpoint;
+
+// A specific instance provided by the device driver. The end of
+// the table is indicated by a NULL endpoint field.    
+extern usbs_testing_endpoint usbs_testing_endpoints[];    
+
+#define USBS_TESTING_ENDPOINTS_TERMINATOR                       \
+    {                                                           \
+        endpoint_type   : USB_ENDPOINT_DESCRIPTOR_ATTR_CONTROL, \
+        endpoint_number : 0,                                    \
+        in_endpoint     : false,                                \
+        endpoint        : (void*) 0,                            \
+        devtab_entry    : (const char*) 0,                      \
+        min_size        : 0,                                    \
+        max_size        : 0,                                    \
+        max_in_padding  : 0                                     \
+    }
+
+#define USBS_TESTING_ENDPOINTS_IS_TERMINATOR(_endpoint_) ((void*)0 == (_endpoint_).endpoint)
+    
 #ifdef __cplusplus
 } // extern "C" {
 #endif
--- a/packages/isoinfra/current/ChangeLog
+++ b/packages/isoinfra/current/ChangeLog
@@ -1,3 +1,10 @@
+2001-08-06  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* cdl/isoinfra.cdl: Add a separate POSIX mutex types header option.
+	* include/sys/types.h: Include it.
+	* include/time.h: Provide a default struct timespec even if the
+	implementation doesn't provide something better.
+
 2001-07-26  Jonathan Larmour  <jlarmour@redhat.com>
 
 	* include/sys/types.h: Move select() related stuff into separate
--- a/packages/isoinfra/current/cdl/isoinfra.cdl
+++ b/packages/isoinfra/current/cdl/isoinfra.cdl
@@ -794,6 +794,17 @@ cdl_package CYGPKG_ISOINFRA {
             default_value 0
         }
 
+        cdl_interface CYGINT_ISO_PMUTEXTYPES {
+            display       "POSIX mutex types implementations"
+            requires      { 1 >= CYGINT_ISO_PTHREADTYPES }
+        }
+    
+        cdl_option CYGBLD_ISO_PMUTEXTYPES_HEADER {
+            display       "POSIX mutex types implementation header"
+            flavor        booldata
+            default_value 0
+        }
+
         cdl_option CYGBLD_ISO_SSIZE_T_HEADER {
             display       "ssize_t implementation header"
             flavor        booldata
--- a/packages/isoinfra/current/include/sys/types.h
+++ b/packages/isoinfra/current/include/sys/types.h
@@ -83,6 +83,10 @@ typedef unsigned short uid_t;
 typedef int pid_t;
 #endif
 
+#if CYGINT_ISO_PMUTEXTYPES
+# include CYGBLD_ISO_PMUTEXTYPES_HEADER
+#endif
+
 #if CYGINT_ISO_PTHREADTYPES
 # include CYGBLD_ISO_PTHREADTYPES_HEADER
 #endif
--- a/packages/isoinfra/current/include/time.h
+++ b/packages/isoinfra/current/include/time.h
@@ -110,6 +110,15 @@ struct timeval {
 
 #if CYGINT_ISO_POSIX_TIMER_TYPES
 # include CYGBLD_ISO_POSIX_TIMER_TYPES_HEADER
+#else
+
+/* Provide a default struct timespec. */
+
+struct timespec
+{
+    time_t      tv_sec;
+    long        tv_nsec;
+};
 #endif
 
 #if CYGINT_ISO_C_TIME_TYPES
--- a/packages/kernel/current/ChangeLog
+++ b/packages/kernel/current/ChangeLog
@@ -1,3 +1,303 @@
+2001-08-06  Hugo Tyson  <hmt@redhat.com>
+
+	* src/sched/sched.cxx (unlock_inner): Fix assignment to current,
+	wouldn't build if stack checking after merger from SMP branch.
+
+2001-08-06  Andrew Lunn   <andrew.lunn@ascom.ch>
+2001-08-06  Hugo Tyson  <hmt@redhat.com>
+
+	* src/sync/mutex.cxx: (set_protocol) Added a function to set the
+	priority inversion protocol for a mutex.
+
+	* src/common/kapi.cxx: Export the new function above and
+	set_ceiling into the C API.
+	
+	* include/mutex.hxx (class Cyg_Mutex): New member function
+	set_protocol().
+
+	* include/kapi.h (cyg_protcol): Define new emumeration for mutex
+	priority protocol setting, and headers for the new function to set
+	it.
+
+2001-08-03  Nick Garnett  <nickg@redhat.com>
+
+	Imported from a development branch:
+	
+	2001-07-11  Nick Garnett  <nickg@redhat.com>
+
+		* src/sched/mlqueue.cxx: Changed behaviour of
+		set_need_reschedule() to a better implementation of the intended
+		algorithm.
+
+		* include/kapi.h: 
+		* src/common/kapi.cxx:
+		Added API for controlling routing of interrupts to CPUs in SMP
+		configurations.
+
+	2001-07-03  Nick Garnett  <nickg@cygnus.co.uk>
+
+		* cdl/scheduler.cdl:
+		* include/bitmap.hxx:
+		* src/sched/bitmap.cxx:
+		Fixed up bitmap scheduler so it still works within the
+		SMP-modified scheduling infrastructure. The bitmap scheduler
+		is not currently SMP-enabled, only single CPU configurations are
+		supported - hence the CDL change to require this.
+
+	2001-06-29  Nick Garnett  <nickg@cygnus.co.uk>
+
+		* src/sched/sched.cxx:
+		Removed the call to Cyg_Interrupt::enable_interrupts() in
+		Cyg_Scheduler::start_cpu(). This was a relic from the days when
+		the interrupt enable state was not part of the thread state. Now
+		it is, and loading the first thread will cause interrupts to be
+		enabled.
+
+		* src/intr/intr.cxx:
+		Changed initial values of Cyg_Interrupt::disable_counter[]s to
+		zero as a result of the change in Cyg_Scheduler::start_cpu().
+
+		* include/kapi.h:
+		* include/kapidata.h:
+		* src/common/kapi.cxx: 
+		Added API for using spinlocks. Largely so that it may be extended
+		to the driver API.
+
+		* include/mlqueue.hxx:
+		* include/intr.hxx:
+		* include/sched.hxx:
+		Added annotations to various static variables.
+
+	2001-06-28  Nick Garnett  <nickg@cygnus.co.uk>
+
+		* include/intr.hxx:
+		* src/intr/intr.cxx:
+		Changed behaviour of Cyg_Interrupt::disable_interrupts() and
+		Cyg_Interrupt::enable_interrupts(). These now claim and release a
+		spinlock in addition to disabling and enabling interrupts. The
+		original interrupt state is also preserved and restored. This is
+		necessary in SMP systems to allow drivers etc. to correctly
+		synchronize with threads and DSRs that may be running on different
+		CPUs. In the single CPU case this mechanism reduces to the
+		original simple interrupt disable code.
+		[Later change] Backed off addition of volatile modifier to
+		interrupt_disable_state.
+
+		* include/smp.hxx: Some minor tidies.
+
+	2001-06-27  Nick Garnett  <nickg@cygnus.co.uk>
+
+		* tests/release.cxx: Added spin loop in thread1 to allow thread0
+		to execute its wait. This is necessary in SMP systems where the
+		threads will execute in parallel, but is also benign in single CPU
+		systems.
+
+		* tests/mutex2.cxx:
+		* tests/mutex3.cxx:
+		* tests/sync3.cxx: 
+		* tests/thread2.cxx: 
+		These tests depend on predicting the behaviour of threads at
+		different priorities to pass. In an SMP system, several threads
+		will run in parallel, and the execution order will not be as
+		expected. These tests are therefore disabled in SMP
+		configurations.
+
+		* src/sched/mlqueue.cxx (add_thread): Moved call to
+		set_need_reschedule() out of test for empty queue. In SMP systems,
+		any addition to a queue may require a reschedule on another CPU.
+
+	2001-06-22  Nick Garnett  <nickg@cygnus.co.uk>
+
+		* include/mlqueue.hxx:
+		* src/sched/mlqueue.cxx:
+		A major change to the way in which this scheduler works in SMP
+		systems. The previous version removed all runnable threads from
+		the run queues when they were executing. This resulted in serious
+		complications and messy code, particularly when dealing with
+		priority changes and timeslicing. The new version keeps running
+		threads in the run queues, just like the single-CPU version. The
+		main disadvantage of this is that we may have to search past
+		threads running on other CPUs before we find one available to run
+		on this CPU. However, the pending count array and map mean that we
+		only need search one run queue, and in any case the search remains
+		bounded by the number of CPUs available.
+		Another change is in the way that timeslicing is handled. Now, the
+		CPU that takes the clock interrupt decrements the timeslice counts
+		for all CPUs and if any go zero, sends a TIMESLICE message to
+		that CPU.
+
+		* src/sched/sched.cxx (unlock_inner):
+		Removed call to requeue(), no longer needed as a result of
+		scheduler reorganization.
+
+		* src/common/thread.cxx:
+		Added test in Cyg_Thread::exit() to check that the thread has not
+		already been killed. This is only an issue if the thread is
+		calling exit() when it is kill()ed from another CPU. The test is
+		redundant in single-CPU systems, but it does no harm having it.
+		Added code to Cyg_Thread::set_priority() to check for reschedule
+		when another thread is being changed in priority.
+		Added call in idle thread constructor to scheduler to install the
+		idle thread as the default current thread for a CPU.
+
+		* include/smp.hxx:
+		Added CYG_KERNEL_CPU_TIMESLICE_INTERRUPT(), did some miscellaneous
+		tidying.
+
+		* include/instrmnt.h: Added SMP_RESCHED_SEND and SMP_RESCHED_RECV
+		events.
+
+		* cdl/kernel.cdl: Added smp test program.
+
+		* tests/smp.cxx: Added this program to test SMP functionality.
+
+	2001-06-13  Nick Garnett  <nickg@cygnus.co.uk>
+
+		* src/sched/sched.cxx:
+		Removed code to set up initial current thread, this is now done
+		in the idle thread constructor.
+		Added code here to set up interrupts for SMP inter-processor
+		interrupts. This is not very tidy and may need to be
+		changed in the future.
+
+		* src/sched/mlqueue.cxx:
+		Added local set_need_reschedule() function to set the
+		need_reschedule flag on a suitable CPU.
+		Many more changes to cope with SMP systems.
+		NOTE: This code has all become somthing of a mess, it need to be
+		tidied up and the SMP-specific changes integrated better into the
+		code. Also, timesliceing currently only works on the CPU that
+		takes clock interrupts - this needs fixing.
+
+		* src/common/thread.cxx:
+		Moved assignment of initial current thread to here from sched.cxx.
+
+		* include/smp.hxx:
+		Changed CYG_KERNEL_CPU_INTERRUPT()
+		CYG_KERNEL_CPU_RESCHEDULE_INTERRUPT() since there may be other
+		interrupt types to worry about.
+		Added annotations to scheduler data items.
+
+		* include/sched.hxx:
+		Split set_current_thread() into two functions, the original works
+		only on the current CPU, the new one sets another CPU's current
+		thread. This latter function is only used to prime the current
+		threads during initialization.
+		Added second need_reschedule() function that takes a thread
+		argument. This is intended to be overridden by a scheduler
+		specific function that sets the need_reschedule flag if the
+		supplied thread is more deserving of CPU time that any current
+		thread.
+
+		* include/mlqueue.hxx:
+		Made cyg_scheduler_set_need_reschedule() a friend of
+		Cyg_Scheduler_Implementation class.
+		Added override set_need_reschedule() functions.
+
+		* include/kapidata.h: Added cpu field to cyg_thread structure when
+		in SMP systems.
+
+		* include/intr.hxx:
+		* src/intr/intr.cxx:
+		Added Cyg_Interrupt::set_cpu() and Cyg_Interrupt::get_cpu() for
+		SMP systems.
+
+		* include/instrmnt.h: Added events for INTR_GET_CPU and
+		INTR_SET_CPU.
+
+	2001-05-29  Nick Garnett  <nickg@cygnus.co.uk>
+
+		The following changes were all imported from the SMP branch:
+
+		* tests/tm_basic.cxx:
+		Modified to work in SMP configuration - mostly at present by
+		ifdeffing out code I didn't want to fix.
+
+		* include/sched.hxx:
+		Moved scheduler lock operation into Cyg_Scheduler_SchedLock class.
+		Converted current_thread, need_reschedule, and thread_switches
+		into CPU indexed arrays. Added member functions to get and set
+		these indirectly.
+		Added start_cpu() to do per-CPU scheduler startup.
+
+		* include/sched.inl:
+		Converted scheduler lock/unlock functions to use new schedlock
+		class.
+
+		* src/sched/sched.cxx:
+		Changed in line with sched.hxx.
+		Added call to requeue() in unlock_inner() to restore current
+		thread to run queue if necessary.	
+		Moved most of scheduler startup to Cyg_Scheduler::start_cpu().
+		Cyg_Scheduler::start() now also starts secondary CPUs in SMP
+		systems.
+		Added cyg_kernel_smp_startup() as entry point from HAL into kernel
+		for secondary CPUs.
+
+		* include/mlqueue.hxx:
+		Added Cyg_RunQueue type and removed
+		Cyg_SchedulerThreadQueue_Implementation type.
+		Converted timeslice_count to CPU indexed array.
+		Added requeue() member function to scheduler class.
+		Added cpu member to thread implementation class, to record
+		thread's current CPU.
+
+		* src/sched/mlqueue.cxx:
+		Changed behaviour when in SMP system to remove scheduled thread
+		from run queue and replace it when preempted.
+		Added some extra asserts, and removed some that are no longer true
+		in an SMP system.
+
+		* src/instrmnt/meminst.cxx: In SMP systems: added spinlock to
+		protect instrument buffer, added CPU Id in top 4 bits of thread Id
+		field.
+
+		* src/common/thread.cxx:
+		Converted to use accessor functions for need_reschedule and
+		current_thread.
+		Rearranged idle thread creation to create one for each CPU.
+
+		* include/test/stackmon.h: Extended to handle stack usage for
+		multiple idle threads.
+
+		* include/thread.inl:
+		Added some extra instrumentation.
+
+		* include/smp.hxx:
+		Added this file to contain all kernel SMP support. The main
+		definitions exported by this file are spin lock and scheduler lock
+		implementation classes, for both SMP and uniprocessor
+		configurations.
+
+		* src/intr/intr.cxx: 
+		* include/intr.hxx:
+		Converted interrupt disable counter to CPU indexed array. In
+		intr.cxx: added lock of scheduler lock in interrupt_end() rather
+		than in default interrupt VSR.
+
+		* cdl/kernel.cdl: Added option to enable SMP support.
+
+		* include/instrmnt.h: 
+		* cdl/instrument.cdl: Added SMP instrumentation.
+
+	2001-05-25  Nick Garnett  <nickg@cygnus.co.uk>
+
+		* include/intr.hxx:
+		* src/intr/intr.cxx: 
+		Added default definition of CYGNUM_HAL_ISR_TABLE_SIZE. This is now
+		used to declare the chain table so that architectures which have
+		different sizes for the interrupt table and vector count will work
+		correctly.
+
+	2001-05-22  Nick Garnett  <nickg@cygnus.co.uk>
+
+		* include/sched.hxx (class Cyg_Scheduler_Base):
+		Added annotation to sched_lock.
+
+		* cdl/instrument.cdl:
+		Rename CYGNUM_KERNEL_INSTRUMENT_BUFFER_WRAP to
+		CYGDBG_KERNEL_INSTRUMENT_BUFFER_WRAP as it appears in the code.
+
 2001-07-27  Jesper Skov  <jskov@redhat.com>
 
 	* src/intr/intr.cxx (chain_isr): Return isr_ret so caller (which
--- a/packages/kernel/current/cdl/instrument.cdl
+++ b/packages/kernel/current/cdl/instrument.cdl
@@ -68,7 +68,7 @@ cdl_option CYGNUM_KERNEL_INSTRUMENT_BUFF
         of memory."
 }
 
-cdl_option CYGNUM_KERNEL_INSTRUMENT_BUFFER_WRAP {
+cdl_option CYGDBG_KERNEL_INSTRUMENT_BUFFER_WRAP {
     display       "Wrap instrument buffer"
     default_value 1
     description   "
@@ -224,6 +224,19 @@ cdl_option CYGDBG_KERNEL_INSTRUMENT_ALAR
         the code related to alarm operations."
 }
 
+cdl_option CYGDBG_KERNEL_INSTRUMENT_SMP {
+    display       "Instrument SMP-related operations"
+    default_value 1
+    active_if     CYGVAR_KERNEL_COUNTERS_CLOCK
+    description   "
+        It is possible to perform selective instrumentation at
+        run-time. It is also possible to disable instrumentation
+        in various kernel components at compile-time, thus
+        reducing the code size overheads. This option controls
+        whether or not instrumentation support is compiled into
+        the code related to SMP operations."
+}
+
 cdl_option CYGDBG_KERNEL_INSTRUMENT_USER {
     display       "Support application-level instrumentation"
     default_value 1
--- a/packages/kernel/current/cdl/kernel.cdl
+++ b/packages/kernel/current/cdl/kernel.cdl
@@ -143,6 +143,16 @@ cdl_package CYGPKG_KERNEL {
     }
 
     # ---------------------------------------------------------------------
+    # SMP support
+    
+    cdl_component CYGPKG_KERNEL_SMP_SUPPORT {
+	display       "SMP support"
+	flavor        bool
+	requires      CYGPKG_HAL_SMP_SUPPORT
+	default_value 0
+    }
+    
+    # ---------------------------------------------------------------------
     cdl_component CYGPKG_KERNEL_COUNTERS {
         display       "Counters and clocks"
         flavor        none
@@ -315,7 +325,7 @@ cdl_package CYGPKG_KERNEL {
                 CYGPKG_HAL_ARM_CMA230 ? "tests/bin_sem0 tests/bin_sem1 tests/bin_sem2 tests/clock0 tests/clock1 tests/clockcnv tests/cnt_sem0 tests/cnt_sem1 tests/flag0 tests/flag1 tests/intr0 tests/kclock0 tests/kclock1 tests/kintr0 tests/kmbox1 tests/kmutex0 tests/kmutex1 tests/ksched1 tests/ksem0 tests/ksem1 tests/kflag0 tests/kflag1 tests/klock tests/kthread0 tests/kthread1 tests/mbox1 tests/mqueue1 tests/mutex0 tests/mutex1 tests/mutex2 tests/mutex3 tests/sched1 tests/sync2 tests/sync3 tests/thread0 tests/thread1 tests/thread2 tests/release tests/kill tests/thread_gdb tests/tm_basic tests/dhrystone" : \
                 CYGPKG_HAL_ARM_E7T ? "tests/bin_sem0 tests/bin_sem1 tests/bin_sem2 tests/clock0 tests/clock1 tests/clockcnv tests/cnt_sem0 tests/cnt_sem1 tests/except1 tests/flag0 tests/flag1 tests/intr0 tests/kclock0 tests/kclock1 tests/kexcept1 tests/kintr0 tests/kmbox1 tests/kmutex0 tests/kmutex1 tests/ksched1 tests/ksem0 tests/ksem1 tests/kflag0 tests/kflag1 tests/klock tests/kthread0 tests/kthread1 tests/mbox1 tests/mqueue1 tests/mutex0 tests/mutex1 tests/mutex2 tests/mutex3 tests/sched1 tests/sync2 tests/sync3 tests/thread0 tests/thread1 tests/thread2 tests/release tests/kill tests/thread_gdb tests/tm_basic tests/dhrystone tests/stress_threads tests/kcache1 tests/kcache2" : \
                 CYGPKG_HAL_ARM ? "tests/bin_sem0 tests/bin_sem1 tests/bin_sem2 tests/clock0 tests/clock1 tests/clockcnv tests/clocktruth tests/cnt_sem0 tests/cnt_sem1 tests/except1 tests/flag0 tests/flag1 tests/intr0 tests/kclock0 tests/kclock1 tests/kexcept1 tests/kintr0 tests/kmbox1 tests/kmutex0 tests/kmutex1 tests/ksched1 tests/ksem0 tests/ksem1 tests/kflag0 tests/kflag1 tests/klock tests/kthread0 tests/kthread1 tests/mbox1 tests/mqueue1 tests/mutex0 tests/mutex1 tests/mutex2 tests/mutex3 tests/sched1 tests/sync2 tests/sync3 tests/thread0 tests/thread1 tests/thread2 tests/release tests/kill tests/thread_gdb tests/tm_basic tests/dhrystone" : \
-                "tests/bin_sem0 tests/bin_sem1 tests/bin_sem2 tests/clock0 tests/clock1 tests/clockcnv tests/clocktruth tests/cnt_sem0 tests/cnt_sem1 tests/except1 tests/flag0 tests/flag1 tests/intr0 tests/kclock0 tests/kclock1 tests/kexcept1 tests/kintr0 tests/kmbox1 tests/kmutex0 tests/kmutex1 tests/ksched1 tests/ksem0 tests/ksem1 tests/kflag0 tests/kflag1 tests/klock tests/kthread0 tests/kthread1 tests/mbox1 tests/mqueue1 tests/mutex0 tests/mutex1 tests/mutex2 tests/mutex3 tests/sched1 tests/sync2 tests/sync3 tests/thread0 tests/thread1 tests/thread2 tests/release tests/kill tests/thread_gdb tests/tm_basic tests/dhrystone tests/stress_threads tests/kcache1 tests/kcache2" 
+                "tests/bin_sem0 tests/bin_sem1 tests/bin_sem2 tests/clock0 tests/clock1 tests/clockcnv tests/clocktruth tests/cnt_sem0 tests/cnt_sem1 tests/except1 tests/flag0 tests/flag1 tests/intr0 tests/kclock0 tests/kclock1 tests/kexcept1 tests/kintr0 tests/kmbox1 tests/kmutex0 tests/kmutex1 tests/ksched1 tests/ksem0 tests/ksem1 tests/kflag0 tests/kflag1 tests/klock tests/kthread0 tests/kthread1 tests/mbox1 tests/mqueue1 tests/mutex0 tests/mutex1 tests/mutex2 tests/mutex3 tests/sched1 tests/sync2 tests/sync3 tests/thread0 tests/thread1 tests/thread2 tests/release tests/kill tests/thread_gdb tests/tm_basic tests/dhrystone tests/stress_threads tests/kcache1 tests/kcache2 tests/smp" 
             }
             description   "
                 This option specifies the set of tests for the eCos kernel."
--- a/packages/kernel/current/cdl/scheduler.cdl
+++ b/packages/kernel/current/cdl/scheduler.cdl
@@ -72,6 +72,7 @@ cdl_option CYGSEM_KERNEL_SCHED_BITMAP {
     default_value 0
     implements    CYGINT_KERNEL_SCHEDULER
     implements    CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES
+    requires      !CYGPKG_KERNEL_SMP_SUPPORT
     description   "
         The bitmap scheduler supports multiple priority levels but
         only one thread can exist at each priority level. This means
--- a/packages/kernel/current/include/bitmap.hxx
+++ b/packages/kernel/current/include/bitmap.hxx
@@ -120,6 +120,9 @@ protected:
     
     // Test the given priority for uniqueness
     cyg_bool    unique( cyg_priority priority);
+
+public:
+    void set_idle_thread( Cyg_Thread *thread, HAL_SMP_CPU_TYPE cpu );
     
 };
 
--- a/packages/kernel/current/include/instrmnt.h
+++ b/packages/kernel/current/include/instrmnt.h
@@ -104,6 +104,8 @@ externC void cyg_instrument_disable( cyg
 #define CYG_INSTRUMENT_CLASS_CLOCK              0x0800
 #define CYG_INSTRUMENT_CLASS_ALARM              0x0900
 #define CYG_INSTRUMENT_CLASS_MBOXT              0x0a00
+#define CYG_INSTRUMENT_CLASS_SMP                0x0b00
+#define CYG_INSTRUMENT_CLASS_MLQ                0x0c00
 
 #define CYG_INSTRUMENT_CLASS_USER               0x0f00
 
@@ -125,6 +127,9 @@ externC void cyg_instrument_disable( cyg
 #define CYG_INSTRUMENT_EVENT_THREAD_DELAY       7
 #define CYG_INSTRUMENT_EVENT_THREAD_ALARM       8
 #define CYG_INSTRUMENT_EVENT_THREAD_ENTER       9
+#define CYG_INSTRUMENT_EVENT_THREAD_CHECK_STACK 10
+#define CYG_INSTRUMENT_EVENT_THREAD_ATTACH_STACK 11
+#define CYG_INSTRUMENT_EVENT_THREAD_CREATE      12
 
 // Interrupt events
 #define CYG_INSTRUMENT_EVENT_INTR_RAISE         1
@@ -142,6 +147,8 @@ externC void cyg_instrument_disable( cyg
 #define CYG_INSTRUMENT_EVENT_INTR_CONFIGURE     13
 #define CYG_INSTRUMENT_EVENT_INTR_ACK           14
 #define CYG_INSTRUMENT_EVENT_INTR_CHAIN_ISR     15
+#define CYG_INSTRUMENT_EVENT_INTR_SET_CPU       16
+#define CYG_INSTRUMENT_EVENT_INTR_GET_CPU       17
 
 // Mutex events
 #define CYG_INSTRUMENT_EVENT_MUTEX_LOCK         1
@@ -200,6 +207,27 @@ externC void cyg_instrument_disable( cyg
 #define CYG_INSTRUMENT_EVENT_MBOXT_TRY          6
 #define CYG_INSTRUMENT_EVENT_MBOXT_PUT          7
 
+// SMP events
+#define CYG_INSTRUMENT_EVENT_SMP_LOCK_INC       1
+#define CYG_INSTRUMENT_EVENT_SMP_LOCK_ZERO      2
+#define CYG_INSTRUMENT_EVENT_SMP_LOCK_SET       3
+#define CYG_INSTRUMENT_EVENT_SMP_CPU_START      4
+#define CYG_INSTRUMENT_EVENT_SMP_LOCK_WAIT      5
+#define CYG_INSTRUMENT_EVENT_SMP_LOCK_GOT       6
+#define CYG_INSTRUMENT_EVENT_SMP_RESCHED_SEND   8
+#define CYG_INSTRUMENT_EVENT_SMP_RESCHED_RECV   9
+
+// MLQ scheduler events
+
+#define CYG_INSTRUMENT_EVENT_MLQ_SCHEDULE       1
+#define CYG_INSTRUMENT_EVENT_MLQ_RESCHEDULE     2
+#define CYG_INSTRUMENT_EVENT_MLQ_ADD            3
+#define CYG_INSTRUMENT_EVENT_MLQ_REM            4
+#define CYG_INSTRUMENT_EVENT_MLQ_TIMESLICE      5
+#define CYG_INSTRUMENT_EVENT_MLQ_YIELD          6
+#define CYG_INSTRUMENT_EVENT_MLQ_ENQUEUE        7
+#define CYG_INSTRUMENT_EVENT_MLQ_DEQUEUE        8
+#define CYG_INSTRUMENT_EVENT_MLQ_REMOVE         9
 
 
 // User events
@@ -373,12 +401,41 @@ externC void cyg_instrument_disable( cyg
 #endif
 
 // -------------------------------------------------------------------------
+// SMP instrumentation
+
+#ifdef CYGDBG_KERNEL_INSTRUMENT_SMP
+            
+#define CYG_INSTRUMENT_SMP(_event_,_arg1_,_arg2_) \
+    CYG_INSTRUMENT(CYGINST_EVENT(SMP,_event_),_arg1_,_arg2_)
+
+#else
+
+#define CYG_INSTRUMENT_SMP(_event_,_arg1_,_arg2_)
+
+#endif
+
+
+// -------------------------------------------------------------------------
+// MLQ instrumentation
+
+#if 1 //def CYGDBG_KERNEL_INSTRUMENT_MLQ
+            
+#define CYG_INSTRUMENT_MLQ(_event_,_arg1_,_arg2_) \
+    CYG_INSTRUMENT(CYGINST_EVENT(MLQ,_event_),_arg1_,_arg2_)
+
+#else
+
+#define CYG_INSTRUMENT_MLQ(_event_,_arg1_,_arg2_)
+
+#endif
+
+// -------------------------------------------------------------------------
 // User instrumentation
 
 #ifdef CYGDBG_KERNEL_INSTRUMENT_USER
             
 #define CYG_INSTRUMENT_USER(_event_,_arg1_,_arg2_) \
-    CYG_INSTRUMENT(CYGINST_EVENT(USER,_event_),_arg1_,_arg2_)
+    CYG_INSTRUMENT((CYG_INSTRUMENT_CLASS_USER|(_event_)),_arg1_,_arg2_)
 
 #else
 
--- a/packages/kernel/current/include/intr.hxx
+++ b/packages/kernel/current/include/intr.hxx
@@ -49,6 +49,19 @@
 
 #include <cyg/kernel/ktypes.h>
 
+#include <cyg/kernel/smp.hxx>
+
+// -------------------------------------------------------------------------
+// Default definitions
+
+// Some HALs define the ISR table to be a different size to the number
+// of ISR vectors. These HALs will define CYGNUM_HAL_ISR_TABLE_SIZE. All
+// other HALs will have the table size equal to the number of vectors.
+
+#ifndef CYGNUM_HAL_ISR_TABLE_SIZE
+# define CYGNUM_HAL_ISR_TABLE_SIZE      CYGNUM_HAL_ISR_COUNT
+#endif
+
 // -------------------------------------------------------------------------
 // Function prototype typedefs
 
@@ -154,20 +167,24 @@ class Cyg_Interrupt
 
 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
     
-    static Cyg_Interrupt *dsr_table[CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE];
+    static Cyg_Interrupt *dsr_table[CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE]
+                                    CYGBLD_ANNOTATE_VARIABLE_INTR;
 
-    static cyg_ucount32 dsr_table_head;
+    static cyg_ucount32 dsr_table_head CYGBLD_ANNOTATE_VARIABLE_INTR;
 
-    static volatile cyg_ucount32 dsr_table_tail;
+    static volatile cyg_ucount32 dsr_table_tail CYGBLD_ANNOTATE_VARIABLE_INTR;
 
 #endif
 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
 
-    volatile cyg_ucount32 dsr_count;	      // Number of DSR posts made
+    // Number of DSR posts made
+    volatile cyg_ucount32 dsr_count CYGBLD_ANNOTATE_VARIABLE_INTR; 
 
-    Cyg_Interrupt* volatile next_dsr; // next DSR in list
-    
-    static Cyg_Interrupt* volatile dsr_list; // static list of pending DSRs
+    // next DSR in list
+    Cyg_Interrupt* volatile next_dsr CYGBLD_ANNOTATE_VARIABLE_INTR; 
+
+    // static list of pending DSRs
+    static Cyg_Interrupt* volatile dsr_list CYGBLD_ANNOTATE_VARIABLE_INTR;
     
 #endif
 
@@ -184,11 +201,45 @@ class Cyg_Interrupt
     static cyg_uint32 chain_isr(cyg_vector vector, CYG_ADDRWORD data);    
 
     // Table of interrupt chains
-    static Cyg_Interrupt *chain_list[CYGNUM_HAL_ISR_COUNT];
+    static Cyg_Interrupt *chain_list[CYGNUM_HAL_ISR_TABLE_SIZE];
     
 #endif
 
-    static cyg_int32 disable_counter;   // Disable level counter
+    // Interrupt disable data. Interrupt disable can be nested. On
+    // each CPU this is controlled by disable_counter[cpu]. When the
+    // counter is first incremented from zero to one, the
+    // interrupt_disable_spinlock is claimed using spin_intsave(), the
+    // original interrupt enable state being saved in
+    // interrupt_disable_state[cpu].  When the counter is decremented
+    // back to zero the spinlock is cleared using clear_intsave().
+
+    // The spinlock is necessary in SMP systems since a thread
+    // accessing data shared with an ISR may be scheduled on a
+    // different CPU to the one that handles the interrupt. So, merely
+    // blocking local interrupts would be ineffective. SMP aware
+    // device drivers should either use their own spinlocks to protect
+    // data, or use the API supported by this class, via
+    // cyg_drv_isr_lock()/_unlock(). Note that it now becomes
+    // essential that ISRs do this if they are to be SMP-compatible.
+
+    // In a single CPU system, this mechanism reduces to just
+    // disabling/enabling interrupts.
+
+    // Disable level counter. This counts the number of times
+    // interrupts have been disabled.
+    static volatile cyg_int32 disable_counter[CYGNUM_KERNEL_CPU_MAX]
+                                              CYGBLD_ANNOTATE_VARIABLE_INTR;
+
+    // Interrupt disable spinlock. This is claimed by any CPU that has
+    // disabled interrupts via the Cyg_Interrupt API.
+    static Cyg_SpinLock interrupt_disable_spinlock CYGBLD_ANNOTATE_VARIABLE_INTR;
+
+    // Saved interrupt state. When each CPU first disables interrupts
+    // the original state of the interrupts are saved here to be
+    // restored later.
+    static CYG_INTERRUPT_STATE interrupt_disable_state[CYGNUM_KERNEL_CPU_MAX]
+                                                       CYGBLD_ANNOTATE_VARIABLE_INTR;
+
     
 public:
 
@@ -241,7 +292,7 @@ public:
     // Are interrupts enabled at the CPU?
     static inline cyg_bool interrupts_enabled()
     {
-        return (0 == disable_counter);
+        return (0 == disable_counter[CYG_KERNEL_CPU_THIS()]);
     }
     
     // Get the vector for the following calls
@@ -267,7 +318,15 @@ public:
         cyg_bool level,                 // level or edge triggered
         cyg_bool up                     // hi/lo level, rising/falling edge
         );
+
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
+
+    // SMP support for associating an interrupt with a specific CPU.
     
+    static void set_cpu( cyg_vector, HAL_SMP_CPU_TYPE cpu );
+    static HAL_SMP_CPU_TYPE get_cpu( cyg_vector );
+    
+#endif    
 };
 
 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS
--- a/packages/kernel/current/include/kapi.h
+++ b/packages/kernel/current/include/kapi.h
@@ -67,6 +67,7 @@ typedef cyg_addrword_t cyg_handle_t;    
 typedef cyg_uint32     cyg_priority_t;      /* type for priorities           */
 typedef cyg_int32      cyg_code_t;          /* type for various codes        */
 typedef cyg_uint32     cyg_vector_t;        /* Interrupt vector id           */
+typedef cyg_uint32     cyg_cpu_t;           /* CPU id type                   */
 
 typedef cyg_uint64 cyg_tick_count_t;
 
@@ -110,6 +111,9 @@ typedef struct cyg_mutex_t cyg_mutex_t;
 struct cyg_cond_t;
 typedef struct cyg_cond_t cyg_cond_t;
 
+struct cyg_spinlock_t;
+typedef struct cyg_spinlock_t cyg_spinlock_t;
+
 /*---------------------------------------------------------------------------*/
 /* Scheduler operations */
 
@@ -239,8 +243,9 @@ void cyg_exception_call_handler(
 /* Interrupt handling                                                        */
 typedef void            cyg_VSR_t(void);
 typedef cyg_uint32      cyg_ISR_t(cyg_vector_t vector, cyg_addrword_t data);
-typedef void            cyg_DSR_t(
-    cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
+typedef void            cyg_DSR_t( cyg_vector_t vector,
+                                   cyg_ucount32 count,
+                                   cyg_addrword_t data);
 
 
 enum cyg_ISR_results
@@ -295,6 +300,15 @@ void cyg_interrupt_configure(
     cyg_bool_t          up              /* rising/faling edge, high/low level*/
 );
 
+void cyg_interrupt_set_cpu(
+    cyg_vector_t        vector,         /* vector to control                 */
+    cyg_cpu_t           cpu             /* CPU to set                        */
+);
+
+cyg_cpu_t cyg_interrupt_get_cpu(
+    cyg_vector_t        vector          /* vector to control                 */
+);
+    
 /*---------------------------------------------------------------------------*/
 /* Counters, Clocks and Alarms                                               */
 
@@ -506,6 +520,15 @@ cyg_bool_t cyg_flag_waiting( cyg_flag_t 
 /*---------------------------------------------------------------------------*/
 /* Mutex                                                                     */
 
+#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
+enum cyg_protcol
+{
+  NONE = 0,                       // no inversion protocol
+  INHERIT,                        // priority inheritance protocol
+  CEILING                         // priority ceiling protocol
+};
+#endif
+
 void cyg_mutex_init(
     cyg_mutex_t        *mutex          /* Mutex to init                      */
 );
@@ -520,6 +543,14 @@ void cyg_mutex_unlock( cyg_mutex_t *mute
 
 void cyg_mutex_release( cyg_mutex_t *mutex );
 
+#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
+void cyg_mutex_set_ceiling( cyg_mutex_t *mutex, cyg_priority_t priority );
+#endif
+
+#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
+void cyg_mutex_set_protocol ( cyg_mutex_t *mutex, enum cyg_protcol protocol );
+#endif
+
 /*---------------------------------------------------------------------------*/
 /* Condition Variables                                                       */
 
@@ -543,11 +574,37 @@ cyg_bool_t cyg_cond_timed_wait(
     );
 #endif
 
+/*---------------------------------------------------------------------------*/
+/* Spinlocks                                                                 */
 
+void cyg_spinlock_init(
+    cyg_spinlock_t      *lock,          /* spinlock to initialize            */
+    cyg_bool_t          locked          /* init locked or unlocked           */
+);
+
+void cyg_spinlock_destroy( cyg_spinlock_t *lock );
+
+void cyg_spinlock_spin( cyg_spinlock_t *lock );
+
+void cyg_spinlock_clear( cyg_spinlock_t *lock );
+
+cyg_bool_t cyg_spinlock_try( cyg_spinlock_t *lock );
+
+cyg_bool_t cyg_spinlock_test( cyg_spinlock_t *lock );
+
+void cyg_spinlock_spin_intsave( cyg_spinlock_t *lock,
+                                cyg_addrword_t *istate );
+
+void cyg_spinlock_clear_intsave( cyg_spinlock_t *lock,
+                                 cyg_addrword_t istate );
+
+/*---------------------------------------------------------------------------*/
 #ifdef __cplusplus
 }
 #endif
 
+/*---------------------------------------------------------------------------*/
+
 #include <cyg/kernel/kapidata.h>
 
 /*---------------------------------------------------------------------------*/
--- a/packages/kernel/current/include/kapidata.h
+++ b/packages/kernel/current/include/kapidata.h
@@ -215,6 +215,10 @@ typedef struct
 
     cyg_priority_t      priority;       /* current thread priority */
 
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
+    cyg_uint32          cpu;            // CPU id of cpu currently running
+#endif
+    
 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE_ENABLE
     cyg_bool            timeslice_enabled; /* per-thread timeslice enable */
 #endif    
@@ -365,6 +369,13 @@ struct cyg_cond_t
 
 /*------------------------------------------------------------------------*/
 
+struct cyg_spinlock_t
+{
+    cyg_atomic          lock;           /* lock word                     */
+};
+
+/*------------------------------------------------------------------------*/
+
 /* Memory allocator types now come from the "memalloc" package which is   */
 /* where the implementation lives.                                        */
 
--- a/packages/kernel/current/include/mlqueue.hxx
+++ b/packages/kernel/current/include/mlqueue.hxx
@@ -92,6 +92,11 @@ typedef cyg_ucount32 cyg_sched_bitmap;
 #define CYG_SCHED_DEFAULT_INFO  CYG_THREAD_MAX_PRIORITY
 
 // -------------------------------------------------------------------------
+// scheduler Run queue object
+
+typedef Cyg_CList_T<Cyg_Thread> Cyg_RunQueue;
+
+// -------------------------------------------------------------------------
 // Thread queue implementation.
 // This class provides the (scheduler specific) implementation of the
 // thread queue class.
@@ -101,7 +106,6 @@ class Cyg_ThreadQueue_Implementation
 {
     friend class Cyg_Scheduler_Implementation;
     friend class Cyg_SchedThread_Implementation;
-    friend class Cyg_SchedulerThreadQueue_Implementation;
 
     void                set_thread_queue(Cyg_Thread *thread,
                                          Cyg_ThreadQueue *tq );
@@ -126,15 +130,6 @@ protected:
 
 };
 
-// thread queue used exclusively by the scheduler, with simpler enqueueing
-
-class Cyg_SchedulerThreadQueue_Implementation
-    : public Cyg_ThreadQueue_Implementation
-{
-public:    
-    void                enqueue(Cyg_Thread *thread);  // Add thread to queue
-};
-
 // -------------------------------------------------------------------------
 // This class contains the implementation details of the scheduler, and
 // provides a standard API for accessing it.
@@ -145,13 +140,25 @@ class Cyg_Scheduler_Implementation
     friend class Cyg_ThreadQueue_Implementation;
     friend class Cyg_SchedThread_Implementation;
     friend class Cyg_HardwareThread;
+    friend void cyg_scheduler_set_need_reschedule();
     
     // Mask of which run queues have ready threads
     cyg_sched_bitmap    queue_map;
 
     // Each run queue is a double linked circular list of threads.
     // These pointers point to the head element of each list.
-    Cyg_SchedulerThreadQueue_Implementation run_queue[CYGNUM_KERNEL_SCHED_PRIORITIES];
+    Cyg_RunQueue run_queue[CYGNUM_KERNEL_SCHED_PRIORITIES];
+
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
+
+    // In SMP systems we additionally keep a counter for each priority
+    // of the number of pending but not running threads in each queue.
+    
+    cyg_uint32 pending[CYGNUM_KERNEL_SCHED_PRIORITIES];
+
+    cyg_sched_bitmap pending_map;
+
+#endif    
 
 protected:
     
@@ -161,7 +168,8 @@ protected:
     // clock tick, and a timeslice is performed each
     // time it zeroes.
     
-    static cyg_ucount32                 timeslice_count;
+    static cyg_ucount32 timeslice_count[CYGNUM_KERNEL_CPU_MAX]
+                                        CYGBLD_ANNOTATE_VARIABLE_SCHED;
 
     static void reset_timeslice_count();
 
@@ -191,13 +199,22 @@ protected:
     // Test the given priority for uniqueness
     cyg_bool    unique( cyg_priority priority);
 
+    // Set need_reschedule if the supplied thread is of lower
+    // priority than any that are currently running.
+    static void set_need_reschedule( Cyg_Thread *thread );
+    static void set_need_reschedule();
+
+public:
+    void set_idle_thread( Cyg_Thread *thread, HAL_SMP_CPU_TYPE cpu );
+    
 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
 
     // If timeslicing is enbled, define a scheduler
-    // entry point to do timeslicing. This will be
+    // entry points to do timeslicing. This will be
     // called from the RTC DSR.
 public:    
     void timeslice();
+    void timeslice_cpu();
 
 #endif
 
@@ -206,11 +223,16 @@ public:
 // -------------------------------------------------------------------------
 // Cyg_Scheduler_Implementation inlines
 
+inline void Cyg_Scheduler_Implementation::set_need_reschedule()
+{
+    need_reschedule[CYG_KERNEL_CPU_THIS()] = true;
+}
+
 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
 
 inline void Cyg_Scheduler_Implementation::reset_timeslice_count()
 {
-    timeslice_count = CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS;
+    timeslice_count[CYG_KERNEL_CPU_THIS()] = CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS;
 }
 
 #endif
@@ -225,12 +247,17 @@ class Cyg_SchedThread_Implementation
 {
     friend class Cyg_Scheduler_Implementation;
     friend class Cyg_ThreadQueue_Implementation;
-    friend class Cyg_SchedulerThreadQueue_Implementation;
 
 protected:
 
     cyg_priority        priority;       // current thread priority
 
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
+    HAL_SMP_CPU_TYPE    cpu;            // CPU id of cpu currently running
+                                        // this thread, or CYG_KERNEL_CPU_NONE
+                                        // if not running.
+#endif
+    
     Cyg_SchedThread_Implementation(CYG_ADDRWORD sched_info);
 
     void yield();                       // Yield CPU to next thread
--- a/packages/kernel/current/include/mutex.hxx
+++ b/packages/kernel/current/include/mutex.hxx
@@ -123,6 +123,12 @@ public:
     cyg_priority get_ceiling(void) { return ceiling; };
     
 #endif
+
+#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
+
+    // set inversion protocol
+    void        set_protocol( cyg_protcol new_protocol );
+#endif
     
 };
 
--- a/packages/kernel/current/include/sched.hxx
+++ b/packages/kernel/current/include/sched.hxx
@@ -49,6 +49,7 @@
 #include <cyg/kernel/ktypes.h>
 #include <cyg/infra/cyg_ass.h>         // assertion macros
 
+#include <cyg/kernel/smp.hxx>          // SMP support
 
 // -------------------------------------------------------------------------
 // Miscellaneous types
@@ -59,6 +60,8 @@ typedef void Cyg_ASR( CYG_ADDRWORD data 
 
 #endif
 
+__externC void cyg_scheduler_set_need_reschedule();
+
 // -------------------------------------------------------------------------
 // Scheduler base class. This defines stuff that is needed by the
 // specific scheduler implementation. Each scheduler comprises three
@@ -66,6 +69,7 @@ typedef void Cyg_ASR( CYG_ADDRWORD data 
 // inherits from it and Cyg_Scheduler which inherits from _it_ in turn.
 
 class Cyg_Scheduler_Base
+     : public Cyg_Scheduler_SchedLock
 {
     friend class Cyg_HardwareThread;
     friend class Cyg_SchedThread;
@@ -74,14 +78,43 @@ protected:
     // The following variables are implicit in the API, but are
     // not publically visible.
 
-    static volatile cyg_ucount32 sched_lock         // lock counter
-                    CYGBLD_ATTRIB_ASM_ALIAS( cyg_scheduler_sched_lock );
+    // Current running thread    
+    static Cyg_Thread * volatile current_thread[CYGNUM_KERNEL_CPU_MAX]
+                                                CYGBLD_ANNOTATE_VARIABLE_SCHED; 
+
+    // Set when reschedule needed
+    static volatile cyg_bool     need_reschedule[CYGNUM_KERNEL_CPU_MAX]
+                                                 CYGBLD_ANNOTATE_VARIABLE_SCHED; 
+
+    // Count of number of thread switches
+    static volatile cyg_ucount32 thread_switches[CYGNUM_KERNEL_CPU_MAX]
+                                                 CYGBLD_ANNOTATE_VARIABLE_SCHED; 
+
+public:
+
+    // return a pointer to the current thread
+    static Cyg_Thread *get_current_thread();
+
+    // Set current thread pointer
+    static void set_current_thread(Cyg_Thread *thread);
+    static void set_current_thread(Cyg_Thread *thread, HAL_SMP_CPU_TYPE cpu);
     
-    static Cyg_Thread   *current_thread;        // current running thread
+    // Set need_reschedule flag
+    static void set_need_reschedule();
+    static void set_need_reschedule(Cyg_Thread *thread);
+
+    // Get need_reschedule flag
+    static cyg_bool get_need_reschedule();
 
-    static cyg_bool     need_reschedule;        // set when schedule needed
+    // Return current value of lock
+    static cyg_ucount32 get_sched_lock();
 
-    static cyg_ucount32 thread_switches;        // count of number of thread switches
+    // Clear need_reschedule flag
+    static void clear_need_reschedule();
+    
+    // Return current number of thread switches
+    static cyg_ucount32 get_thread_switches();
+    
 };
 
 // -------------------------------------------------------------------------
@@ -135,20 +168,14 @@ public:
     // release the preemption lock without rescheduling
     static void             unlock_simple();
     
-    // return a pointer to the current thread
-    static Cyg_Thread       *get_current_thread();
-
-    // Return current value of lock
-    static cyg_ucount32 get_sched_lock();
-
-    // Return current number of thread switches
-    static cyg_ucount32 get_thread_switches();
-    
     // Start execution of the scheduler
     static void start() __attribute__ ((noreturn));
+
+    // Start execution of the scheduler on the current CPU
+    static void start_cpu() __attribute__ ((noreturn));    
     
     // The only  scheduler instance should be this one...
-    static Cyg_Scheduler scheduler;
+    static Cyg_Scheduler scheduler CYGBLD_ANNOTATE_VARIABLE_SCHED;
 
 };
 
@@ -318,21 +345,51 @@ public:
 // -------------------------------------------------------------------------
 // Simple inline accessor functions
 
-inline Cyg_Thread *Cyg_Scheduler::get_current_thread()
+inline Cyg_Thread *Cyg_Scheduler_Base::get_current_thread()
+{
+    return current_thread[CYG_KERNEL_CPU_THIS()];
+}
+
+inline void Cyg_Scheduler_Base::set_current_thread(Cyg_Thread *thread )
 {
-    return current_thread;
+    current_thread[CYG_KERNEL_CPU_THIS()] = thread;
+}
+
+inline void Cyg_Scheduler_Base::set_current_thread(Cyg_Thread *thread,
+                                                   HAL_SMP_CPU_TYPE cpu)
+{
+    current_thread[cpu] = thread;
 }
 
-// Return current value of lock
-inline cyg_ucount32 Cyg_Scheduler::get_sched_lock()
+inline cyg_bool Cyg_Scheduler_Base::get_need_reschedule()
+{
+    return need_reschedule[CYG_KERNEL_CPU_THIS()];
+}
+
+inline void Cyg_Scheduler_Base::set_need_reschedule()
+{
+    need_reschedule[CYG_KERNEL_CPU_THIS()] = true;
+}
+
+inline void Cyg_Scheduler_Base::set_need_reschedule(Cyg_Thread *thread)
 {
-    return sched_lock;
+    need_reschedule[CYG_KERNEL_CPU_THIS()] = true;
+}
+
+inline void Cyg_Scheduler_Base::clear_need_reschedule()
+{
+    need_reschedule[CYG_KERNEL_CPU_THIS()] = false;
+}
+
+inline cyg_ucount32 Cyg_Scheduler_Base::get_sched_lock()
+{
+    return Cyg_Scheduler_SchedLock::get_sched_lock();
 }
 
 // Return current number of thread switches
-inline cyg_ucount32 Cyg_Scheduler::get_thread_switches()
+inline cyg_ucount32 Cyg_Scheduler_Base::get_thread_switches()
 {
-    return thread_switches;
+    return thread_switches[CYG_KERNEL_CPU_THIS()];
 }
 
 // Return current queue pointer
--- a/packages/kernel/current/include/sched.inl
+++ b/packages/kernel/current/include/sched.inl
@@ -67,11 +67,11 @@ inline void Cyg_Scheduler::lock()
 
     HAL_REORDER_BARRIER();
 
-    sched_lock++;
+    inc_sched_lock();
 
     HAL_REORDER_BARRIER();
 
-    CYG_INSTRUMENT_SCHED(LOCK,sched_lock,0);
+    CYG_INSTRUMENT_SCHED(LOCK,get_sched_lock(),0);
 };
 
 inline void Cyg_Scheduler::unlock()
@@ -83,14 +83,14 @@ inline void Cyg_Scheduler::unlock()
     // decrement and return. As with lock() we do not need any special code
     // to decrement the lock counter.
 
-    CYG_INSTRUMENT_SCHED(UNLOCK,sched_lock,0);
-
+    CYG_INSTRUMENT_SCHED(UNLOCK,get_sched_lock(),0);
+    
     HAL_REORDER_BARRIER();
     
-    cyg_ucount32 __lock = sched_lock - 1;
+    cyg_ucount32 __lock = get_sched_lock() - 1;
     
     if( __lock == 0 ) unlock_inner(0);
-    else sched_lock = __lock;
+    else set_sched_lock(__lock);
 
     HAL_REORDER_BARRIER();
 }
@@ -102,9 +102,9 @@ inline void Cyg_Scheduler::reschedule()
     // leave a brief window between the calls when the lock is unclaimed
     // by the current thread.
     
-    CYG_INSTRUMENT_SCHED(RESCHEDULE,sched_lock,0);
+    CYG_INSTRUMENT_SCHED(RESCHEDULE,get_sched_lock(),0);
     
-    unlock_inner( sched_lock );
+    unlock_inner( get_sched_lock() );
 }
 
 inline void Cyg_Scheduler:: unlock_reschedule()
@@ -115,9 +115,9 @@ inline void Cyg_Scheduler:: unlock_resch
     // lock is being decremented to a non-zero value, it is more or less
     // equivalent to reschedule() followed by unlock().
     
-    CYG_INSTRUMENT_SCHED(UNLOCK,sched_lock,0);
+    CYG_INSTRUMENT_SCHED(UNLOCK,get_sched_lock(),0);
     
-    unlock_inner( sched_lock - 1 );
+    unlock_inner( get_sched_lock() - 1 );
 }
 
 inline void Cyg_Scheduler::unlock_simple()
@@ -128,12 +128,13 @@ inline void Cyg_Scheduler::unlock_simple
     // indeterminate future time.  This is mainly for use by
     // debuggers, it should not normally be used anywhere else.
 
-    CYG_INSTRUMENT_SCHED(UNLOCK,sched_lock,0);
+    CYG_INSTRUMENT_SCHED(UNLOCK,get_sched_lock(),0);
 
     HAL_REORDER_BARRIER();
         
-    if (sched_lock > 0)
-        sched_lock = sched_lock - 1;
+    if (get_sched_lock() > 1)
+        set_sched_lock(get_sched_lock() - 1);
+    else zero_sched_lock();
 
     HAL_REORDER_BARRIER();
 }
new file mode 100644
--- /dev/null
+++ b/packages/kernel/current/include/smp.hxx
@@ -0,0 +1,453 @@
+#ifndef CYGONCE_KERNEL_SMP_HXX
+#define CYGONCE_KERNEL_SMP_HXX
+
+//==========================================================================
+//
+//      smp.hxx
+//
+//      SMP kernel support
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):   nickg
+// Contributors:nickg
+// Date:        2001-02-10
+// Purpose:     Kernel SMP support
+// Description: If SMP support is configured into the kernel, then this file
+//              translates HAL defined macros into C and C++ classes and methods
+//              that can be called from the rest of the kernel. If SMP is not
+//              configured in, then the same classes and methods are defined here
+//              to operate correctly in a single CPU configuration.
+//              
+// Usage:       #include <cyg/kernel/smp.hxx>
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <cyg/kernel/ktypes.h>
+#include <cyg/infra/cyg_ass.h>          // assertion macros
+
+#include <cyg/hal/hal_intr.h>           // HAL_DISABLE_INTERRUPTS() etc.
+
+#include <cyg/kernel/instrmnt.h>
+
+//==========================================================================
+
+#if defined(CYGPKG_KERNEL_SMP_SUPPORT) && (CYGPKG_HAL_SMP_SUPPORT)
+
+//==========================================================================
+// SMP support is included
+
+#define CYG_KERNEL_SMP_ENABLED
+
+// -------------------------------------------------------------------------
+// Get HAL support
+
+#include <cyg/hal/hal_smp.h>
+
+// -------------------------------------------------------------------------
+// Defined values
+// These all just map straight through to the HAL.
+
+#define CYGNUM_KERNEL_CPU_MAX           HAL_SMP_CPU_MAX
+
+#define CYG_KERNEL_CPU_COUNT()          HAL_SMP_CPU_COUNT()
+
+#define CYG_KERNEL_CPU_THIS()           HAL_SMP_CPU_THIS()
+
+#define CYG_KERNEL_CPU_NONE             HAL_SMP_CPU_NONE
+
+// -------------------------------------------------------------------------
+// CPU control
+
+#define CYG_KERNEL_CPU_START( __cpu ) HAL_SMP_CPU_START( __cpu )
+
+#define CYG_KERNEL_CPU_RESCHEDULE_INTERRUPT( __cpu, __wait ) \
+        HAL_SMP_CPU_RESCHEDULE_INTERRUPT( __cpu, __wait )
+
+#define CYG_KERNEL_CPU_TIMESLICE_INTERRUPT( __cpu, __wait ) \
+        HAL_SMP_CPU_TIMESLICE_INTERRUPT( __cpu, __wait )
+
+// -------------------------------------------------------------------------
+// Scheduler lock default implementation.
+
+// This implementation should serve for most targets. However, some
+// targets may have hardware or other features that make simple
+// spinlocks impossible, or allow us to implement the scheduler lock
+// in a more efficient manner. If that is the case then the HAL will
+// implement these macros itself.
+
+#ifndef HAL_SMP_SCHEDLOCK_DATA_TYPE
+
+#define HAL_SMP_SCHEDLOCK_DATA_TYPE struct hal_smp_schedlock_data_type
+
+struct hal_smp_schedlock_data_type {
+    HAL_SPINLOCK_TYPE           spinlock;
+    volatile HAL_SMP_CPU_TYPE   holder;
+};
+
+#define HAL_SMP_SCHEDLOCK_INIT( __lock, __data )        \
+CYG_MACRO_START                                         \
+{                                                       \
+    __lock = 1;                                         \
+    HAL_SPINLOCK_CLEAR(__data.spinlock);                \
+    HAL_SPINLOCK_SPIN(__data.spinlock);                 \
+    __data.holder = HAL_SMP_CPU_THIS();                 \
+}                                                       \
+CYG_MACRO_END
+
+
+#define HAL_SMP_SCHEDLOCK_INC( __lock, __data )                 \
+CYG_MACRO_START                                                 \
+{                                                               \
+    CYG_INTERRUPT_STATE __state;                                \
+    HAL_DISABLE_INTERRUPTS(__state);                            \
+    if( __data.holder == HAL_SMP_CPU_THIS() )                   \
+        __lock++;                                               \
+    else                                                        \
+    {                                                           \
+        CYG_INSTRUMENT_SMP(LOCK_WAIT,CYG_KERNEL_CPU_THIS(),0);  \
+        HAL_SPINLOCK_SPIN(__data.spinlock);                     \
+        __data.holder = HAL_SMP_CPU_THIS();                     \
+        __lock++;                                               \
+        CYG_INSTRUMENT_SMP(LOCK_GOT,CYG_KERNEL_CPU_THIS(),0);   \
+    }                                                           \
+    HAL_RESTORE_INTERRUPTS(__state);                            \
+}                                                               \
+CYG_MACRO_END
+
+#define HAL_SMP_SCHEDLOCK_ZERO( __lock, __data )                                                 \
+CYG_MACRO_START                                                                                  \
+{                                                                                                \
+    CYG_INTERRUPT_STATE __state;                                                                 \
+    HAL_DISABLE_INTERRUPTS(__state);                                                             \
+    CYG_ASSERT( __data.holder == HAL_SMP_CPU_THIS(), "Zeroing schedlock not owned by me!");      \
+    __lock = 0;                                                                                  \
+    __data.holder = HAL_SMP_CPU_NONE;                                                            \
+    HAL_SPINLOCK_CLEAR(__data.spinlock);                                                         \
+    HAL_RESTORE_INTERRUPTS(__state);                                                             \
+}                                                                                                \
+CYG_MACRO_END
+
+#define HAL_SMP_SCHEDLOCK_SET( __lock, __data, __new )                                          \
+CYG_MACRO_START                                                                                 \
+{                                                                                               \
+    CYG_ASSERT( __data.holder == HAL_SMP_CPU_THIS(), "Setting schedlock not owned by me!");     \
+    __lock = __new;                                                                             \
+}                                                                                               \
+CYG_MACRO_END
+
+#endif
+
+// -------------------------------------------------------------------------
+// SpinLock class
+// This class supplies a C++ wrapper for the HAL spinlock API.
+
+#ifdef __cplusplus
+
+#ifdef HAL_SPINLOCK_SPIN
+
+class Cyg_SpinLock
+{
+    HAL_SPINLOCK_TYPE   lock;
+
+public:
+
+    // Constructor, initialize the lock to clear
+    Cyg_SpinLock() { lock = HAL_SPINLOCK_INIT_CLEAR; };
+
+    ~Cyg_SpinLock()
+    {
+        CYG_ASSERT( !test(), "spinlock still claimed");
+    };
+    
+    // Spin on the lock.
+    void spin()
+    {
+        HAL_SPINLOCK_SPIN(lock);
+    };
+
+    // Clear the lock.
+    void clear()
+    {
+        HAL_SPINLOCK_CLEAR(lock);
+    };
+
+    // Try to claim the lock. Return true if successful, false if not.
+    cyg_bool trylock()
+    {
+        cyg_bool testval;
+        HAL_SPINLOCK_TRY(lock,testval);
+        return testval;
+    };
+
+    // Test the current value of the lock
+    cyg_bool test()
+    {
+        cyg_bool testval;
+        HAL_SPINLOCK_TEST(lock, testval);
+        return testval;
+    };
+
+
+    // The following two member functions are only necessary if the
+    // spinlock is to be used in an ISR. 
+    
+    // Claim the spinlock, but also mask this CPU's interrupts while
+    // we have it.
+    void spin_intsave(CYG_INTERRUPT_STATE *state)
+    {
+        HAL_DISABLE_INTERRUPTS(*state);
+        spin();
+    };
+
+    // Clear the lock, and restore the interrupt state saved in
+    // spin_intsave().
+    void clear_intsave(CYG_INTERRUPT_STATE state)
+    {
+        clear();
+        HAL_RESTORE_INTERRUPTS(state);
+    };
+};
+
+#endif
+
+// -------------------------------------------------------------------------
+// Scheduler lock class
+// This uses the scheduler lock API defined by the HAL, or the defaults
+// defined above.
+
+class Cyg_Scheduler_SchedLock
+{
+    static volatile cyg_ucount32 sched_lock         // lock counter
+                    CYGBLD_ATTRIB_ASM_ALIAS( cyg_scheduler_sched_lock )
+                    CYGBLD_ANNOTATE_VARIABLE_SCHED
+                    ;
+    
+    static HAL_SMP_SCHEDLOCK_DATA_TYPE lock_data
+                                       CYGBLD_ANNOTATE_VARIABLE_SCHED;
+    
+protected:
+
+    Cyg_Scheduler_SchedLock()
+    {
+        HAL_SMP_SCHEDLOCK_INIT( sched_lock, lock_data );
+    };
+    
+    // Increment the scheduler lock. If this takes the lock from zero
+    // to one then this code must also do whatever is necessary to
+    // serialize CPUs through the scheduler.
+    static void inc_sched_lock()
+    {
+        CYG_INSTRUMENT_SMP(LOCK_INC,CYG_KERNEL_CPU_THIS(),0);
+        HAL_SMP_SCHEDLOCK_INC( sched_lock, lock_data );
+    };
+
+    // Zero the scheduler lock. This will release the CPU serializing
+    // lock and allow another CPU in.
+    static void zero_sched_lock()
+    {
+        CYG_INSTRUMENT_SMP(LOCK_ZERO,CYG_KERNEL_CPU_THIS(),0);
+        CYG_ASSERT( sched_lock != 0, "Scheduler lock already zero");
+        HAL_SMP_SCHEDLOCK_ZERO( sched_lock, lock_data );
+    };
+    
+    // Set the scheduler lock to a non-zero value. Both the scheduler
+    // lock and the new value must be non-zero.
+    static void set_sched_lock(cyg_uint32 new_lock)
+    {
+        CYG_INSTRUMENT_SMP(LOCK_SET,CYG_KERNEL_CPU_THIS(),new_lock);        
+        CYG_ASSERT( new_lock > 0, "New scheduler lock value == 0");
+        CYG_ASSERT( sched_lock > 0, "Scheduler lock == 0");
+        HAL_SMP_SCHEDLOCK_SET( sched_lock, lock_data, new_lock );        
+    };
+
+    static cyg_ucount32 get_sched_lock()
+    {
+        return sched_lock;
+    };
+};
+
+#define CYGIMP_KERNEL_SCHED_LOCK_DEFINITIONS                    \
+volatile cyg_ucount32 Cyg_Scheduler_SchedLock::sched_lock = 1;  \
+HAL_SMP_SCHEDLOCK_DATA_TYPE Cyg_Scheduler_SchedLock::lock_data;
+
+#endif // __cplusplus
+
+// -------------------------------------------------------------------------
+
+#else // defined(CYGSEM_KERNEL_SMP_SUPPORT) && (CYGSEM_HAL_SMP_SUPPORT)
+
+//==========================================================================
+// SMP support is NOT included.
+
+#undef CYG_KERNEL_SMP_ENABLED
+
+// -------------------------------------------------------------------------
+// Defined values
+// Supply a set of values that describe a single CPU system.
+
+#ifndef HAL_SMP_CPU_TYPE
+#define HAL_SMP_CPU_TYPE                cyg_uint32
+#endif
+
+#define CYGNUM_KERNEL_CPU_MAX           1
+
+#define CYG_KERNEL_CPU_COUNT()          1
+
+#define CYG_KERNEL_CPU_THIS()           0
+
+#define CYG_KERNEL_CPU_NONE             -1
+
+#define CYG_KERNEL_CPU_LOWPRI()         CYG_KERNEL_CPU_THIS()
+
+// -------------------------------------------------------------------------
+// SpinLock class
+// This single CPU version simply goes through the motions of setting
+// and clearing the lock variable for debugging purposes. 
+
+#ifdef __cplusplus
+
+class Cyg_SpinLock
+{
+    cyg_atomic          lock;
+
+public:
+
+    // Constructor, initialize the lock to clear
+    Cyg_SpinLock() { lock = 0; };
+
+    ~Cyg_SpinLock()
+    {
+        CYG_ASSERT( lock == 0, "spinlock still claimed");
+    };
+    
+    // Spin on the lock. In this case we just set it to 1 and proceed.
+    void spin()
+    {
+        CYG_ASSERT( lock == 0, "spinlock already claimed!");
+        lock = 1;
+    };
+
+    // Clear the lock. Again, just set the value.
+    void clear()
+    {
+        CYG_ASSERT( lock != 0, "spinlock already cleared!");
+        lock = 0;
+    };
+
+    // Try to claim the lock. Return true if successful, false if not.
+    cyg_bool trylock()
+    {
+        if( lock ) return false;
+        else { lock = 1; return true; }
+    };
+
+    // Test the current value of the lock
+    cyg_bool test() { return lock; };
+
+
+    // The following two member functions are only necessary if the
+    // spinlock is to be used in an ISR. 
+    
+    // Claim the spinlock, but also mask this CPU's interrupts while
+    // we have it.
+    void spin_intsave(CYG_INTERRUPT_STATE *state)
+    {
+        HAL_DISABLE_INTERRUPTS(*state);
+        spin();
+    };
+
+    // Clear the lock, and restore the interrupt state saved in
+    // spin_intsave().
+    void clear_intsave(CYG_INTERRUPT_STATE state)
+    {
+        clear();
+        HAL_RESTORE_INTERRUPTS(state);
+    };
+
+};
+
+// -------------------------------------------------------------------------
+// Scheduler lock class
+
+class Cyg_Scheduler_SchedLock
+{
+    static volatile cyg_ucount32 sched_lock         // lock counter
+                    CYGBLD_ATTRIB_ASM_ALIAS( cyg_scheduler_sched_lock )
+                    CYGBLD_ANNOTATE_VARIABLE_SCHED
+                    ;
+    
+    // For non-SMP versions, the code here does the basic and obvious things.
+protected:
+
+    Cyg_Scheduler_SchedLock()
+    {
+        sched_lock = 1;
+    };
+    
+    // Increment the scheduler lock, possibly taking it from zero to
+    // one.
+    static void inc_sched_lock()
+    {
+        sched_lock++;
+    };
+
+    static void zero_sched_lock()
+    {
+        CYG_ASSERT( sched_lock != 0, "Scheduler lock already zero");
+        sched_lock = 0;
+    };
+    
+    // Set the scheduler lock to a non-zero value. Both the scheduler
+    // lock and the new value must be non-zero.
+    static void set_sched_lock(cyg_uint32 new_lock)
+    {
+        CYG_ASSERT( new_lock > 0, "New scheduler lock value == 0");
+        CYG_ASSERT( sched_lock > 0, "Scheduler lock == 0");
+        sched_lock = new_lock;
+    };
+
+    static cyg_ucount32 get_sched_lock()
+    {
+        return sched_lock;
+    };
+};
+
+#define CYGIMP_KERNEL_SCHED_LOCK_DEFINITIONS                    \
+volatile cyg_ucount32 Cyg_Scheduler_SchedLock::sched_lock = 1;
+
+#endif // __cplusplus
+
+#endif // defined(CYGSEM_KERNEL_SMP_SUPPORT) && (CYGSEM_HAL_SMP_SUPPORT)
+
+// -------------------------------------------------------------------------
+#endif // ifndef CYGONCE_KERNEL_SMP_HXX
+
+// EOF smp.hxx
--- a/packages/kernel/current/include/test/stackmon.h
+++ b/packages/kernel/current/include/test/stackmon.h
@@ -61,6 +61,7 @@
 #  include <cyg/kernel/thread.hxx>
 #  include <cyg/kernel/thread.inl>
 # endif
+# include <cyg/kernel/smp.hxx>
 #endif
 
 #ifndef STACKMON_PRINTF
@@ -129,13 +130,17 @@ inline void cyg_test_dump_thread_stack_s
 inline void cyg_test_dump_idlethread_stack_stats( char *comment )
 {
 #if defined(CYGPKG_KERNEL)
-    extern Cyg_Thread idle_thread;
-    // idle thread is not really a plain CygThread; danger.
-    char *ibase  = (char *)idle_thread.get_stack_base();
-    char *istack = ibase + idle_thread.get_stack_size();
-    cyg_test_size_a_stack( comment,
-              "%20s : Idlethread stack used %5d size %5d\n",
-              ibase, istack );
+    int i;
+    extern Cyg_Thread idle_thread[CYGNUM_KERNEL_CPU_MAX];
+    for( i = 0; i < CYGNUM_KERNEL_CPU_MAX; i++ )
+    {
+        // idle thread is not really a plain CygThread; danger.
+        char *ibase  = (char *)idle_thread[i].get_stack_base();
+        char *istack = ibase + idle_thread[i].get_stack_size();
+        cyg_test_size_a_stack( comment,
+                               "%20s : Idlethread stack used %5d size %5d\n",
+                               ibase, istack );
+    }
 #endif
 }
 
--- a/packages/kernel/current/include/thread.inl
+++ b/packages/kernel/current/include/thread.inl
@@ -88,6 +88,8 @@ inline void Cyg_HardwareThread::check_st
     cyg_uint32 *top =  (cyg_uint32 *)(stack_base + stack_size);
     cyg_ucount32 i;
 
+    CYG_INSTRUMENT_THREAD(CHECK_STACK, base, top );
+    
     CYG_ASSERT( 0 == ((sizeof(CYG_WORD)-1) & (cyg_uint32)base), "stack base not word aligned" );
     CYG_ASSERT( 0 == ((sizeof(CYG_WORD)-1) & (cyg_uint32)top),  "stack  top not word aligned" );
 
@@ -165,6 +167,8 @@ inline void Cyg_HardwareThread::attach_s
 
         unsigned int i;
 
+        CYG_INSTRUMENT_THREAD(ATTACH_STACK, base, top );
+        
         CYG_ASSERT( NULL != base, "stack base non-NULL" );
         CYG_ASSERT( 0 == ((sizeof(CYG_WORD)-1) & (cyg_uint32)base), "stack base alignment" );
         CYG_ASSERT( 0 == ((sizeof(CYG_WORD)-1) & (cyg_uint32)top),  "stack  top alignment" );
--- a/packages/kernel/current/src/common/kapi.cxx
+++ b/packages/kernel/current/src/common/kapi.cxx
@@ -456,6 +456,27 @@ externC void cyg_interrupt_configure(
     Cyg_Interrupt::configure_interrupt( (cyg_vector)vector, level, up );
 }
 
+externC void cyg_interrupt_set_cpu(
+    cyg_vector_t        vector,         /* vector to control                 */
+    cyg_cpu_t           cpu             /* CPU to set                        */
+)
+{
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT    
+    Cyg_Interrupt::set_cpu( vector, cpu );
+#endif    
+}
+
+externC cyg_cpu_t cyg_interrupt_get_cpu(
+    cyg_vector_t        vector          /* vector to control                 */
+)
+{
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT        
+    return Cyg_Interrupt::get_cpu( vector );
+#else
+    return CYG_KERNEL_CPU_THIS();
+#endif    
+    
+}
 
 /*---------------------------------------------------------------------------*/
 /* Counters, Clocks and Alarms                                               */
@@ -877,6 +898,24 @@ externC void cyg_mutex_release( cyg_mute
     ((Cyg_Mutex *)mutex)->release();
 }
 
+#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
+externC void cyg_mutex_set_ceiling( 
+    cyg_mutex_t *mutex, 
+    cyg_priority_t priority )
+{
+    ((Cyg_Mutex *)mutex)->set_ceiling(priority);
+}
+#endif
+
+#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
+externC void cyg_mutex_set_protocol( 
+    cyg_mutex_t *mutex,
+    enum cyg_protcol protocol )
+{
+    ((Cyg_Mutex *)mutex)->set_protocol((Cyg_Mutex::cyg_protcol)protocol);
+}
+#endif
+
 /*---------------------------------------------------------------------------*/
 /* Condition Variables                                                       */
 
@@ -923,6 +962,62 @@ externC cyg_bool_t cyg_cond_timed_wait(
 
 #endif
 
+/*---------------------------------------------------------------------------*/
+/* Spinlocks                                                                 */
+
+externC void cyg_spinlock_init(
+    cyg_spinlock_t      *lock,          /* spinlock to initialize            */
+    cyg_bool_t          locked          /* init locked or unlocked           */
+)
+{
+    CYG_ASSERT_SIZES( cyg_spinlock_t, Cyg_SpinLock );
+
+    // Create the spinlock in cleared state
+    Cyg_SpinLock *t = new((void *)lock) Cyg_SpinLock();
+
+    // If the lock is to start locked, then lock it now.
+    if( locked )
+        t->spin();
+}
+
+externC void cyg_spinlock_destroy( cyg_spinlock_t *lock )
+{
+    ((Cyg_SpinLock *)lock)->~Cyg_SpinLock();
+}
+
+externC void cyg_spinlock_spin( cyg_spinlock_t *lock )
+{
+    ((Cyg_SpinLock *)lock)->spin();
+}
+
+externC void cyg_spinlock_clear( cyg_spinlock_t *lock )
+{
+    ((Cyg_SpinLock *)lock)->clear();
+}
+
+externC cyg_bool_t cyg_spinlock_try( cyg_spinlock_t *lock )
+{
+    return ((Cyg_SpinLock *)lock)->trylock();
+}
+
+externC cyg_bool_t cyg_spinlock_test( cyg_spinlock_t *lock )
+{
+    return ((Cyg_SpinLock *)lock)->test();
+}
+
+externC void cyg_spinlock_spin_intsave( cyg_spinlock_t *lock,
+                                cyg_addrword_t *istate )
+{
+    ((Cyg_SpinLock *)lock)->spin_intsave(istate);
+}
+    
+externC void cyg_spinlock_clear_intsave( cyg_spinlock_t *lock,
+                                 cyg_addrword_t istate )
+{
+    ((Cyg_SpinLock *)lock)->clear_intsave(istate);
+}
+    
+
 // -------------------------------------------------------------------------
 // Check structure sizes.
 // This class and constructor get run automatically in debug versions
@@ -965,6 +1060,7 @@ Cyg_Check_Structure_Sizes::Cyg_Check_Str
     CYG_CHECK_SIZES( cyg_flag_t, Cyg_Flag );
     CYG_CHECK_SIZES( cyg_mutex_t, Cyg_Mutex );
     CYG_CHECK_SIZES( cyg_cond_t, Cyg_Condition_Variable );
+    CYG_CHECK_SIZES( cyg_spinlock_t, Cyg_SpinLock );
     
     CYG_ASSERT( !fail, "Size checks failed");
 }
--- a/packages/kernel/current/src/common/thread.cxx
+++ b/packages/kernel/current/src/common/thread.cxx
@@ -77,8 +77,8 @@ Cyg_HardwareThread::thread_entry( Cyg_Th
 {
     CYG_REPORT_FUNCTION();
 
-    Cyg_Scheduler::scheduler.need_reschedule = false; // finished rescheduling
-    Cyg_Scheduler::scheduler.current_thread = thread; // restore current thread pointer
+    Cyg_Scheduler::scheduler.clear_need_reschedule(); // finished rescheduling
+    Cyg_Scheduler::scheduler.set_current_thread(thread); // restore current thread pointer
 
     CYG_INSTRUMENT_THREAD(ENTER,thread,0);
     
@@ -90,11 +90,11 @@ Cyg_HardwareThread::thread_entry( Cyg_Th
     
     // Zero the lock
     HAL_REORDER_BARRIER ();            // Prevent the compiler from moving
-    Cyg_Scheduler::sched_lock = 0;     // the assignment into the code above.
+    Cyg_Scheduler::zero_sched_lock();     // the assignment into the code above.
     HAL_REORDER_BARRIER();
 
     // Call entry point in a loop.
-    
+
     for(;;)
     {
         thread->entry_point(thread->entry_data);
@@ -190,6 +190,8 @@ Cyg_Thread::Cyg_Thread(
 {
     CYG_REPORT_FUNCTION();
 
+    CYG_INSTRUMENT_THREAD(CREATE,this,0);
+    
     // Start the thread in suspended state.
     state               = SUSPENDED;
     suspend_count       = 1;
@@ -592,7 +594,7 @@ Cyg_Thread::resume()
     CYG_REPORT_FUNCTION();
 
     CYG_INSTRUMENT_THREAD(RESUME,this,Cyg_Scheduler::current_thread);
-            
+ 
     // Prevent preemption
     Cyg_Scheduler::lock();
 
@@ -619,6 +621,7 @@ Cyg_Thread::resume()
 
     // Unlock the scheduler and maybe switch threads
     Cyg_Scheduler::unlock();
+
     CYG_REPORT_RETURN();
 }
 
@@ -736,13 +739,17 @@ Cyg_Thread::exit()
     // clear the timer; if there was none, no worries.
     clear_timer();
 
-    self->state = EXITED;
-
-    Cyg_Scheduler::scheduler.rem_thread(self);
+    // It is possible that we have already been killed by another
+    // thread, in which case we do not want to try and take ourself
+    // out of the scheduler again.
+    if( self->state != EXITED )
+    {
+        self->state = EXITED;
 
-    // Un-nest any scheduler locks we have until we
-    // suspend.
-    for( ;; ) Cyg_Scheduler::unlock();
+        Cyg_Scheduler::scheduler.rem_thread(self);
+    }
+
+    Cyg_Scheduler::reschedule();
 }
 
 // -------------------------------------------------------------------------
@@ -910,9 +917,13 @@ Cyg_Thread::set_priority( cyg_priority n
     // priority is less than that of some other runnable thread, in
     // practice checking that is as expensive as what the scheduler
     // will do anyway).
+    // If it is not the current thread then we need to see whether
+    // it is more worthy of execution than any current thread and
+    // rescheduled if necessary.
     
     if( this == Cyg_Scheduler::get_current_thread() )
-        Cyg_Scheduler::need_reschedule = true;
+         Cyg_Scheduler::set_need_reschedule();
+    else Cyg_Scheduler::set_need_reschedule(this);
     
     // Unlock the scheduler and maybe switch threads
     Cyg_Scheduler::unlock();
@@ -1177,10 +1188,10 @@ Cyg_ThreadTimer::alarm(
 # endif // CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE
 #endif // CYGNUM_HAL_STACK_SIZE_MINIMUM
 
-static char idle_thread_stack[CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE];
+static char idle_thread_stack[CYGNUM_KERNEL_CPU_MAX][CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE];
 
 // Loop counter for debugging/housekeeping
-cyg_uint32 idle_thread_loops = 1;
+cyg_uint32 idle_thread_loops[CYGNUM_KERNEL_CPU_MAX];
 
 // -------------------------------------------------------------------------
 // Idle thread code.
@@ -1192,9 +1203,9 @@ idle_thread_main( CYG_ADDRESS data )
 
     for(;;)
     {
-        idle_thread_loops++;
+        idle_thread_loops[CYG_KERNEL_CPU_THIS()]++;
 
-        HAL_IDLE_THREAD_ACTION(idle_thread_loops);
+        HAL_IDLE_THREAD_ACTION(idle_thread_loops[CYG_KERNEL_CPU_THIS()]);
 
 #if 0
         // For testing, it is useful to be able to fake
@@ -1217,47 +1228,35 @@ idle_thread_main( CYG_ADDRESS data )
 class Cyg_IdleThread : public Cyg_Thread
 {
 public:
-    Cyg_IdleThread(
-        cyg_thread_entry        *entry,           // entry point function
-        CYG_ADDRWORD            entry_data,       // entry data
-        cyg_ucount32            stack_size = 0,   // stack size, 0 = use default
-        CYG_ADDRESS             stack_base = 0    // stack base, NULL = allocate
-        );
+    Cyg_IdleThread();
         
 };
 
 // -------------------------------------------------------------------------
+// Instantiate the idle thread
+
+Cyg_IdleThread idle_thread[CYGNUM_KERNEL_CPU_MAX] CYG_INIT_PRIORITY( IDLE_THREAD );
+
+// -------------------------------------------------------------------------
 // Idle threads constructor
 
-Cyg_IdleThread::Cyg_IdleThread(
-    cyg_thread_entry        *entry,           // entry point function
-    CYG_ADDRWORD            entry_data,       // entry data
-    cyg_ucount32            stack_size,       // stack size, 0 = use default
-    CYG_ADDRESS             stack_base        // stack base, NULL = allocate
-    )
+Cyg_IdleThread::Cyg_IdleThread()
     : Cyg_Thread( CYG_THREAD_MIN_PRIORITY,
-                  entry,
-                  entry_data,
+                  idle_thread_main,
+                  0,
                   "Idle Thread",
-                  stack_base,
-                  stack_size)
+                  (CYG_ADDRESS)idle_thread_stack[this-&idle_thread[0]],
+                  CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE)
 {
     CYG_REPORT_FUNCTION();
 
-    resume();
+    // Call into scheduler to set up this thread as the default
+    // current thread for its CPU.
+    
+    Cyg_Scheduler::scheduler.set_idle_thread( this, this-&idle_thread[0] );
+
     CYG_REPORT_RETURN();
 }
 
 // -------------------------------------------------------------------------
-// Instantiate the idle thread
-
-Cyg_IdleThread idle_thread CYG_INIT_PRIORITY( IDLE_THREAD ) =
-Cyg_IdleThread( idle_thread_main,
-                0,
-                CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE,
-                CYG_ADDRESS(idle_thread_stack)
-    ); 
-
-
-// -------------------------------------------------------------------------
 // EOF common/thread.cxx
--- a/packages/kernel/current/src/instrmnt/meminst.cxx
+++ b/packages/kernel/current/src/instrmnt/meminst.cxx
@@ -117,6 +117,20 @@ cyg_uint32 instrument_flags[(CYG_INSTRUM
 
 // -------------------------------------------------------------------------
 
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
+
+HAL_SPINLOCK_TYPE instrument_lock = HAL_SPINLOCK_INIT_CLEAR;
+
+#else
+
+#define HAL_SPINLOCK_SPIN( __lock )
+
+#define HAL_SPINLOCK_CLEAR( __lock )
+
+#endif
+
+// -------------------------------------------------------------------------
+
 void cyg_instrument( cyg_uint32 type, CYG_ADDRWORD arg1, CYG_ADDRWORD arg2 )
 {
 
@@ -131,11 +145,16 @@ void cyg_instrument( cyg_uint32 type, CY
 #endif        
     {
         HAL_DISABLE_INTERRUPTS(old_ints);
-
+        HAL_SPINLOCK_SPIN( instrument_lock );
+        
         Instrument_Record *p = instrument_buffer_pointer;
         Cyg_Thread *t = Cyg_Scheduler::get_current_thread();
         p->type             = type;
-        p->thread           = (t==0)?0xFFFF:t->get_unique_id();
+        p->thread           = (t==0)?0x0FFF:t->get_unique_id();
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
+        // Add CPU id to in top 4 bytes of thread id
+        p->thread           = (p->thread&0x0FFF)|(CYG_KERNEL_CPU_THIS()<<12);
+#endif        
 #ifdef CYGVAR_KERNEL_COUNTERS_CLOCK        
 //        p->timestamp        = Cyg_Clock::real_time_clock->current_value_lo();
         HAL_CLOCK_READ( &p->timestamp );
@@ -156,6 +175,7 @@ void cyg_instrument( cyg_uint32 type, CY
         if( p != &instrument_buffer_end )
             instrument_buffer_pointer = p;
 #endif
+        HAL_SPINLOCK_CLEAR( instrument_lock );        
         HAL_RESTORE_INTERRUPTS(old_ints);
     }
     
--- a/packages/kernel/current/src/intr/intr.cxx
+++ b/packages/kernel/current/src/intr/intr.cxx
@@ -58,10 +58,11 @@
 // -------------------------------------------------------------------------
 // Statics
 
-// Interrupt disable counter. Note that this is initialized to 1 since
-// enable_interrupts() is called in Cyg_Scheduler::start().
+volatile cyg_int32 Cyg_Interrupt::disable_counter[CYGNUM_KERNEL_CPU_MAX];
 
-cyg_int32 Cyg_Interrupt::disable_counter = 1;
+Cyg_SpinLock Cyg_Interrupt::interrupt_disable_spinlock CYG_INIT_PRIORITY( INTERRUPTS );
+
+CYG_INTERRUPT_STATE Cyg_Interrupt::interrupt_disable_state[CYGNUM_KERNEL_CPU_MAX];
 
 // -------------------------------------------------------------------------
 
@@ -200,7 +201,6 @@ Cyg_Interrupt::call_pending_DSRs(void)
 {
     CYG_ASSERT( Cyg_Scheduler::get_sched_lock() == 1,
                 "DSRs being called with sched_lock not equal to 1");
-    
     HAL_INTERRUPT_STACK_CALL_PENDING_DSRS();
 }
 
@@ -271,6 +271,10 @@ interrupt_end(
 {
 //    CYG_REPORT_FUNCTION();
 
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT    
+    Cyg_Scheduler::lock();
+#endif
+    
     // Sometimes we have a NULL intr object pointer.
     cyg_vector vector = (intr!=NULL)?intr->vector:0;
 
@@ -319,7 +323,7 @@ interrupt_end(
 
 #ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
 
-Cyg_Interrupt *Cyg_Interrupt::chain_list[CYGNUM_HAL_ISR_COUNT];
+Cyg_Interrupt *Cyg_Interrupt::chain_list[CYGNUM_HAL_ISR_TABLE_SIZE];
 
 #endif
 
@@ -545,15 +549,22 @@ Cyg_Interrupt::disable_interrupts(void)
 {
     CYG_REPORT_FUNCTION();
 
-    CYG_INSTRUMENT_INTR(DISABLE, disable_counter+1, 0);
+    CYG_INSTRUMENT_INTR(DISABLE, disable_counter[CYG_KERNEL_CPU_THIS()]+1, 0);
 
-    CYG_INTERRUPT_STATE dummy;
+    HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS();
 
-    HAL_DISABLE_INTERRUPTS(dummy);
+    // If the disable_counter is zero, disable interrupts and claim the spinlock.
+    
+    if( 0 == disable_counter[cpu_this] )
+    {
+        // Claim the spinlock and disable interrupts. We save the original interrupt
+        // enable state to restore later.
+        interrupt_disable_spinlock.spin_intsave(&interrupt_disable_state[cpu_this]);
+    }
 
-    CYG_ASSERT( disable_counter >= 0 , "Disable counter negative");
+    // Now increment our disable counter.
     
-    disable_counter++;
+    disable_counter[cpu_this]++;
     
     CYG_REPORT_RETURN();
 }
@@ -567,15 +578,18 @@ Cyg_Interrupt::enable_interrupts(void)
 {
     CYG_REPORT_FUNCTION();
         
-    CYG_INSTRUMENT_INTR(ENABLE, disable_counter, 0);
+    CYG_INSTRUMENT_INTR(ENABLE, disable_counter[CYG_KERNEL_CPU_THIS()], 0);
 
-    CYG_ASSERT( disable_counter > 0 , "Disable counter not greater than zero");
+    HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS();
+
+    CYG_ASSERT( disable_counter[cpu_this] > 0 , "Disable counter not greater than zero");
     
-    disable_counter--;
-
-    if ( disable_counter == 0 )
+    // If the disable counter goes to zero, then release the spinlock and restore
+    // the previous interrupt state.
+    
+    if( --disable_counter[cpu_this] == 0 )
     {
-        HAL_ENABLE_INTERRUPTS();
+        interrupt_disable_spinlock.clear_intsave(interrupt_disable_state[cpu_this]);
     }
 
     CYG_REPORT_RETURN();
@@ -660,4 +674,52 @@ Cyg_Interrupt::configure_interrupt(
 }
 
 // -------------------------------------------------------------------------
+// SMP support for setting/getting interrupt CPU
+
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
+
+void
+Cyg_Interrupt::set_cpu(
+    cyg_vector vector,              // vector to control
+    HAL_SMP_CPU_TYPE cpu            // CPU to set
+    )
+{
+    CYG_REPORT_FUNCTION();
+    CYG_REPORT_FUNCARG2("vector = %d, cpu = %d", vector, cpu );
+
+    CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");    
+    CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
+
+    CYG_INSTRUMENT_INTR(SET_CPU, vector, cpu);
+
+    HAL_INTERRUPT_SET_CPU( vector, cpu );
+
+    CYG_REPORT_RETURN();
+}
+
+HAL_SMP_CPU_TYPE
+Cyg_Interrupt::get_cpu(
+    cyg_vector vector              // vector to control
+    )
+{
+    CYG_REPORT_FUNCTION();
+    CYG_REPORT_FUNCARG1("vector = %d", vector);
+
+    CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");    
+    CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
+
+    HAL_SMP_CPU_TYPE cpu;
+    
+    HAL_INTERRUPT_GET_CPU( vector, cpu );
+
+    CYG_INSTRUMENT_INTR(GET_CPU, vector, cpu);
+    
+    CYG_REPORT_RETURN();
+
+    return cpu;
+}
+
+#endif
+
+// -------------------------------------------------------------------------
 // EOF intr/intr.cxx
--- a/packages/kernel/current/src/sched/bitmap.cxx
+++ b/packages/kernel/current/src/sched/bitmap.cxx
@@ -126,7 +126,7 @@ void Cyg_Scheduler_Implementation::add_t
     // current thread, request a reschedule.
 
     if( thread->priority < Cyg_Scheduler::get_current_thread()->priority )
-        need_reschedule = true;
+        set_need_reschedule();
 }
 
 // -------------------------------------------------------------------------
@@ -142,6 +142,25 @@ void Cyg_Scheduler_Implementation::rem_t
                 "Run queue bit not set" );
 
     run_queue &= ~(1<<thread->priority);
+
+    if( thread == Cyg_Scheduler::get_current_thread() )
+        set_need_reschedule();
+}
+
+// -------------------------------------------------------------------------
+// Set up initial idle thread
+
+void Cyg_Scheduler_Implementation::set_idle_thread( Cyg_Thread *thread, HAL_SMP_CPU_TYPE cpu )
+{
+    CYG_REPORT_FUNCTION();
+
+    // Make the thread the current thread for this CPU.
+    
+    current_thread[cpu] = thread;
+    
+    // This will insert the thread in the run queues and make it
+    // available to execute.
+    thread->resume();
 }
 
 // -------------------------------------------------------------------------
--- a/packages/kernel/current/src/sched/mlqueue.cxx
+++ b/packages/kernel/current/src/sched/mlqueue.cxx
@@ -78,8 +78,7 @@
 
 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
 
-cyg_ucount32 Cyg_Scheduler_Implementation::timeslice_count =
-                                        CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS;
+cyg_ucount32 Cyg_Scheduler_Implementation::timeslice_count[CYGNUM_KERNEL_CPU_MAX];
 
 #endif
 
@@ -96,6 +95,21 @@ Cyg_Scheduler_Implementation::Cyg_Schedu
         
     queue_map   = 0;
 
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
+
+    pending_map = 0;
+    
+    for( int i = 0; i < CYGNUM_KERNEL_SCHED_PRIORITIES; i++ )
+        pending[i] = 0;
+
+#endif
+    
+    for( int i = 0; i < CYGNUM_KERNEL_CPU_MAX; i++ )
+    {
+        timeslice_count[i] = CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS;
+        need_reschedule[i] = true;
+    }
+    
     CYG_REPORT_RETURN();
 }
 
@@ -113,15 +127,71 @@ Cyg_Scheduler_Implementation::schedule(v
     CYG_ASSERT( queue_map != 0, "Run queue empty");
     CYG_ASSERT( queue_map & (1<<CYG_THREAD_MIN_PRIORITY), "Idle thread vanished!!!");
     CYG_ASSERT( !run_queue[CYG_THREAD_MIN_PRIORITY].empty(), "Idle thread vanished!!!");
+
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
+
+    Cyg_Thread *current = get_current_thread();
+    register cyg_uint32 index;
+
+    CYG_ASSERT( current->cpu != CYG_KERNEL_CPU_NONE, "Current thread does not have CPU set!");
+
+    // If the current thread is still runnable, return it to pending
+    // state so that it can be considered alongside any other threads
+    // for execution.
+    if( current->get_state() == Cyg_Thread::RUNNING )
+    {
+        current->cpu = CYG_KERNEL_CPU_NONE;
+        pending[current->priority]++;
+        pending_map |= (1<<current->priority);
+    }
+    else
+    {
+        // Otherwise, ensure that the thread is no longer marked as
+        // running.
+        current->cpu = CYG_KERNEL_CPU_NONE;        
+    }
+
     
+    HAL_LSBIT_INDEX(index, pending_map);
+
+    Cyg_RunQueue *queue = &run_queue[index];
+    
+    CYG_ASSERT( !queue->empty(), "Queue for index empty");
+    CYG_ASSERT( pending[index] > 0, "Pending array and map disagree");
+
+    Cyg_Thread *thread = queue->get_head();
+
+    // We know there is a runnable thread in this queue, If the thread
+    // we got is not it, scan until we find it. While not constant time,
+    // this search has an upper bound of the number of CPUs in the system.
+    
+    while( thread->cpu != CYG_KERNEL_CPU_NONE )
+        thread = thread->get_next();
+
+    // Take newly scheduled thread out of pending map
+    thread->cpu = CYG_KERNEL_CPU_THIS();
+    if( --pending[index] == 0 )
+        pending_map &= ~(1<<index);
+    
+#else    
+
     register cyg_uint32 index;
 
     HAL_LSBIT_INDEX(index, queue_map);
 
-    Cyg_Thread *thread = run_queue[index].highpri();
+    Cyg_RunQueue *queue = &run_queue[index];
+    
+    CYG_ASSERT( !queue->empty(), "Queue for index empty");
+
+    Cyg_Thread *thread = queue->get_head();
 
+#endif
+    
+    CYG_INSTRUMENT_MLQ( SCHEDULE, thread, index);
+    
     CYG_ASSERT( thread != NULL , "No threads in run queue");
-
+    CYG_ASSERT( thread->queue == NULL , "Runnable thread on a queue!");
+   
     CYG_REPORT_RETVAL(thread);
 
     return thread;
@@ -136,12 +206,16 @@ Cyg_Scheduler_Implementation::add_thread
     CYG_REPORT_FUNCARG1("thread=%08x", thread);
 
     cyg_priority pri                               = thread->priority;
-    Cyg_SchedulerThreadQueue_Implementation *queue = &run_queue[pri];
+    Cyg_RunQueue *queue = &run_queue[pri];
 
+    CYG_INSTRUMENT_MLQ( ADD, thread, pri);
+    
     CYG_ASSERT((CYG_THREAD_MIN_PRIORITY >= pri) 
                && (CYG_THREAD_MAX_PRIORITY <= pri),
                "Priority out of range!");
 
+    CYG_ASSERT( ((queue_map & (1<<pri))!=0) == ((!run_queue[pri].empty())!=0), "Map and queue disagree");
+
     // If the thread is on some other queue, remove it
     // here.
     if( thread->queue != NULL )
@@ -156,21 +230,38 @@ Cyg_Scheduler_Implementation::add_thread
       
         queue_map |= (1<<pri);
 
-        // If the new thread is higher priority than the
-        // current thread, request a reschedule.
-
-        if( pri < Cyg_Scheduler::get_current_thread()->priority )
-            need_reschedule = true;
-        
     }
     // else the queue already has an occupant, queue behind him
 
+    queue->add_tail(thread);
+
+    // If the new thread is higher priority than any
+    // current thread, request a reschedule.
+
+    set_need_reschedule(thread);
+    
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
+
+    // If the thread is not currently running, increment the pending
+    // count for the priority, and if necessary set the bit in the
+    // pending map.
+
+    if( thread->cpu == CYG_KERNEL_CPU_NONE )
+    {
+        if( pending[pri]++ == 0 )
+            pending_map |= (1<<pri);
+    }
+    // Otherwise the pending count will be dealt with in schedule().
+    
+#endif    
+    
+    CYG_ASSERT( thread->queue == NULL , "Runnable thread on a queue!");
     CYG_ASSERT( queue_map != 0, "Run queue empty");
     CYG_ASSERT( queue_map & (1<<pri), "Queue map bit not set for pri");
+    CYG_ASSERT( !run_queue[pri].empty(), "Queue for pri empty");
+    CYG_ASSERT( ((queue_map & (1<<pri))!=0) == ((!run_queue[pri].empty())!=0), "Map and queue disagree");    
     CYG_ASSERT( queue_map & (1<<CYG_THREAD_MIN_PRIORITY), "Idle thread vanished!!!");
-//    CYG_ASSERT( !run_queue[CYG_THREAD_MIN_PRIORITY].empty(), "Idle thread vanished!!!");
-    
-    queue->enqueue(thread);
+    CYG_ASSERT( !run_queue[CYG_THREAD_MIN_PRIORITY].empty(), "Idle thread vanished!!!");
     
     CYG_REPORT_RETURN();
 }
@@ -184,13 +275,39 @@ Cyg_Scheduler_Implementation::rem_thread
     CYG_REPORT_FUNCARG1("thread=%08x", thread);
         
     CYG_ASSERT( queue_map != 0, "Run queue empty");
-      
-    cyg_priority pri                               = thread->priority;
-    Cyg_SchedulerThreadQueue_Implementation *queue = &run_queue[pri];
+
+    cyg_priority pri    = thread->priority;
+    Cyg_RunQueue *queue = &run_queue[pri];
+
+    CYG_INSTRUMENT_MLQ( REM, thread, pri);
+    
+    CYG_ASSERT( pri != CYG_THREAD_MIN_PRIORITY, "Idle thread trying to sleep!");
+    CYG_ASSERT( !run_queue[CYG_THREAD_MIN_PRIORITY].empty(), "Idle thread vanished!!!");
+
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
+
+    if( thread->cpu == CYG_KERNEL_CPU_NONE )
+    {
+        // If the thread is not running, then we need to adjust the
+        // pending count array and map if necessary.
 
-    CYG_ASSERT( pri != CYG_THREAD_MIN_PRIORITY, "Idle thread trying to sleep!");
+        if( --pending[pri] == 0 )
+            pending_map &= ~(1<<pri);
+    }
+    else
+    {
+        // If the target thread is currently running on a different
+        // CPU, send a reschedule interrupt there to deschedule it.        
+        if( thread->cpu != CYG_KERNEL_CPU_THIS() )
+            CYG_KERNEL_CPU_RESCHEDULE_INTERRUPT( thread->cpu, 0 );
+    }
+    // If the thread is current running on this CPU, then the pending
+    // count will be dealt with in schedule().
+    
+#endif
+        
     CYG_ASSERT( queue_map & (1<<pri), "Queue map bit not set for pri");
-    CYG_ASSERT( !run_queue[CYG_THREAD_MIN_PRIORITY].empty(), "Idle thread vanished!!!");
+    CYG_ASSERT( !run_queue[pri].empty(), "Queue for pri empty");
     
     // remove thread from queue
     queue->remove(thread);
@@ -206,8 +323,104 @@ Cyg_Scheduler_Implementation::rem_thread
     CYG_ASSERT( queue_map != 0, "Run queue empty");
     CYG_ASSERT( queue_map & (1<<CYG_THREAD_MIN_PRIORITY), "Idle thread vanished!!!");
     CYG_ASSERT( !run_queue[CYG_THREAD_MIN_PRIORITY].empty(), "Idle thread vanished!!!");
+    CYG_ASSERT( ((queue_map & (1<<pri))!=0) == ((!run_queue[pri].empty())!=0), "Map and queue disagree");
+    
+    CYG_REPORT_RETURN();
+}
 
-    CYG_REPORT_RETURN();
+// -------------------------------------------------------------------------
+// Set the need_reschedule flag
+// This function overrides the definition in Cyg_Scheduler_Base and tests
+// for a reschedule condition based on the priorities of the given thread
+// and the current thread(s).
+
+void Cyg_Scheduler_Implementation::set_need_reschedule(Cyg_Thread *thread)
+{
+#ifndef CYGPKG_KERNEL_SMP_SUPPORT
+
+    if( current_thread[0]->priority > thread->priority ||
+        current_thread[0]->get_state() != Cyg_Thread::RUNNING )
+        need_reschedule[0] = true;
+    
+#else
+
+    HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS();
+    HAL_SMP_CPU_TYPE cpu_count = CYG_KERNEL_CPU_COUNT();
+
+    // Start with current CPU. If we can do the job locally then
+    // that is most efficient. Only go on to other CPUs if that is
+    // not possible.
+        
+    HAL_SMP_CPU_TYPE cpu = cpu_this;
+    HAL_SMP_CPU_TYPE cpu_last = (cpu + cpu_count - 1) % cpu_count;
+
+    for(;;)
+    {
+        
+        // If a CPU is not already marked for rescheduling, and its
+        // current thread is of lower priority than _thread_, then
+        // set its need_reschedule flag.
+
+        Cyg_Thread *cur = current_thread[cpu];
+        
+        if( !need_reschedule[cpu] &&
+            (cur->priority > thread->priority)
+          )
+        {
+            need_reschedule[cpu] = true;
+
+            if( cpu != cpu_this )
+            {
+                CYG_INSTRUMENT_SMP( RESCHED_SEND, cpu, 0 );
+                CYG_KERNEL_CPU_RESCHEDULE_INTERRUPT( cpu, 0 );
+            }
+
+            // Having notionally rescheduled _thread_ onto the cpu, we
+            // now see if we can reschedule the former current thread of
+            // that CPU onto another.
+            
+            thread = cur;
+            cpu = (cpu + 1) % cpu_count;
+            cpu_last = (cpu + cpu_count - 1) % cpu_count;
+            continue;
+        }
+
+        // If that was the last CPU in the circle, stop here.
+        if( cpu == cpu_last )
+            break;
+
+        // Otherwise go on to the next.
+        cpu = (cpu + 1) % cpu_count;
+    } 
+
+#endif  
+}
+
+// -------------------------------------------------------------------------
+// Set up initial idle thread
+
+void Cyg_Scheduler_Implementation::set_idle_thread( Cyg_Thread *thread, HAL_SMP_CPU_TYPE cpu )
+{
+    // Make the thread the current thread for this CPU.
+    
+    current_thread[cpu] = thread;
+
+    // This will insert the thread in the run queues and make it
+    // available to execute.
+    thread->resume();
+
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
+
+    thread->cpu = cpu;
+    
+    // In SMP, we need to take this thread out of the pending array
+    // and map.
+    
+    cyg_priority pri    = thread->priority;
+    if( --pending[pri] == 0 )
+        pending_map &= ~(1<<pri);
+#endif    
+    
 }
 
 // -------------------------------------------------------------------------
@@ -252,19 +465,61 @@ Cyg_Scheduler_Implementation::unique( cy
 
 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
 
+// -------------------------------------------------------------------------
+
 void
 Cyg_Scheduler_Implementation::timeslice(void)
 {
 #ifdef CYGDBG_KERNEL_TRACE_TIMESLICE
     CYG_REPORT_FUNCTION();
 #endif
+
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
+
+    HAL_SMP_CPU_TYPE cpu;
+    HAL_SMP_CPU_TYPE cpu_count = CYG_KERNEL_CPU_COUNT();
+    HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS();
+    
+    for( cpu = 0; cpu < cpu_count; cpu++ )
+    {
+        if( --timeslice_count[cpu] == 0 )
+            if( cpu == cpu_this )
+                timeslice_cpu();
+            else CYG_KERNEL_CPU_TIMESLICE_INTERRUPT( cpu, 0 );
+    }
+
+#else    
+
+    if( --timeslice_count[CYG_KERNEL_CPU_THIS()] )
+        timeslice_cpu();
+    
+#endif
+
+#ifdef CYGDBG_KERNEL_TRACE_TIMESLICE
+    CYG_REPORT_RETURN();
+#endif    
+}
+
+// -------------------------------------------------------------------------
+
+void
+Cyg_Scheduler_Implementation::timeslice_cpu(void)
+{
+#ifdef CYGDBG_KERNEL_TRACE_TIMESLICE
+    CYG_REPORT_FUNCTION();
+#endif
+
+    Cyg_Thread *thread = get_current_thread();
+    HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS();
+    
     CYG_ASSERT( queue_map != 0, "Run queue empty");
     CYG_ASSERT( queue_map & (1<<CYG_THREAD_MIN_PRIORITY), "Idle thread vanished!!!");
 
 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE_ENABLE
-    if( current_thread->timeslice_enabled && --timeslice_count == 0 )
+    if( thread->timeslice_enabled &&
+        timeslice_count[cpu_this] == 0 )
 #else    
-    if( --timeslice_count == 0 )
+    if( timeslice_count[cpu_this] == 0 )
 #endif
     {
         CYG_INSTRUMENT_SCHED(TIMESLICE,0,0);
@@ -272,9 +527,7 @@ Cyg_Scheduler_Implementation::timeslice(
         CYG_TRACE0( true, "quantum consumed, time to reschedule" );
 #endif
 
-        CYG_ASSERT( sched_lock > 0 , "Timeslice called with zero sched_lock");
-
-        Cyg_Thread *thread = current_thread;
+        CYG_ASSERT( get_sched_lock() > 0 , "Timeslice called with zero sched_lock");
 
         // Only try to rotate the run queue if the current thread is running.
         // Otherwise we are going to reschedule anyway.
@@ -282,18 +535,30 @@ Cyg_Scheduler_Implementation::timeslice(
         {
             Cyg_Scheduler *sched = &Cyg_Scheduler::scheduler;
 
+            CYG_INSTRUMENT_MLQ( TIMESLICE, thread, 0);
+                
             CYG_ASSERTCLASS( thread, "Bad current thread");
             CYG_ASSERTCLASS( sched, "Bad scheduler");
     
-            cyg_priority pri                               = thread->priority;
-            Cyg_SchedulerThreadQueue_Implementation *queue = &sched->run_queue[pri];
+            cyg_priority pri    = thread->priority;
+            Cyg_RunQueue *queue = &sched->run_queue[pri];
 
-            queue->rotate();
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
 
-            if( queue->highpri() != thread )
-                sched->need_reschedule = true;
+            // In SMP systems we set the head of the queue to point to
+            // the thread immediately after the current
+            // thread. schedule() will then pick that thread, or one
+            // after it to run next.
+            
+            queue->to_head( thread->get_next() );
+#else            
+            queue->rotate();
+#endif
+            
+            if( queue->get_head() != thread )
+                sched->set_need_reschedule();
 
-            timeslice_count = CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS;
+//            timeslice_count[cpu_this] = CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS;
         }
     }
 
@@ -305,6 +570,13 @@ Cyg_Scheduler_Implementation::timeslice(
 #endif
 }
 
+// -------------------------------------------------------------------------
+
+__externC void cyg_scheduler_timeslice_cpu(void)
+{
+    Cyg_Scheduler::scheduler.timeslice_cpu();
+}
+
 #endif
 
 //==========================================================================
@@ -325,6 +597,9 @@ Cyg_SchedThread_Implementation::Cyg_Sche
     // If timeslice_enabled exists, set it true by default
     timeslice_enabled = true;
 #endif
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
+    cpu = CYG_KERNEL_CPU_NONE;
+#endif
     
     CYG_REPORT_RETURN();
 }
@@ -352,19 +627,32 @@ Cyg_SchedThread_Implementation::yield(vo
         // To yield we simply rotate the appropriate
         // run queue to the next thread and reschedule.
 
+        CYG_INSTRUMENT_MLQ( YIELD, thread, 0);
+        
         CYG_ASSERTCLASS( thread, "Bad current thread");
     
         Cyg_Scheduler *sched = &Cyg_Scheduler::scheduler;
 
         CYG_ASSERTCLASS( sched, "Bad scheduler");
     
-        cyg_priority pri                               = thread->priority;
-        Cyg_SchedulerThreadQueue_Implementation *queue = &sched->run_queue[pri];
+        cyg_priority pri    = thread->priority;
+        Cyg_RunQueue *queue = &sched->run_queue[pri];
+
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
 
-        queue->rotate();
+            // In SMP systems we set the head of the queue to point to
+            // the thread immediately after the current
+            // thread. schedule() will then pick that thread, or one
+            // after it to run next.
+            
+            queue->to_head( thread->get_next() );
+#else            
+            queue->rotate();
+#endif
+        
+        if( queue->get_head() != thread )
+            sched->set_need_reschedule();
 
-        if( queue->highpri() != thread )
-            sched->need_reschedule = true;
 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
             // Reset the timeslice counter so that this thread gets a full
             // quantum. 
@@ -376,7 +664,7 @@ Cyg_SchedThread_Implementation::yield(vo
 #ifdef CYGDBG_USE_ASSERTS
     // This test keeps the assertions in unlock_inner() happy if
     // need_reschedule was not set above.
-    if( !Cyg_Scheduler::need_reschedule )
+    if( !Cyg_Scheduler::get_need_reschedule() )
         Cyg_Scheduler::unlock();
     else 
 #endif    
@@ -388,7 +676,7 @@ Cyg_SchedThread_Implementation::yield(vo
 
 // -------------------------------------------------------------------------
 // Rotate the run queue at a specified priority.
-// (pri is the decider, no this, so the routine is static)
+// (pri is the decider, not this, so the routine is static)
 
 void
 Cyg_SchedThread_Implementation::rotate_queue( cyg_priority pri )
@@ -403,11 +691,11 @@ Cyg_SchedThread_Implementation::rotate_q
 
     CYG_ASSERTCLASS( sched, "Bad scheduler");
     
-    Cyg_SchedulerThreadQueue_Implementation *queue = &sched->run_queue[pri];
+    Cyg_RunQueue *queue = &sched->run_queue[pri];
 
     if ( !queue->empty() ) {
         queue->rotate();
-        sched->need_reschedule = true;
+        sched->set_need_reschedule();
     }
 
     // Unlock the scheduler and switch threads
@@ -454,6 +742,8 @@ Cyg_ThreadQueue_Implementation::enqueue(
     CYG_REPORT_FUNCTION();
     CYG_REPORT_FUNCARG1("thread=%08x", thread);
 
+    CYG_INSTRUMENT_MLQ( ENQUEUE, this, thread );
+    
 #ifdef CYGIMP_KERNEL_SCHED_SORTED_QUEUES
 
     // Insert the thread into the queue in priority order.
@@ -537,6 +827,8 @@ Cyg_ThreadQueue_Implementation::dequeue(
     CYG_REPORT_FUNCTYPE("returning thread %08x");
         
     Cyg_Thread *thread = rem_head();
+
+    CYG_INSTRUMENT_MLQ( DEQUEUE, this, thread );
     
     if( thread != NULL )
         thread->queue = NULL;
@@ -553,6 +845,8 @@ Cyg_ThreadQueue_Implementation::remove( 
     CYG_REPORT_FUNCTION();
     CYG_REPORT_FUNCARG1("thread=%08x", thread);
 
+    CYG_INSTRUMENT_MLQ( REMOVE, this, thread );
+    
     thread->queue = NULL;
 
     Cyg_CList_T<Cyg_Thread>::remove( thread );
@@ -582,22 +876,6 @@ Cyg_ThreadQueue_Implementation::set_thre
 
 // -------------------------------------------------------------------------
 
-void
-Cyg_SchedulerThreadQueue_Implementation::enqueue(Cyg_Thread *thread)
-{
-    CYG_REPORT_FUNCTION();
-    CYG_REPORT_FUNCARG1("thread=%08x", thread);
-
-    add_tail( thread );
-    
-    set_thread_queue( thread, CYG_CLASSFROMBASE(Cyg_ThreadQueue,
-                                      Cyg_SchedulerThreadQueue_Implementation,
-                                                this));
-    CYG_REPORT_RETURN();
-}
-
-// -------------------------------------------------------------------------
-
 #endif
 
 // -------------------------------------------------------------------------
--- a/packages/kernel/current/src/sched/sched.cxx
+++ b/packages/kernel/current/src/sched/sched.cxx
@@ -80,15 +80,27 @@
 // We start with sched_lock at 1 so that any kernel code we
 // call during initialization will not try to reschedule.
 
-volatile cyg_ucount32 Cyg_Scheduler_Base::sched_lock = 1;
+CYGIMP_KERNEL_SCHED_LOCK_DEFINITIONS;
+
+Cyg_Thread              *volatile Cyg_Scheduler_Base::current_thread[CYGNUM_KERNEL_CPU_MAX];
 
-Cyg_Thread            *Cyg_Scheduler_Base::current_thread = NULL;
+volatile cyg_bool       Cyg_Scheduler_Base::need_reschedule[CYGNUM_KERNEL_CPU_MAX];
+
+Cyg_Scheduler           Cyg_Scheduler::scheduler CYG_INIT_PRIORITY( SCHEDULER );
+
+volatile cyg_ucount32   Cyg_Scheduler_Base::thread_switches[CYGNUM_KERNEL_CPU_MAX];
 
-cyg_bool              Cyg_Scheduler_Base::need_reschedule = false;
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
+
+CYG_BYTE cyg_sched_cpu_interrupt[CYGNUM_KERNEL_CPU_MAX][sizeof(Cyg_Interrupt)]
+                                 CYGBLD_ANNOTATE_VARIABLE_SCHED;
 
-Cyg_Scheduler         Cyg_Scheduler::scheduler CYG_INIT_PRIORITY( SCHEDULER );
+__externC cyg_ISR cyg_hal_cpu_message_isr;
+__externC cyg_DSR cyg_hal_cpu_message_dsr;
 
-cyg_ucount32          Cyg_Scheduler_Base::thread_switches = 0;
+inline void *operator new(size_t size, void *ptr) { return ptr; };
+
+#endif
 
 // -------------------------------------------------------------------------
 // Scheduler unlock function.
@@ -124,14 +136,14 @@ void Cyg_Scheduler::unlock_inner( cyg_uc
     // it fail if the current thread that was about to sleep is awoken by
     // the DSR!  Going round the loop to run new DSRs does the same.
     CYG_ASSERT( (new_lock == 0) ||
-                (current_thread->state != Cyg_Thread::RUNNING ||
-                 need_reschedule) ,
+                (get_current_thread()->state != Cyg_Thread::RUNNING ||
+                 get_need_reschedule()) ,
                 "Unnecessary call to unlock_inner()" );
         
     do {
 
-        CYG_PRECONDITION( new_lock==0 ? sched_lock == 1 :
-                          ((sched_lock == new_lock) || (sched_lock == new_lock+1)),
+        CYG_PRECONDITION( new_lock==0 ? get_sched_lock() == 1 :
+                          ((get_sched_lock() == new_lock) || (get_sched_lock() == new_lock+1)),
                           "sched_lock not at expected value" );
         
 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS
@@ -143,7 +155,7 @@ void Cyg_Scheduler::unlock_inner( cyg_uc
             Cyg_Interrupt::call_pending_DSRs();
 #endif
 
-        Cyg_Thread *current = current_thread;
+        Cyg_Thread *current = get_current_thread();
 
         CYG_ASSERTCLASS( current, "Bad current thread" );
 
@@ -154,7 +166,7 @@ void Cyg_Scheduler::unlock_inner( cyg_uc
             current->check_stack();
             current = current->get_list_next();
         }
-        current = current_thread;
+        current = get_current_thread();
 #endif
 
 #ifdef CYGFUN_KERNEL_THREADS_STACK_CHECKING
@@ -164,7 +176,7 @@ void Cyg_Scheduler::unlock_inner( cyg_uc
         // If the current thread is going to sleep, or someone
         // wants a reschedule, choose another thread to run
 
-        if( current->state != Cyg_Thread::RUNNING || need_reschedule ) {
+        if( current->state != Cyg_Thread::RUNNING || get_need_reschedule() ) {
 
             CYG_INSTRUMENT_SCHED(RESCHEDULE,0,0);
             
@@ -180,11 +192,12 @@ void Cyg_Scheduler::unlock_inner( cyg_uc
                 CYG_INSTRUMENT_THREAD(SWITCH,current,next);
 
                 // Count this thread switch
-                thread_switches++;
-                
+                thread_switches[CYG_KERNEL_CPU_THIS()]++;
+
 #ifdef CYGFUN_KERNEL_THREADS_STACK_CHECKING
                 next->check_stack(); // before running it
 #endif
+
                 // Switch contexts
                 HAL_THREAD_SWITCH_CONTEXT( &current->stack_ptr,
                                            &next->stack_ptr );
@@ -206,8 +219,7 @@ void Cyg_Scheduler::unlock_inner( cyg_uc
                 CYG_CHECK_DATA_PTR( current, "Invalid current thread pointer");
                 CYG_ASSERTCLASS( current, "Bad current thread" );
 
-                current_thread = current;   // restore current thread pointer
-
+                current_thread[CYG_KERNEL_CPU_THIS()] = current;   // restore current thread pointer
             }
 
 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
@@ -216,7 +228,7 @@ void Cyg_Scheduler::unlock_inner( cyg_uc
             reset_timeslice_count();
 #endif
 
-            need_reschedule = false;        // finished rescheduling
+            clear_need_reschedule();    // finished rescheduling
         }
 
         if( new_lock == 0 )
@@ -242,7 +254,7 @@ void Cyg_Scheduler::unlock_inner( cyg_uc
             
             HAL_REORDER_BARRIER(); // Make sure everything above has happened
                                    // by this point
-            sched_lock = 0;        // Clear the lock
+            zero_sched_lock();     // Clear the lock
             HAL_REORDER_BARRIER();
                 
 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS
@@ -254,14 +266,14 @@ void Cyg_Scheduler::unlock_inner( cyg_uc
             // not be run until the _next_ time we release the sched lock.
 
             if( Cyg_Interrupt::DSRs_pending() ) {
-                sched_lock = 1;     // reclaim the lock
+                inc_sched_lock();   // reclaim the lock
                 continue;           // go back to head of loop
             }
 
 #endif
             // Otherwise the lock is zero, we can return.
 
-            CYG_POSTCONDITION( sched_lock == 0, "sched_lock not zero" );
+//            CYG_POSTCONDITION( get_sched_lock() == 0, "sched_lock not zero" );
 
 #ifdef CYGSEM_KERNEL_SCHED_ASR_SUPPORT
             // If the test within the sched_lock indicating that the ASR
@@ -280,7 +292,7 @@ void Cyg_Scheduler::unlock_inner( cyg_uc
             
             HAL_REORDER_BARRIER();
             
-            sched_lock = new_lock;
+            set_sched_lock(new_lock);
             
             HAL_REORDER_BARRIER();            
         }
@@ -297,19 +309,66 @@ void Cyg_Scheduler::unlock_inner( cyg_uc
 
 // -------------------------------------------------------------------------
 // Start the scheduler. This is called after the initial threads have been
-// created to start scheduling.
+// created to start scheduling. It gets any other CPUs running, and then
+// enters the scheduler.
 
 void Cyg_Scheduler::start()
 {
     CYG_REPORT_FUNCTION();
-        
+
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
+
+    HAL_SMP_CPU_TYPE cpu;
+    
+    for( cpu = 0; cpu < CYG_KERNEL_CPU_COUNT(); cpu++ )
+    {
+        // Don't start this CPU, it is running already!
+        if( cpu == CYG_KERNEL_CPU_THIS() )
+            continue;
+
+        CYG_KERNEL_CPU_START( cpu );
+    }
+
+#endif    
+    
+    start_cpu();
+}
+
+// -------------------------------------------------------------------------
+// Start scheduling on this CPU. This is called on each CPU in the system
+// when it is started.
+
+void Cyg_Scheduler::start_cpu()
+{
+    CYG_REPORT_FUNCTION();
+
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
+
+    // Set up the inter-CPU interrupt for this CPU
+
+    Cyg_Interrupt * intr = new( (void *)&cyg_sched_cpu_interrupt[HAL_SMP_CPU_THIS()] )
+        Cyg_Interrupt( CYGNUM_HAL_SMP_CPU_INTERRUPT_VECTOR( HAL_SMP_CPU_THIS() ),
+                       0,
+                       0,
+                       cyg_hal_cpu_message_isr,
+                       cyg_hal_cpu_message_dsr
+                     );
+
+    intr->set_cpu( intr->get_vector(), HAL_SMP_CPU_THIS() );
+    
+    intr->attach();
+
+    intr->unmask_interrupt( intr->get_vector() );
+    
+#endif    
+    
     // Get the first thread to run from scheduler
     register Cyg_Thread *next = scheduler.schedule();
 
     CYG_ASSERTCLASS( next, "Bad initial thread" );
 
-    need_reschedule = false;    // finished rescheduling
-    current_thread = next;      // restore current thread pointer
+    clear_need_reschedule();            // finished rescheduling
+    set_current_thread(next);           // restore current thread pointer
 
 #ifdef CYGVAR_KERNEL_COUNTERS_CLOCK
     // Reference the real time clock. This ensures that at least one
@@ -318,14 +377,40 @@ void Cyg_Scheduler::start()
     CYG_REFERENCE_OBJECT( Cyg_Clock::real_time_clock );
 #endif
 
-    // Let the interrupts go
-    Cyg_Interrupt::enable_interrupts();
+    // Load the first thread. This will also enable interrupts since
+    // the initial state of all threads is to have interrupts enabled.
     
     HAL_THREAD_LOAD_CONTEXT( &next->stack_ptr );    
     
 }
 
 // -------------------------------------------------------------------------
+// SMP support functions
+
+#ifdef CYGPKG_KERNEL_SMP_SUPPORT
+
+// This is called on each secondary CPU on its interrupt stack after
+// the initial CPU has initialized the world.
+
+externC void cyg_kernel_smp_startup()
+{
+    CYG_INSTRUMENT_SMP( CPU_START, CYG_KERNEL_CPU_THIS(), 0 );
+    Cyg_Scheduler::lock();
+    Cyg_Scheduler::start_cpu();
+}
+
+// This is called from the DSR of the inter-CPU interrupt to cause a
+// reschedule when the scheduler lock is zeroed.
+
+__externC void cyg_scheduler_set_need_reschedule()
+{
+    CYG_INSTRUMENT_SMP( RESCHED_RECV, 0, 0 );    
+    Cyg_Scheduler::need_reschedule[HAL_SMP_CPU_THIS()] = true;
+}
+
+#endif
+
+// -------------------------------------------------------------------------
 // Consistency checker
 
 #ifdef CYGDBG_USE_ASSERTS
@@ -342,7 +427,7 @@ cyg_bool Cyg_Scheduler::check_this( cyg_
     case cyg_system_test:
     case cyg_extreme:
     case cyg_thorough:
-        if( !current_thread->check_this(zeal) ) return false;
+        if( !get_current_thread()->check_this(zeal) ) return false;
     case cyg_quick:
     case cyg_trivial:
     case cyg_none:
@@ -382,9 +467,6 @@ Cyg_SchedThread::Cyg_SchedThread(Cyg_Thr
     CYG_REPORT_FUNCTION();
         
     queue = NULL;
-    
-    if( Cyg_Scheduler::current_thread == NULL )
-        Cyg_Scheduler::current_thread = thread;
 
 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL
 
--- a/packages/kernel/current/src/sync/mutex.cxx
+++ b/packages/kernel/current/src/sync/mutex.cxx
@@ -467,6 +467,28 @@ void Cyg_Mutex::set_ceiling( cyg_priorit
 
 #endif
 
+// -------------------------------------------------------------------------
+// Set priority inversion protocol
+
+#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
+void Cyg_Mutex::set_protocol( cyg_protcol new_protocol )
+{
+    CYG_REPORT_FUNCTION();
+
+    // Prevent preemption
+    Cyg_Scheduler::lock();
+    
+    protocol = new_protocol;
+    
+    // Unlock the scheduler
+    Cyg_Scheduler::unlock();
+    
+    CYG_REPORT_RETURN();    
+}
+
+#endif
+
+
 //==========================================================================
 // Condition variables
 
--- a/packages/kernel/current/tests/mutex2.cxx
+++ b/packages/kernel/current/tests/mutex2.cxx
@@ -49,18 +49,27 @@
 #include <cyg/kernel/sched.inl>
 #include <cyg/kernel/thread.inl>
 
+// ------------------------------------------------------------------------
+
+#if !defined(CYGPKG_KERNEL_SMP_SUPPORT)
+
+// ------------------------------------------------------------------------
 
 #define NTHREADS 4
 #include "testaux.hxx"
 #include "testaux.h"
 
+// ------------------------------------------------------------------------
+
 static Cyg_Mutex m0, m1;
 static Cyg_Condition_Variable cvar0( m0 ), cvar1( m0 ), cvar2( m1 );
 
 volatile int thread_state[NTHREADS];
 
+// ------------------------------------------------------------------------
 // This thread is meant to get hung up trying to re-acquire m0
 // after waiting on the cv.
+
 static void entry0( CYG_ADDRWORD data )
 {
     CYG_TEST_INFO( "thread0: lock mutex 0");
@@ -88,7 +97,9 @@ static void entry0( CYG_ADDRWORD data )
     thread[data]->exit();
 }
 
+// ------------------------------------------------------------------------
 // This thread is meant to claim and keep m0.
+
 static void entry1( CYG_ADDRWORD data )
 {
     CYG_TEST_INFO( "thread1: lock mutex 0");
@@ -128,6 +139,7 @@ static void entry1( CYG_ADDRWORD data )
     thread[data]->exit();
 }
 
+// ------------------------------------------------------------------------
 // This thread is meant to get hung trying to acquire m0, and then get
 // released out of it by thread3.
 
@@ -155,6 +167,8 @@ static void entry2( CYG_ADDRWORD data )
     thread[data]->exit();    
 }
 
+// ------------------------------------------------------------------------
+
 static void entry3( CYG_ADDRWORD data )
 {
 
@@ -193,6 +207,8 @@ static void entry3( CYG_ADDRWORD data )
     thread[data]->exit();    
 }
 
+// ------------------------------------------------------------------------
+
 void mutex2_main( void )
 {
     CYG_TEST_INIT();
@@ -214,6 +230,8 @@ void mutex2_main( void )
     CYG_TEST_FAIL_FINISH("Not reached");
 }
 
+// ------------------------------------------------------------------------
+
 externC void
 cyg_start( void )
 { 
@@ -223,4 +241,24 @@ cyg_start( void )
     mutex2_main();
 }
 
+// ------------------------------------------------------------------------
+
+#else // CYGPKG_KERNEL_SMP_SUPPORT
+
+// ------------------------------------------------------------------------
+
+externC void
+cyg_start( void )
+{ 
+    CYG_TEST_INIT();
+    CYG_TEST_PASS_FINISH("Mutex2 test requires:\n"
+                         "!defined(CYGPKG_KERNEL_SMP_SUPPORT)\n");
+
+}
+
+// ------------------------------------------------------------------------
+
+#endif // CYGPKG_KERNEL_SMP_SUPPORT
+
+// ------------------------------------------------------------------------
 // EOF mutex2.cxx
--- a/packages/kernel/current/tests/mutex3.cxx
+++ b/packages/kernel/current/tests/mutex3.cxx
@@ -64,7 +64,8 @@ cyg_hal_invoke_constructors();
 // so the test should work correctly.
 
 #if defined(CYGVAR_KERNEL_COUNTERS_CLOCK) &&    \
-    (CYGNUM_KERNEL_SCHED_PRIORITIES > 20)
+    (CYGNUM_KERNEL_SCHED_PRIORITIES > 20) &&    \
+    !defined(CYGPKG_KERNEL_SMP_SUPPORT)
 
 // ------------------------------------------------------------------------
 // Manufacture a simpler feature test macro for priority inheritance than
@@ -426,7 +427,8 @@ cyg_start( void )
     CYG_TEST_INIT();
     CYG_TEST_PASS_FINISH("Mutex3 test requires:\n"
                          "CYGVAR_KERNEL_COUNTERS_CLOCK &&\n"
-                         "(CYGNUM_KERNEL_SCHED_PRIORITIES > 20)\n");
+                         "(CYGNUM_KERNEL_SCHED_PRIORITIES > 20) &&\n"
+                         "!defined(CYGPKG_KERNEL_SMP_SUPPORT)\n");
 }
 #endif // CYGVAR_KERNEL_COUNTERS_CLOCK &c
 
--- a/packages/kernel/current/tests/release.cxx
+++ b/packages/kernel/current/tests/release.cxx
@@ -77,6 +77,12 @@ static void entry0( CYG_ADDRWORD data )
 
 static void entry1( CYG_ADDRWORD data )
 {
+    Cyg_Thread *self = Cyg_Thread::self();    
+
+    // Give the other thread a chance to wait in SMP systems.
+    for( int i = 0; i < 100; i++ )
+        self->yield();
+    
     thread[0]->release();
 
     s1.wait();
new file mode 100644
--- /dev/null
+++ b/packages/kernel/current/tests/smp.cxx
@@ -0,0 +1,450 @@
+//==========================================================================
+//
+//        smp.cxx
+//
+//        SMP tests
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     nickg
+// Contributors:  nickg
+// Date:          2001-06-18
+// Description:   Some basic SMP tests.
+//
+//####DESCRIPTIONEND####
+//==========================================================================
+
+#include <pkgconf/kernel.h>
+#include <pkgconf/hal.h>
+
+#if 1
+#include <cyg/kernel/sched.hxx>
+#include <cyg/kernel/thread.hxx>
+#include <cyg/kernel/thread.inl>
+#include <cyg/kernel/mutex.hxx>
+#include <cyg/kernel/sema.hxx>
+#include <cyg/kernel/sched.inl>
+#include <cyg/kernel/clock.hxx>
+#include <cyg/kernel/clock.inl>
+#endif
+
+#include <cyg/kernel/kapi.h>
+
+#include <cyg/infra/testcase.h>
+#include <cyg/infra/diag.h>
+
+#define NTHREADS 1
+#include "testaux.hxx"
+
+//==========================================================================
+
+#if defined(CYGPKG_KERNEL_SMP_SUPPORT) &&       \
+    defined(CYGFUN_KERNEL_API_C) &&             \
+    defined(CYGSEM_KERNEL_SCHED_MLQUEUE) &&     \
+    defined(CYGVAR_KERNEL_COUNTERS_CLOCK) &&    \
+    !defined(CYGPKG_HAL_I386_LINUX) &&          \
+    !defined(CYGDBG_INFRA_DIAG_USE_DEVICE) &&   \
+    (CYGNUM_KERNEL_SCHED_PRIORITIES > 12)
+
+//==========================================================================
+
+#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
+
+#define NTHREADS_MAX (CYGNUM_KERNEL_CPU_MAX*3)
+
+static int ncpus = CYGNUM_KERNEL_CPU_MAX;
+static int nthread = NTHREADS_MAX;
+
+static char stacks[NTHREADS_MAX][STACK_SIZE];
+static cyg_thread test_threads[NTHREADS_MAX];
+static cyg_handle_t threads[NTHREADS_MAX];
+
+static volatile cyg_uint32 cpu_run[CYGNUM_KERNEL_CPU_MAX];
+static volatile int failed = false;
+static volatile cyg_handle_t cpu_thread[CYGNUM_KERNEL_CPU_MAX];
+
+static volatile cyg_uint32 slicerun[NTHREADS_MAX][CYGNUM_KERNEL_CPU_MAX];
+
+
+static cyg_mutex_t mx;
+
+
+//==========================================================================
+// Compute a name for a thread
+char *
+thread_name(char *basename, int indx) {
+    return "<<NULL>>";  // Not currently used
+}
+
+//==========================================================================
+
+void 
+test_thread_cpu(CYG_ADDRESS id)
+{
+    for(;;)
+        cpu_run[CYG_KERNEL_CPU_THIS()] = true;
+}
+
+//==========================================================================
+// First test: just run as many threads as CPUs and check that we
+// get to run on each CPU.
+
+void run_smp_test_cpus()
+{
+    int i;
+
+    CYG_TEST_INFO( "CPU Test: Check CPUs functional");
+    
+    // Init flags.
+    for (i = 0;  i < ncpus;  i++)
+        cpu_run[i] = false;
+    
+    // Set my priority higher than any I plan to create
+    cyg_thread_set_priority(cyg_thread_self(), 2);
+
+    for (i = 0;  i < ncpus;  i++) {
+        cyg_thread_create(10,              // Priority - just a number
+                          test_thread_cpu, // entry
+                          i,               // index
+                          thread_name("thread", i),     // Name
+                          &stacks[i][0],   // Stack
+                          STACK_SIZE,      // Size
+                          &threads[i],     // Handle
+                          &test_threads[i] // Thread data structure
+            );
+        cyg_thread_resume( threads[i]);
+    }
+
+    // Just wait a while, until the threads have all run for a bit.
+    cyg_thread_delay( 1 );
+
+    // Delete all the threads
+    for (i = 0;  i < ncpus;  i++) {
+        cyg_thread_delete(threads[i]);
+    }
+
+    // And check that a thread ran on each CPU
+    for (i = 0;  i < ncpus;  i++) {
+        CYG_TEST_CHECK( cpu_run[i], "CPU didn't run");
+        if( !cpu_run[i] )
+            failed++;
+    }
+
+    CYG_TEST_INFO( "CPU Test: done");
+}
+
+
+//==========================================================================
+
+void 
+test_thread_pri(CYG_ADDRESS id)
+{
+    for(;;)
+    {
+        cpu_thread[CYG_KERNEL_CPU_THIS()] = cyg_thread_self();
+    }
+}
+
+//==========================================================================
+// Second test: Run a thread on each CPU and then by manipulating the
+// priorities, get the current thread to migrate to each CPU in turn.
+
+void run_smp_test_pri()
+{
+    int i;
+
+    CYG_TEST_INFO( "Pri Test: Check set_priority functionality");
+    
+    // Init flags.
+    for (i = 0;  i < ncpus;  i++)
+        cpu_run[i] = false;
+    
+    // Set my priority higher than any I plan to creat
+    cyg_thread_set_priority(cyg_thread_self(), 2);
+
+    for (i = 0;  i < ncpus;  i++) {
+        cyg_thread_create(10,              // Priority - just a number
+                          test_thread_pri, // entry
+                          i,               // index
+                          thread_name("thread", i),     // Name
+                          &stacks[i][0],   // Stack
+                          STACK_SIZE,      // Size
+                          &threads[i],     // Handle
+                          &test_threads[i] // Thread data structure
+            );
+        cyg_thread_resume( threads[i]);
+    }
+
+    cyg_handle_t cthread = threads[0];
+    cyg_thread_set_priority(cthread, 25);
+    
+    // Just wait a while, until the threads have all run for a bit.
+    cyg_thread_delay( 1 );
+
+    for (i = 0;  i < ncpus*5;  i++)
+    {
+        HAL_SMP_CPU_TYPE cpu = i % CYG_KERNEL_CPU_COUNT();
+        
+        if( cpu != CYG_KERNEL_CPU_THIS() )
+        {
+            // At this point we have the current thread running on a
+            // CPU at priority 2, ncpus-1 threads running at priority
+            // 10 and the last thread (cthread) in the run queue at
+            // priority 25.
+            
+            // Pick a thread on a different CPU
+            cyg_handle_t dthread = cpu_thread[cpu];
+
+            // Change the priority of the victim thread to 20. It is
+            // still higher priority than cthread so it will continue
+            // running.
+            
+            cyg_thread_set_priority(dthread, 20);
+
+            // Now change our priority to 15. We are still higher
+            // priority that cthread so we will still run.
+            
+            cyg_thread_set_priority(cyg_thread_self(), 15);
+
+            // Finally change the priority of cthread to 10. This will
+            // cause it to preempt us on the current CPU. In turn we
+            // will preempt dthread on its CPU.
+
+            // NOTE: This relies somewhat on the SMP scheduler doing
+            // what we expect here. Specifically, that it will preempt
+            // the current thread with cthread locally. A more
+            // sophisticated scheduler might decide that the most
+            // efficient thing to do is to preempt dthread with
+            // cthread remotely, leaving the current thread where it
+            // is. If we ever bother to implement this, then this test
+            // will need to change.
+            
+            cyg_thread_set_priority(cthread, 10);
+
+            // Spin here a while until the scheduler sorts itself out.
+            
+            for( int j = 0; j < 1000; j++ );
+
+            // Indicate that we have run on this CPU
+            cpu_run[CYG_KERNEL_CPU_THIS()]++;
+
+            // Restore our priority to 2 and depress dthread to 25 and
+            // make it the new cthread.
+            
+            cyg_thread_set_priority(cyg_thread_self(), 2);
+            cyg_thread_set_priority(dthread, 25);
+            cthread = dthread;
+        }
+    }
+
+    
+    // Delete all the threads
+    for (i = 0;  i < ncpus;  i++) {
+        cyg_thread_delete(threads[i]);
+    }
+
+    // And check that a thread ran on each CPU
+    for (i = 0;  i < ncpus;  i++) {
+        CYG_TEST_CHECK( cpu_run[i], "CPU didn't run");
+        if( !cpu_run[i] )
+            failed++;
+    }
+
+    CYG_TEST_INFO( "PRI Test: done");
+}
+
+//==========================================================================
+
+void 
+test_thread_timeslice(CYG_ADDRESS id)
+{
+    for(;;)
+        slicerun[id][CYG_KERNEL_CPU_THIS()]++;
+}
+
+//==========================================================================
+// First test: just run as many threads as CPUs and check that we
+// get to run on each CPU.
+
+void run_smp_test_timeslice()
+{
+    int i;
+
+    CYG_TEST_INFO( "Timeslice Test: Check timeslicing works");
+    
+    // Init flags.
+    for (i = 0;  i < nthread;  i++)
+        for( int j = 0; j < ncpus; j++ )
+            slicerun[i][j] = 0;
+    
+    // Set my priority higher than any I plan to create
+    cyg_thread_set_priority(cyg_thread_self(), 2);
+
+    for (i = 0;  i < nthread;  i++) {
+        cyg_thread_create(10,              // Priority - just a number
+                          test_thread_timeslice, // entry
+                          i,               // index
+                          thread_name("thread", i),     // Name
+                          &stacks[i][0],   // Stack
+                          STACK_SIZE,      // Size
+                          &threads[i],     // Handle
+                          &test_threads[i] // Thread data structure
+            );
+        cyg_thread_resume( threads[i]);
+    }
+
+    // Just wait a while, until the threads have all run for a bit.
+    cyg_thread_delay( 20 );
+
+    // Delete all the threads
+    for (i = 0;  i < nthread;  i++) {
+        cyg_thread_suspend(threads[i]);
+    }
+
+    
+    // And check that a thread ran on each CPU
+
+    cyg_uint32 cpu_total[ncpus];
+    cyg_uint32 cpu_threads[ncpus];
+    cyg_uint32 thread_total[nthread];
+    
+    diag_printf(" Thread ");
+    for( int j = 0; j < ncpus; j++ )
+    {
+        cpu_total[j] = 0;
+        cpu_threads[j] = 0;
+        diag_printf("   CPU %2d",j);
+    }
+    diag_printf("   Total\n");
+    for (i = 0;  i < nthread;  i++)
+    {
+        thread_total[i] = 0;
+        diag_printf("     %2d ",i);
+        for( int j = 0; j < ncpus; j++ )
+        {
+            thread_total[i] += slicerun[i][j];
+            cpu_total[j] += slicerun[i][j];
+            if( slicerun[i][j] > 0 )
+                cpu_threads[j]++;
+            diag_printf(" %8d",slicerun[i][j]);
+        }
+        diag_printf("%8d\n",thread_total[i]);
+    }
+    diag_printf(" Total  ");
+    for( int j = 0; j < ncpus; j++ )
+        diag_printf(" %8d",cpu_total[j]);
+    diag_printf("\n");
+    diag_printf("Threads ");
+    for( int j = 0; j < ncpus; j++ )
+    {
+        diag_printf(" %8d",cpu_threads[j]);
+        if( cpu_threads[j] < 2 )
+            failed++;
+    }
+    diag_printf("\n");
+
+    // Delete all the threads
+    for (i = 0;  i < nthread;  i++) {
+        cyg_thread_delete(threads[i]);
+    }
+
+    CYG_TEST_INFO( "Timeslice Test: done");
+}
+
+
+//==========================================================================
+
+void 
+run_smp_tests(CYG_ADDRESS id)
+{
+    cyg_mutex_init( &mx );
+
+    for( int i = 0; i < 10; i++ )
+    {
+        run_smp_test_cpus();
+        run_smp_test_pri();
+        run_smp_test_timeslice();
+    }
+
+    if( failed )
+        CYG_TEST_FAIL_FINISH("SMP tests failed\n");
+    
+    CYG_TEST_PASS_FINISH("SMP tests OK");    
+}
+
+//==========================================================================
+
+void smp_main( void )
+{
+    CYG_TEST_INIT();
+
+    // Work out how many CPUs we actually have.
+    ncpus = CYG_KERNEL_CPU_COUNT();
+
+    new_thread(run_smp_tests, 0);
+
+    cyg_scheduler_start();
+}
+
+//==========================================================================
+
+#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
+externC void
+cyg_hal_invoke_constructors();
+#endif
+
+externC void
+cyg_start( void )
+{
+#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
+    cyg_hal_invoke_constructors();
+#endif
+    smp_main();
+}   
+
+//==========================================================================
+
+#else // CYGPKG_KERNEL_SMP_SUPPORT etc.
+
+externC void
+cyg_start( void )
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA("SMP test requires:\n"
+                "CYGPKG_KERNEL_SMP_SUPPORT &&\n"
+                "CYGFUN_KERNEL_API_C && \n"
+                "CYGSEM_KERNEL_SCHED_MLQUEUE &&\n"
+                "CYGVAR_KERNEL_COUNTERS_CLOCK &&\n"
+                "!CYGPKG_HAL_I386_LINUX &&\n"
+                "!CYGDBG_INFRA_DIAG_USE_DEVICE &&\n"
+                "(CYGNUM_KERNEL_SCHED_PRIORITIES > 12)\n");
+}
+#endif // CYGPKG_KERNEL_SMP_SUPPORT etc.
+
+//==========================================================================
+// EOF tm_basic.cxx
--- a/packages/kernel/current/tests/sync3.cxx
+++ b/packages/kernel/current/tests/sync3.cxx
@@ -64,9 +64,8 @@
 
 #include <cyg/kernel/sched.inl>
 
-#ifndef CYGIMP_THREAD_PRIORITY
-#error "Thread priorities disabled"
-#endif
+#if defined(CYGIMP_THREAD_PRIORITY) && \
+    !defined(CYGPKG_KERNEL_SMP_SUPPORT)
 
 // ------------------------------------------------------------------------
 // Manufacture a simpler feature test macro for priority inheritance than
@@ -205,5 +204,19 @@ cyg_start( void )
 #endif
     sync3_main();
 }
-   
+
+#else // defined(CYGIMP_THREAD_PRIORITY) etc
+
+externC void
+cyg_start( void )
+{ 
+    CYG_TEST_INIT();
+    CYG_TEST_PASS_FINISH("Sync3 test requires:\n"
+                         "defined(CYGIMP_THREAD_PRIORITY) &&\n"
+                         "!defined(CYGPKG_KERNEL_SMP_SUPPORT)\n");
+
+}
+
+#endif // defined(CYGIMP_THREAD_PRIORITY) etc
+
 // EOF sync3.cxx
--- a/packages/kernel/current/tests/thread2.cxx
+++ b/packages/kernel/current/tests/thread2.cxx
@@ -54,6 +54,7 @@
 //    CYGSEM_KERNEL_SCHED_BITMAP
 //    CYGSEM_KERNEL_SCHED_MLQUEUE
 //####DESCRIPTIONEND####
+//==========================================================================
 
 #include <pkgconf/kernel.h>
 
@@ -67,9 +68,12 @@
 
 #include <cyg/kernel/sched.inl>
 
-#ifndef CYGIMP_THREAD_PRIORITY
-#error "Test requires thread priorities"
-#endif
+// ------------------------------------------------------------------------
+
+#if defined(CYGIMP_THREAD_PRIORITY) && \
+    !defined(CYGPKG_KERNEL_SMP_SUPPORT)
+
+// ------------------------------------------------------------------------
 
 static Cyg_Counting_Semaphore s0, s1, s2;
 
@@ -80,6 +84,8 @@ static Cyg_Thread *thread0, *thread1, *t
 #define NTHREADS 3
 #include "testaux.hxx"
 
+// ------------------------------------------------------------------------
+
 static void entry0( CYG_ADDRWORD data )
 {
     CHECK(  0 == q++ );
@@ -92,6 +98,8 @@ static void entry0( CYG_ADDRWORD data )
     CYG_TEST_PASS_FINISH("Thread 2 OK");
 }
 
+// ------------------------------------------------------------------------
+
 static void entry1( CYG_ADDRWORD data )
 {
     CHECK(  1 == q++ );
@@ -124,6 +132,8 @@ static void entry1( CYG_ADDRWORD data )
     s1.wait();
 }
 
+// ------------------------------------------------------------------------
+
 static void entry2( CYG_ADDRWORD data )
 {
     CHECK(  2 == q++ );
@@ -153,6 +163,8 @@ static void entry2( CYG_ADDRWORD data )
 }
 
 
+// ------------------------------------------------------------------------
+
 void thread2_main( void )
 {
     CYG_TEST_INIT();
@@ -180,6 +192,8 @@ void thread2_main( void )
     CYG_TEST_FAIL_FINISH("Unresolved");
 }
 
+// ------------------------------------------------------------------------
+
 externC void
 cyg_start( void )
 {
@@ -188,5 +202,26 @@ cyg_start( void )
 #endif
     thread2_main();
 }
+// ------------------------------------------------------------------------
 
+
+#else // CYGPKG_KERNEL_SMP_SUPPORT etc
+
+// ------------------------------------------------------------------------
+
+externC void
+cyg_start( void )
+{ 
+    CYG_TEST_INIT();
+    CYG_TEST_PASS_FINISH("Thread2 test requires:\n"
+                         "defined(CYGIMP_THREAD_PRIORITY) &&\n"
+                         "!defined(CYGPKG_KERNEL_SMP_SUPPORT)\n");
+
+}
+
+// ------------------------------------------------------------------------
+
+#endif // CYGPKG_KERNEL_SMP_SUPPORT etc
+
+// ------------------------------------------------------------------------
 // EOF thread2.cxx
--- a/packages/kernel/current/tests/tm_basic.cxx
+++ b/packages/kernel/current/tests/tm_basic.cxx
@@ -400,7 +400,10 @@ thread_name(char *basename, int indx) {
 void
 test0(cyg_uint32 indx)
 {
+#ifndef CYGPKG_KERNEL_SMP_SUPPORT
+    // In SMP, somw of these threads will execute
     diag_printf("test0.%d executed?\n", indx);
+#endif    
     cyg_thread_exit();
 }
 
@@ -1531,11 +1534,13 @@ run_all_tests(CYG_ADDRESS id)
 
     disable_clock_latency_measurement();
 
+#ifndef CYGPKG_KERNEL_SMP_SUPPORT
     cyg_test_dump_thread_stack_stats( "Startup, main stack", thread[0] );
     cyg_test_dump_interrupt_stack_stats( "Startup" );
     cyg_test_dump_idlethread_stack_stats( "Startup" );
     cyg_test_clear_interrupt_stack();
-
+#endif
+    
     diag_printf("\neCos Kernel Timings\n");
     diag_printf("Notes: all times are in microseconds (.000001) unless otherwise stated\n");
 #ifdef STATS_WITHOUT_FIRST_SAMPLE
@@ -1546,6 +1551,7 @@ run_all_tests(CYG_ADDRESS id)
 
     ns_per_system_clock = 1000000/rtc_resolution[1];
 
+    wait_for_tick();
     for (i = 0;  i < nsamples;  i++) {
         HAL_CLOCK_READ(&tv[i]);
     }
@@ -1626,6 +1632,7 @@ run_all_tests(CYG_ADDRESS id)
     enable_clock_latency_measurement();
 #endif
 
+#ifndef CYGPKG_KERNEL_SMP_SUPPORT    
     disable_clock_latency_measurement();
     min_stack = STACK_SIZE;
     max_stack = 0;
@@ -1649,7 +1656,8 @@ run_all_tests(CYG_ADDRESS id)
     cyg_test_dump_thread_stack_stats( "All done, main stack", thread[0] );
     cyg_test_dump_interrupt_stack_stats( "All done" );
     cyg_test_dump_idlethread_stack_stats( "All done" );
-
+#endif
+    
     enable_clock_latency_measurement();
 
     ticks = cyg_current_time();
--- a/packages/language/c/libc/stdio/current/ChangeLog
+++ b/packages/language/c/libc/stdio/current/ChangeLog
@@ -1,3 +1,16 @@
+2001-08-10  Robin Farine  <robin.farine@terminus.org>
+
+        * src/output/vfnprintf.cxx (cvt): Handles the cases of finite,
+        NaN and infinite numbers separately.
+
+	* src/common/stream.cxx (read): Read correct number of bytes when
+	a character has been "ungot".
+
+2001-08-03  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* include/streambuf.inl (~Cyg_StdioStreamBuffer): use correct configury
+	to decide when to call free.
+
 2001-07-27  Jesper Skov  <jskov@redhat.com>
 
 	* src/common/fflush.cxx (cyg_libc_stdio_flush_all_but): The check
--- a/packages/language/c/libc/stdio/current/include/streambuf.inl
+++ b/packages/language/c/libc/stdio/current/include/streambuf.inl
@@ -90,7 +90,7 @@ Cyg_StdioStreamBuffer::Cyg_StdioStreamBu
 inline
 Cyg_StdioStreamBuffer::~Cyg_StdioStreamBuffer()
 {
-#ifdef CYGSEM_LIBC_STDIO_DYNAMIC_SETVBUF
+#ifdef CYGSEM_LIBC_STDIO_SETVBUF_MALLOC
     if ((buffer_bottom != NULL) && call_free)
         free( buffer_bottom );
 #endif        
--- a/packages/language/c/libc/stdio/current/src/common/stream.cxx
+++ b/packages/language/c/libc/stdio/current/src/common/stream.cxx
@@ -355,11 +355,13 @@ Cyg_StdioStream::read( cyg_uint8 *user_b
         bytes_available = io_buf.get_buffer_addr_to_read(
               (cyg_uint8 **)&buff_to_read_from );
         
-        *bytes_read += (bytes_available < buffer_length) ? bytes_available
-                                                         : buffer_length;
-        if (*bytes_read) {
-            memcpy( user_buffer, buff_to_read_from, *bytes_read );
-            io_buf.set_bytes_read( *bytes_read );
+        cyg_ucount32 count =
+            (bytes_available < buffer_length) ? bytes_available : buffer_length;
+
+        if (count) {
+            memcpy( user_buffer, buff_to_read_from, count );
+            io_buf.set_bytes_read( count );
+            *bytes_read += count;
         } // if
 
     } // if
--- a/packages/language/c/libc/stdio/current/src/output/vfnprintf.cxx
+++ b/packages/language/c/libc/stdio/current/src/output/vfnprintf.cxx
@@ -735,20 +735,23 @@ static int
 cvt(double number, int prec, int flags, char *signp, int fmtch, char *startp,
     char *endp)
 {
-        char *p, *t;
+    Cyg_libm_ieee_double_shape_type ieeefp;
+    char *t = startp;
+
+    ieeefp.value = number;
+    *signp = 0;
+    if ( ieeefp.number.sign ){  // this checks for <0.0 and -0.0
+        number = -number;
+        *signp = '-';
+    }
+
+    if (finite(number)) {
+        char *p;
         double fract;
         int dotrim, expcnt, gformat;
         double integer, tmp;
-        Cyg_libm_ieee_double_shape_type ieeefp;
 
         dotrim = expcnt = gformat = 0;
-        ieeefp.value = number;
-        if ( ieeefp.number.sign ){  // this checks for <0.0 and -0.0
-                number = -number;
-                *signp = '-';
-        } else
-                *signp = 0;
-
         fract = modf(number, &integer);
 
         /* get an extra slot for rounding. */
@@ -917,7 +920,28 @@ eformat:        if (expcnt) {
                                 ++t;
                 }
         }
-        return (t - startp);
+    } else {
+	unsigned case_adj;
+	switch (fmtch) {
+	case 'f':
+	case 'g':
+	case 'e':
+	    case_adj = 'a' - 'A';
+	    break;
+	default:
+	    case_adj = 0;
+	}
+	if (isnan(number)) {
+	    *t++ = 'N' + case_adj;
+	    *t++ = 'A' + case_adj;
+	    *t++ = 'N' + case_adj;
+	} else { // infinite
+	    *t++ = 'I' + case_adj;
+	    *t++ = 'N' + case_adj;
+	    *t++ = 'F' + case_adj;
+	}
+    }
+    return (t - startp);
 } // cvt()
 
 #endif // ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT
--- a/packages/language/c/libc/string/current/ChangeLog
+++ b/packages/language/c/libc/string/current/ChangeLog
@@ -1,3 +1,14 @@
+2001-08-10  Robin Farine  <acnrf@dial.eunet.ch>
+
+	* src/memchr.cxx (__memchr): Don't check string validity if number
+	of bytes to operate on is 0.
+	* src/memcmp.cxx (__memcmp): Ditto.
+	* src/memmove.cxx (__memmove): Ditto.
+	* src/strncat.cxx (__strncat): Ditto.
+	* src/strncmp.cxx (__strncmp): Ditto.
+	* src/strncpy.cxx (__strncpy): Ditto.
+	* src/strxfrm.cxx (__strxfrm): Ditto.
+
 2000-05-20  Jonathan Larmour  <jlarmour@redhat.co.uk>
 
 	* src/strtok.cxx: Remove aliases
--- a/packages/language/c/libc/string/current/src/memchr.cxx
+++ b/packages/language/c/libc/string/current/src/memchr.cxx
@@ -69,7 +69,10 @@ void *
     CYG_REPORT_FUNCNAMETYPE( "__memchr", "returning addr %08x" );
     CYG_REPORT_FUNCARG3( "s=%08x, c=%d, n=%d", s, c, n );
 
-    CYG_CHECK_DATA_PTR( s, "s is not a valid pointer!" );
+    if (n)
+    {
+        CYG_CHECK_DATA_PTR( s, "s is not a valid pointer!" );
+    }
 
 #if defined(CYGIMP_LIBC_STRING_PREFER_SMALL_TO_FAST) || defined(__OPTIMIZE_SIZE__)
     const unsigned char *src = (const unsigned char *) s;
--- a/packages/language/c/libc/string/current/src/memcmp.cxx
+++ b/packages/language/c/libc/string/current/src/memcmp.cxx
@@ -73,8 +73,11 @@ int
     CYG_REPORT_FUNCNAMETYPE( "__memcmp", "returning %d" );
     CYG_REPORT_FUNCARG3( "s1=%08x, s2=%08x, n=%d", s1, s2, n );
 
-    CYG_CHECK_DATA_PTR( s1, "s1 is not a valid pointer!" );
-    CYG_CHECK_DATA_PTR( s2, "s2 is not a valid pointer!" );
+    if (n)
+    {
+        CYG_CHECK_DATA_PTR( s1, "s1 is not a valid pointer!" );
+        CYG_CHECK_DATA_PTR( s2, "s2 is not a valid pointer!" );
+    }
 
 #if defined(CYGIMP_LIBC_STRING_PREFER_SMALL_TO_FAST) || defined(__OPTIMIZE_SIZE__)
     const unsigned char *m1 = (const unsigned char *) s1;
--- a/packages/language/c/libc/string/current/src/memmove.cxx
+++ b/packages/language/c/libc/string/current/src/memmove.cxx
@@ -73,8 +73,11 @@ void *
     CYG_REPORT_FUNCNAMETYPE( "__memmove", "returning %08x" );
     CYG_REPORT_FUNCARG3( "s1=%08x, s2=%08x, n=%d", s1, s2, n );
 
-    CYG_CHECK_DATA_PTR( s1, "s1 is not a valid pointer!" );
-    CYG_CHECK_DATA_PTR( s2, "s2 is not a valid pointer!" );
+    if (n)
+    {
+        CYG_CHECK_DATA_PTR( s1, "s1 is not a valid pointer!" );
+        CYG_CHECK_DATA_PTR( s2, "s2 is not a valid pointer!" );
+    }
 
     if ((src < dst) && (dst < (src + n)))
     {
--- a/packages/language/c/libc/string/current/src/strncat.cxx
+++ b/packages/language/c/libc/string/current/src/strncat.cxx
@@ -70,8 +70,11 @@ char *
     CYG_REPORT_FUNCNAMETYPE( "__strncat", "returning %08x" );
     CYG_REPORT_FUNCARG3( "s1=%08x, s2=%08x, n=%d", s1, s2, n );
 
-    CYG_CHECK_DATA_PTR( s1, "s1 is not a valid pointer!" );
-    CYG_CHECK_DATA_PTR( s2, "s2 is not a valid pointer!" );
+    if (n)
+    {
+        CYG_CHECK_DATA_PTR( s1, "s1 is not a valid pointer!" );
+        CYG_CHECK_DATA_PTR( s2, "s2 is not a valid pointer!" );
+    }
 
 #if defined(CYGIMP_LIBC_STRING_PREFER_SMALL_TO_FAST) || defined(__OPTIMIZE_SIZE__)
     char *s = s1;
--- a/packages/language/c/libc/string/current/src/strncmp.cxx
+++ b/packages/language/c/libc/string/current/src/strncmp.cxx
@@ -71,14 +71,17 @@ int
 
     CYG_REPORT_FUNCNAMETYPE( "__strncmp", "returning %d" );
     CYG_REPORT_FUNCARG3( "s1=%08x, s2=%08x, n=%d", s1, s2, n );
+    
+    if (n == 0)
+    {
+        CYG_REPORT_RETVAL( 0 );
+        return 0;
+    }
 
     CYG_CHECK_DATA_PTR( s1, "s1 is not a valid pointer!" );
     CYG_CHECK_DATA_PTR( s2, "s2 is not a valid pointer!" );
 
 #if defined(CYGIMP_LIBC_STRING_PREFER_SMALL_TO_FAST) || defined(__OPTIMIZE_SIZE__)
-    if (n == 0)
-        return 0;
-
     while (n-- != 0 && *s1 == *s2)
     {
         if (n == 0 || *s1 == '\0' || *s2 == '\0')
@@ -96,12 +99,6 @@ int
     const CYG_WORD *aligned_s1;
     const CYG_WORD *aligned_s2;
     
-    if (n == 0)
-    {
-        CYG_REPORT_RETVAL( 0 );
-        return 0;
-    } // if
-    
     // If s1 or s2 are unaligned, then compare bytes.
     if (CYG_LIBC_STR_UNALIGNED2 (s1, s2))
     {  
--- a/packages/language/c/libc/string/current/src/strncpy.cxx
+++ b/packages/language/c/libc/string/current/src/strncpy.cxx
@@ -70,8 +70,11 @@ char *
     CYG_REPORT_FUNCNAMETYPE( "__strncpy", "returning %08x" );
     CYG_REPORT_FUNCARG3( "s1=%08x, s2=%08x, n=%d", s1, s2, n );
 
-    CYG_CHECK_DATA_PTR( s1, "s1 is not a valid pointer!" );
-    CYG_CHECK_DATA_PTR( s2, "s2 is not a valid pointer!" );
+    if (n)
+    {
+        CYG_CHECK_DATA_PTR( s1, "s1 is not a valid pointer!" );
+        CYG_CHECK_DATA_PTR( s2, "s2 is not a valid pointer!" );
+    }
 
 #if defined(CYGIMP_LIBC_STRING_PREFER_SMALL_TO_FAST) || defined(__OPTIMIZE_SIZE__)
     char *dscan;
--- a/packages/language/c/libc/string/current/src/strxfrm.cxx
+++ b/packages/language/c/libc/string/current/src/strxfrm.cxx
@@ -72,8 +72,10 @@ size_t
     CYG_REPORT_FUNCNAMETYPE( "__strxfrm", "returning size %d" );
     CYG_REPORT_FUNCARG3( "s1=%08x, s2=%08x, n=%d", s1, s2, n );
 
-    if (s1 != NULL)
+    if (n)
+    {
         CYG_CHECK_DATA_PTR( s1, "s1 is not a valid pointer!" );
+    }
     CYG_CHECK_DATA_PTR( s2, "s2 is not a valid pointer!" );
 
     while (n-- > 0)
--- a/packages/redboot/current/ChangeLog
+++ b/packages/redboot/current/ChangeLog
@@ -1,3 +1,32 @@
+2001-08-10  Jesper Skov  <jskov@redhat.com>
+
+	* src/flash.c (do_flash_init): Print error message instead of
+	error code on init failure.
+	Don't print error codes where error messages are printed. Make
+	failure reporting strings look consistent.
+ 	CYGHWR_IO_FLASH_BLOCK_LOCKING flavor changed to booldata.
+
+2001-08-08  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* src/io.c (gets): Match $ as indicating GDB anywhere in a line.
+
+2001-08-07  Julian Smart <julians@redhat.com>
+
+	* src/version.c: added commented-out CYGDAT_REDBOOT_CUSTOM_VERSION
+	define that can be replaced using the RedBoot release script by
+	a specific version in a customer branch.
+
+2001-08-06  Jesper Skov  <jskov@redhat.com>
+
+	* src/fs/disk.c: Simple fix for DISK_IDE_CDROM partition type.
+
+	* cdl/redboot.cdl: Added (unused) CYGSEM_REDBOOT_DISK_ISO9660 option.
+
+2001-08-03  David Howells  <dhowells@redhat.com>
+
+	* src/net/net_io.c: Show the MAC address of the ethernet device
+	amongst the boot banners.
+
 2001-08-01  Mark Salter  <msalter@redhat.com>
 
 	* src/fs/ide.c (ide_reset): Check for bogus status and timeout. Add
--- a/packages/redboot/current/cdl/redboot.cdl
+++ b/packages/redboot/current/cdl/redboot.cdl
@@ -100,7 +100,7 @@ cdl_package CYGPKG_REDBOOT {
         compile main.c crc.c
         compile printf.c misc_funs.c io.c parse.c ticks.c xyzModem.c syscall.c
         compile decompress.c
-        compile -library=libextras.a load.c 
+        compile -library=libextras.a load.c
 
         make -priority 320 {
             <PREFIX>/bin/redboot.elf : $(PREFIX)/lib/target.ld $(PREFIX)/lib/vectors.o $(PREFIX)/lib/libtarget.a $(PREFIX)/lib/libextras.a
@@ -464,6 +464,15 @@ cdl_package CYGPKG_REDBOOT {
               When this option is enabled, RedBoot will support IDE disks."
 	    compile -library=libextras.a fs/e2fs.c
 	}
+
+        cdl_component CYGSEM_REDBOOT_DISK_ISO9660 {
+            display       "Support ISO9660 filesystems."
+            flavor        bool
+            calculated    0
+            description "
+              When this option is enabled, RedBoot will support ISO9660 filesystems."
+	    compile -library=libextras.a fs/iso9660fs.c
+	}
     }
 
     cdl_component CYGPKG_REDBOOT_BOOT_SCRIPT {
--- a/packages/redboot/current/src/flash.c
+++ b/packages/redboot/current/src/flash.c
@@ -115,7 +115,7 @@ local_cmd_entry("erase",
                 fis_erase,
                 FIS_cmds
     );
-#if 0 < CYGHWR_IO_FLASH_BLOCK_LOCKING // This is an *interface*
+#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
 local_cmd_entry("lock",
                 "LOCK FLASH contents",
                 "-f <flash_addr> -l <length>",
@@ -280,8 +280,8 @@ fis_init(int argc, char *argv[])
             erase_size -= erase_start;
             if ((stat = flash_erase((void *)erase_start, erase_size,
                                     (void **)&err_addr)) != 0) {
-                printf("   initialization failed %p: 0x%x(%s)\n",
-                       err_addr, stat, flash_errmsg(stat));
+                printf("   initialization failed at %p: %s\n",
+                       err_addr, flash_errmsg(stat));
             }
         }
         // second deal with the larger part in the main:
@@ -293,8 +293,8 @@ fis_init(int argc, char *argv[])
 #endif
         if ((stat = flash_erase((void *)erase_start, erase_size,
                                 (void **)&err_addr)) != 0) {
-            printf("   initialization failed %p: 0x%x(%s)\n",
-                   err_addr, stat, flash_errmsg(stat));
+            printf("   initialization failed at %p: %s\n",
+                   err_addr, flash_errmsg(stat));
         }
     } else {
         printf("    Warning: device contents not erased, some blocks may not be usable\n");
@@ -305,13 +305,13 @@ fis_init(int argc, char *argv[])
     flash_unlock((void *)fis_base, block_size, (void **)&err_addr);
 #endif
     if ((stat = flash_erase(fis_base, block_size, (void **)&err_addr)) != 0) {
-            printf("   initialization failed %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
+            printf("   initialization failed at %p: %s\n", err_addr, flash_errmsg(stat));
     } else {
         if ((stat = flash_program(fis_base, fis_work_block, 
                                   (unsigned long)img - (unsigned long)fis_work_block,
                                   (void **)&err_addr)) != 0) {
-            printf("Error writing image descriptors at %p: 0x%x(%s)\n", 
-                   err_addr, stat, flash_errmsg(stat));
+            printf("Error writing image descriptors at %p: %s\n", 
+                   err_addr, flash_errmsg(stat));
         }
     }
 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
@@ -533,7 +533,7 @@ fis_create(int argc, char *argv[])
     if (flash_addr_set &&
         ((stat = flash_verify_addr((void *)flash_addr)) ||
          (stat = flash_verify_addr((void *)(flash_addr+img_size-1))))) {
-        printf("Invalid FLASH address: %p (%s)\n", (void *)flash_addr, flash_errmsg(stat));
+        printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat));
         printf("   valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);
         return;
     }
@@ -608,14 +608,14 @@ fis_create(int argc, char *argv[])
         if (prog_ok) {
             // Erase area to be programmed
             if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
-                printf("Can't erase region at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
+                printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat));
                 prog_ok = false;
             }
         }
         if (prog_ok) {
             // Now program it
             if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, img_size, (void **)&err_addr)) != 0) {
-                printf("Can't program region at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
+                printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));
                 prog_ok = false;
             }
         }
@@ -636,12 +636,12 @@ fis_create(int argc, char *argv[])
     flash_unlock((void *)fis_addr, block_size, (void **)&err_addr);
 #endif
     if ((stat = flash_erase((void *)fis_addr, block_size, (void **)&err_addr)) != 0) {
-        printf("Error erasing at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
+        printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
         // Don't try to program if the erase failed
     } else {
         // Now program it
         if ((stat = flash_program((void *)fis_addr, (void *)fis_work_block, block_size, (void **)&err_addr)) != 0) {
-            printf("Error programming at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
+            printf("Error programming at %p: %s\n", err_addr, flash_errmsg(stat));
         }
     }
 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
@@ -706,7 +706,7 @@ fis_delete(int argc, char *argv[])
     }
     // Erase Data blocks (free space)
     if ((stat = flash_erase((void *)img->flash_base, img->size, (void **)&err_addr)) != 0) {
-        printf("Error erasing at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
+        printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
     }
 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
     // Insure [quietly] that the directory is unlocked before trying to update
@@ -715,12 +715,12 @@ fis_delete(int argc, char *argv[])
     // Update directory
     memset(img, 0xFF, sizeof(*img));
     if ((stat = flash_erase((void *)fis_addr, block_size, (void **)&err_addr)) != 0) {
-        printf("Error erasing at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
+        printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
         // Don't try to program if the erase failed
     } else {
         // Now program it
         if ((stat = flash_program((void *)fis_addr, (void *)fis_work_block, block_size, (void **)&err_addr)) != 0) {
-            printf("Error programming at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
+            printf("Error programming at %p: %s\n", err_addr, flash_errmsg(stat));
         }
     }
 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
@@ -858,7 +858,7 @@ fis_write(int argc, char *argv[])
     if (flash_addr_set &&
         ((stat = flash_verify_addr((void *)flash_addr)) ||
          (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
-        printf("Invalid FLASH address: %p (%s)\n", (void *)flash_addr, flash_errmsg(stat));
+        printf("Invalid FLASH address %p: (%s)\n", (void *)flash_addr, flash_errmsg(stat));
         printf("   valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);
         return;
     }
@@ -886,14 +886,14 @@ fis_write(int argc, char *argv[])
     if (prog_ok) {
         // Erase area to be programmed
         if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
-            printf("Can't erase region at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
+            printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat));
             prog_ok = false;
         }
     }
     if (prog_ok) {
         // Now program it
         if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, length, (void **)&err_addr)) != 0) {
-            printf("Can't program region at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
+            printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));
             prog_ok = false;
         }
     }
@@ -926,7 +926,7 @@ fis_erase(int argc, char *argv[])
     if (flash_addr_set &&
         ((stat = flash_verify_addr((void *)flash_addr)) ||
          (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
-        printf("Invalid FLASH address: %p (%s)\n", (void *)flash_addr, flash_errmsg(stat));
+        printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat));
         printf("   valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);
         return;
     }
@@ -941,11 +941,11 @@ fis_erase(int argc, char *argv[])
         return;
     }
     if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
-        printf("Error erasing at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
+        printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
     }
 }
 
-#if 0 < CYGHWR_IO_FLASH_BLOCK_LOCKING // This is an *interface*
+#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
 
 static void
 fis_lock(int argc, char *argv[])
@@ -974,12 +974,12 @@ fis_lock(int argc, char *argv[])
     if (flash_addr_set &&
         ((stat = flash_verify_addr((void *)flash_addr)) ||
          (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
-        printf("Invalid FLASH address: %p (%s)\n", (void *)flash_addr, flash_errmsg(stat));
+        printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat));
         printf("   valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);
         return;
     }
     if ((stat = flash_lock((void *)flash_addr, length, (void **)&err_addr)) != 0) {
-        printf("Error locking at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
+        printf("Error locking at %p: %s\n", err_addr, flash_errmsg(stat));
     }
 }
 
@@ -1010,12 +1010,12 @@ fis_unlock(int argc, char *argv[])
     if (flash_addr_set &&
         ((stat = flash_verify_addr((void *)flash_addr)) ||
          (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
-        printf("Invalid FLASH address: %p (%s)\n", (void *)flash_addr, flash_errmsg(stat));
+        printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat));
         printf("   valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);
         return;
     }
     if ((stat = flash_unlock((void *)flash_addr, length, (void **)&err_addr)) != 0) {
-        printf("Error unlocking at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
+        printf("Error unlocking at %p: %s\n", err_addr, flash_errmsg(stat));
     }
 }
 #endif
@@ -1039,7 +1039,7 @@ do_flash_init(void)
         __flash_init = 1;
         if ((stat = flash_init((void *)(workspace_end-FLASH_MIN_WORKSPACE), 
                                FLASH_MIN_WORKSPACE, printf)) != 0) {
-            printf("FLASH: driver init failed!, status: 0x%x\n", stat);
+            printf("FLASH: driver init failed: %s\n", flash_errmsg(stat));
             return false;
         }
         flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end);
@@ -1639,12 +1639,12 @@ flash_write_config(void)
         flash_unlock((void *)cfg_base, cfg_size, (void **)&err_addr);
 #endif
         if ((stat = flash_erase(cfg_base, cfg_size, (void **)&err_addr)) != 0) {
-            printf("   initialization failed %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
+            printf("   initialization failed at %p: %s\n", err_addr, flash_errmsg(stat));
         } else {
             if ((stat = flash_program(cfg_base, (void *)&config, 
                                       sizeof(config), (void **)&err_addr)) != 0) {
-                printf("Error writing config data at %p: 0x%x(%s)\n", 
-                       err_addr, stat, flash_errmsg(stat));
+                printf("Error writing config data at %p: %s\n", 
+                       err_addr, flash_errmsg(stat));
             }
         }
 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
--- a/packages/redboot/current/src/fs/disk.c
+++ b/packages/redboot/current/src/fs/disk.c
@@ -49,6 +49,9 @@
 #ifdef CYGSEM_REDBOOT_DISK_EXT2FS
 #include <fs/e2fs.h>
 #endif
+#ifdef CYGSEM_REDBOOT_DISK_ISO9660
+#include <fs/iso9660fs.h>
+#endif
 
 static void do_disks(int argc, char *argv[]);
 
@@ -168,6 +171,9 @@ find_partitions(disk_t *d)
 	p->disk = d;
 	p->start_sector = 0;
 	p->nr_sectors = d->nr_sectors;
+#ifdef CYGSEM_REDBOOT_DISK_ISO9660
+	p->funs = &redboot_iso9660fs_funs;
+#endif
 	return 1;
     }
 
@@ -183,13 +189,6 @@ find_partitions(disk_t *d)
 	// Might want to handle other MBR types, here...
     }
 
-#ifdef CYGSEM_REDBOOT_DISK_ISO9660
-    if (d->kind == DISK_IDE_CDROM) {
-	p->funs = &redboot_iso9660_funs;
-	return found;
-    }
-#endif
-
     // Now go through all partitions and install the correct
     // funcs for supported filesystems.
     for (i = 0, p = d->partitions; i < CYGNUM_REDBOOT_MAX_PARTITIONS; i++, p++) {
--- a/packages/redboot/current/src/io.c
+++ b/packages/redboot/current/src/io.c
@@ -306,13 +306,15 @@ gets(char *buf, int buflen, int timeout)
             break;
 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
         case '+':
+            // If start of line, treat as GDB protocol. Otherwise fall
+            // through to default.
+            if (ptr == buf)
         case '$':
-            if (ptr == buf) {
+            {
                 // Give up and try GDB protocol
                 ungetDebugChar(c);  // Push back character so stubs will see it
                 return _GETS_GDB;
             }
-            // Fall through - accept '$' at other than start of line
 #endif
         default:
             if (console_echo) {
--- a/packages/redboot/current/src/net/net_io.c
+++ b/packages/redboot/current/src/net/net_io.c
@@ -593,6 +593,15 @@ net_init(void)
         have_net = true;  // Assume values in FLASH were OK
     }
     if (have_net) {
+        printf("Ethernet %s: MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
+               __local_enet_sc->dev_name,
+               __local_enet_addr[0],
+               __local_enet_addr[1],
+               __local_enet_addr[2],
+               __local_enet_addr[3],
+               __local_enet_addr[4],
+               __local_enet_addr[5]);
+
         printf("IP: %s", inet_ntoa((in_addr_t *)&__local_ip_addr));
         printf(", Default server: %s\n", inet_ntoa(&my_bootp_info.bp_siaddr));
         net_io_init();
--- a/packages/redboot/current/src/version.c
+++ b/packages/redboot/current/src/version.c
@@ -59,6 +59,11 @@
 // outlined above.
 //
 
+// Please do not edit the line below by hand: it is changed by the RedBoot
+// release process. In a CVS branch, the line is commented out.
+// In a release, it is defined to be the RedBoot release number.
+//#define CYGDAT_REDBOOT_CUSTOM_VERSION current
+
 #if defined(CYGDAT_REDBOOT_CUSTOM_VERSION)
 #define _REDBOOT_VERSION CYGDAT_REDBOOT_CUSTOM_VERSION
 #elif defined(CYGPKG_REDBOOT_current)