Mercurial > ecos
changeset 177:4c750ce71ae3
Merge from eCos master repository on 2001-08-10-19:22:57-BST
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 "Help|Configuration -Tool Help" menu item, or from the internal help viewer's index, -under "Linux Configuration Tool Guide".</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 "Linux Configuration Tool Guide" in the -internal help system's contents. This is similar to but different -from "The eCos Configuration Tool" 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="HTML -document" \<BR>exts="htm,html"</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>> mkdir c:\wxWindows<BR>> c:<BR>> cd \wxWindows<BR>> - 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 "wxvc - WIN32 Debug" and "wxvc - WIN32 - Release". 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 *)(®s))[-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(ð_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( ¤t->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)
