summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/powerpc/mbx8xx
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2000-06-12 19:57:02 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2000-06-12 19:57:02 +0000
commit8ef38186faea3d9b5e6f0f1242f668cb7e7a3d52 (patch)
tree9253f150814c99167239f7c2cc850cdd9d92c003 /c/src/lib/libbsp/powerpc/mbx8xx
parentf481c39c015a71a6747d8e0f4f923fabe1086ffc (diff)
downloadrtems-8ef38186faea3d9b5e6f0f1242f668cb7e7a3d52.tar.bz2
Patch from John Cotton <john.cotton@nrc.ca>, Charles-Antoine Gauthier
<charles.gauthier@iit.nrc.ca>, and Darlene A. Stewart <Darlene.Stewart@nrc.ca> to add support for a number of very significant things: + BSPs for many variations on the Motorola MBX8xx board series + Cache Manager including initial support for m68040 and PowerPC + Rework of mpc8xx libcpu code so all mpc8xx CPUs now use same code base. + Rework of eth_comm BSP to utiltize above. John reports this works on the 821 and 860
Diffstat (limited to 'c/src/lib/libbsp/powerpc/mbx8xx')
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/Makefile.am17
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/README372
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/bsp_specs26
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/configure.in36
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/console/Makefile.am32
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/console/console.c484
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/include/Makefile.am23
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/include/bsp.h121
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/include/coverhd.h366
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/network/Makefile.am36
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/network/network.c1702
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/startup/Makefile.am42
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/startup/bspstart.c193
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/startup/bspstart.c.nocache202
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/startup/imbx8xx.c535
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/startup/linkcmds259
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/startup/mmutlbtab.c132
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/startup/setvec.c44
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/startup/start.S383
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/times-mbx821191
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/times-mbx860191
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/wrapup/Makefile.am40
22 files changed, 5427 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/Makefile.am b/c/src/lib/libbsp/powerpc/mbx8xx/Makefile.am
new file mode 100644
index 0000000000..fbbb0bf6c2
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/Makefile.am
@@ -0,0 +1,17 @@
+##
+## $Id$
+##
+
+AUTOMAKE_OPTIONS = foreign 1.4
+ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal
+
+# wrapup is the one that actually builds and installs the library
+# from the individual .rel files built in other directories
+SUBDIRS = console include network startup wrapup
+
+include $(top_srcdir)/../../bsp.am
+
+EXTRA_DIST = README bsp_specs times
+
+include $(top_srcdir)/../../../../../../automake/subdirs.am
+include $(top_srcdir)/../../../../../../automake/local.am
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/README b/c/src/lib/libbsp/powerpc/mbx8xx/README
new file mode 100644
index 0000000000..7a1c9fe5b2
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/README
@@ -0,0 +1,372 @@
+This is a README file for the MBX860/MBX821 port of RTEMS 4.5.0
+
+Please send any comments, improvements, or bug reports to:
+
+Darlene A. Stewart
+Software Engineering Group
+Institute for Information Technology
+National Research Council of Canada
+Ottawa, ON, K1A 0R6
+Canada
+
+Darlene.Stewart@nrc.ca
+
+
+
+Disclaimer
+----------
+
+The National Research Council of Canada is distributing this RTEMS
+board support package for the Motorola MBX860 and MBX821 as free
+software; you can redistribute it and/or modify it under terms of
+the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+This software is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details. You should have received a
+copy of the GNU General Public License along with RTEMS; see file
+COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+Under no circumstances will the National Research Council of Canada
+nor Her Majesty the Queen in right of Canada assume any liablility
+for the use this software, nor any responsibility for its quality or
+its support.
+
+
+Summary
+-------
+
+BSP NAME: mbx8xx
+BOARD: Motorola MBX860 and MBX821 Embedded Controllers
+BUS: No backplane. On-board ISA, PCI, PC/104 and PCMCIA.
+CPU FAMILY: PowerPC
+CPU: PowerPC MPC860 or MPC821
+COPROCESSORS: Built-in Motorola QUICC
+MODE: 32 bit mode
+
+DEBUG MONITOR: EPPC-Bug
+
+PERIPHERALS
+===========
+TIMERS: PIT / Timebase
+ RESOLUTION: 1 microsecond / frequency = clock-speed / 16
+SERIAL PORTS: 2 or 4 SCCs (SCC1 is hardwired for Ethernet)
+ 2 SMC
+ 1 SIO
+REAL-TIME CLOCK: Many. Look at documentation.
+DMA: Each SCC and SMC.
+VIDEO: None on-board. MPC821 has a built-in LCD panel driver.
+SCSI: None on-board.
+NETWORKING: Ethernet (10 Mbps) on SCC1
+
+
+DRIVER INFORMATION
+==================
+CLOCK DRIVER: yes
+CONSOLE DRIVER: yes
+SHMSUPP: N/A
+TIMER DRIVER: yes
+NETWORK DRIVER: yes
+
+NOTES
+=====
+On-chip resources:
+ SCC1 network or console
+ SCC2 serial port
+ SMC1 gdb debug console/application console
+ SMC2 application console
+ CLK1 network
+ CLK2 network
+ CLK3
+ CLK4
+ CLK5
+ CLK6
+ CLK7
+ CLK8
+ BRG1 console
+ BRG2 console
+ BRG3 console
+ BRG4 console
+ RTC
+ PIT clock
+ TB
+ DEC
+ SWT
+ *CS0 FLASH
+ *CS1 DRAM bank (onboard)
+ *CS2 DRAM bank 0 (1st half of DIMM)
+ *CS3 DRAM bank 1 (2nd half of DIMM)
+ *CS4 Battery-Backed SRAM
+ *CS5 QSPAN PCI
+ *CS6 QSPAN
+ *CS7 Boot ROM
+ UPMA
+ UPMB
+ IRQ0
+ IRQ1
+ IRQ2
+ IRQ3
+ IRQ4
+ IRQ5
+ IRQ6
+ IRQ7
+ IRQ_LVL0
+ IRQ_LVL1
+ IRQ_LVL2
+ IRQ_LVL3
+ IRQ_LVL4
+ IRQ_LVL5
+ IRQ_LVL6
+ IRQ_LVL7
+
+
+Board description
+-----------------
+Clock rate: 50MHz Entry level boards, 40 MHz others.
+Bus width: 8/32 bit Flash, 32 bit DRAM
+FLASH: 2-4MB, 120ns
+RAM: 4-16MB EDO, 60ns DRAM DIMM
+
+
+Installation
+------------
+
+All MBX821/MBX860 ports share the same source code base. The MPC821 does
+not have SCC3 and SCC4. Instead, it has an LCD panel driver. Otherwise,
+the MBX821 and MBX860 boards are essentially identical. Entry level boards
+do not have all connectors and peripheral devices present. This has no
+impact on the source code base; it merely means that some functionality
+is not available on these entry level boards. For the most part, the port
+uses the standard build process for powerpc targets. However, you must
+specify the EXACT model of MBX board that you are building for as the
+argument to the RTEMS_BSP make variable. If you do not, the build process
+will build for a MBX860-002. Look at rtems/make/custom/mbx8xx.cfg for the
+specific list of boards supported and their corresponding names. An
+example build command is:
+
+ make RTEMS_BSP=mbx821_001 all debug
+
+This will build the optimized and debug versions of all RTEMS libraries,
+samples and tests (if the latter are enabled).
+
+The Software Engineering Group of the Institute for Information Technology
+only owns an MBX821-001 and MBX86-002. The only provided config files are
+mbx821_001.cfg and mbx860_002.cfg. A SPECIFIC CONFIG FILE IS REQUIRED. Use
+one of the provided files as a template to create a specific config file for
+another model.
+
+We rely on EPPC-BUG to download to the targets. We use the 'PLH" command.
+We enabled a TFTP deamon on our development host.
+
+
+Port Description
+Console driver
+---------------
+
+This BSP includes an termios-capable console driver that supports SMC1,
+SMC2, SCC2, and SCC3 and SCC4 if present. The RTEMS console is selected
+in rtems/make/custom/mbx8xx.cfg with the CONSOLE_MINOR variable. We
+normally run with the RTEMS application console on SMC1.
+
+Support is provided for polled and interrupt-driven terminal I/O. Interrupt-
+driven I/O is selected by setting the UARTS_USE_INTERRUPTS variable in
+rtems/make/custom/mbx8xx.cfg. If the variable is not set, or if it is set
+to zero, polled I/O is used. If the EPPCBUG_SMC1 variable is set in
+rtems/make/custom/mbx8xx.cfg, SMC1 will be used in polled mode with all
+I/O done by EPPC-Bug rather than the supplied device driver. This mode
+should be used if the application console is shared with EPPC-Bug.
+
+Polled I/O must be used when running the timing tests. It must also be used
+to run some other tests and some samples, such as the cdtest. Applications
+would normally use interrupt-driven I/O.
+
+
+EPPC-Bug and I/O
+----------------
+
+Be warned that when EPPC-Bug does I/O through a serial port, all interrupts
+get turned off in the SIMASK register! This is a definite bug in release 1.1
+of the firmware. It may have been fixed in later releases.
+
+To solve this problem that occurs when GDB communicates with EPPC-Bug,
+whenever the BSP manipulates the SIMASK, it makes copy of the written
+in a global variable called 'simask_copy'. That value must be restored by
+GDB before execution resumes. The following commands placed in the .gdbinit
+file takes care of this:
+
+# GDB Initialization file for EPPCBug.
+
+define hook-stepi
+set language c
+set *(int *)0xFA200014=simask_copy
+set language auto
+end
+
+define hook-step
+set language c
+set *(int *)0xFA200014=simask_copy
+set language auto
+end
+
+define hook-continue
+set language c
+set *(int *)0xFA200014=simask_copy
+set language auto
+end
+
+define hook-nexti
+set language c
+set *(int *)0xFA200014=simask_copy
+set language auto
+end
+
+define hook-next
+set language c
+set *(int *)0xFA200014=simask_copy
+set language auto
+end
+
+define hook-finish
+set language c
+set *(int *)0xFA200014=simask_copy
+set language auto
+end
+
+
+Floating-point
+--------------
+
+The MPC860 and MPC821 do not have floating-point units. All code should
+get compiled with the appropriate -mcpu flag. The nof variants of the gcc
+runtime libraries should be used for linking.
+
+
+Miscellaneous
+-------------
+
+All development was based on the eth_comm port.
+
+
+Host System
+-----------
+
+12345678901234567890123456789012345678901234567890123456789012345678901234567890
+The port was developed on Pentiums II and III running RedHat Linux 6.0 and
+6.1. The following tools were used:
+
+ - GNU gcc snapshot dated 19991208 configured for powerpc-rtems;
+ - GNU binutils 2.9.1 configured for powerpc-rtems;
+
+Gcc 2.95.2 also worked. Gcc 2.95.1 will not compile the console driver with
+-O4 or -O3. Compile it manually with -O2.
+
+
+Known Problems
+--------------
+
+The cdtest will not run with interrupt-driven I/O. The reason is that the
+constructors for the static objects are called at boot time when the
+interrupts are still disabled. The output buffer fills up, but never empties,
+and the application goes into an infinite loop waiting for buffer space. This
+should have been documented in the rtems/c/src/tests/PROBLEMS file. The moral
+of this story is: do not do I/O from the constructors or destructors of static
+objects.
+
+The cpuuse and malloctest tests do not work properly, either with polled I/O
+or interrupt-driven I/O. They are known not to work with interrupt-driven I/O,
+but should work with polled I/O?
+
+Output stops prematurely in the termios test when the console is operating in
+interrupt-driven mode because the serial port is re-initialized before all
+characters in the last raw output buffer are sent. Adding calls to tcdrain()
+in the test task helps, but it does not solve the problem. What happens is
+that the CD2401 raises a transmit interrupt when the last character in the
+DMA buffer is written into the transmit FIFO, not when the last character
+has been transmitted. When tcdrain() returns, there might be up to 16
+characters in the output FIFO. The call to tcsetattr() causes the serial port
+to re-initialize, at which point the output FIFO is cleared. We could not find
+a way to detect whether characters are still in the FIFO and to wait for them
+to be transmitted.
+
+The first raw buffer to be transmitted after the console is re-initialized
+with tcsetattr() is garbled. At this time, it does not seem worth while to
+track this problem down.
+
+In the stackchk test, an access fault exception is raised after the stack is
+blown. This is one case were overwritting the first or last 16 bytes of the
+stack does cause problems (but hey, an exception occurred, which is better
+than propagating the error).
+
+In the stackchk test, an access fault exception is raised after the stack is
+blown. This is one case were overwritting the first or last 16 bytes of the
+stack does cause problems (but hey, an exception occurred, which is better
+than propagating the error).
+
+When using interrupt-driven I/O, psx08 produces all the expected output, but
+it does not return control to 167Bug. Is this test supposed to work with
+interrupt-driven console I/O?
+
+
+What's new
+----------
+
+All known problems with use of the caches on the MBX860-002 and MBX821-001
+have been resolved.
+
+
+Thanks
+------
+
+- to Jay Monkman (jmonkman@frasca.com) of Frasca International, Inc.
+ for his eth_comm port.
+
+- to On-Line Applications Research Corporation (OAR) for developing
+ RTEMS and making it available on a Technology Transfer basis;
+
+- to the FSF and to Cygnus Support for great free software;
+
+
+Test Configuration
+------------------
+
+Board: MBX821-001, MBX860-002
+CPU: Motorola MPC821, MPC860
+Clock Speed: 50 MHz, 40 MHz
+RAM: 4 MBytes of 32-bit DRAM
+Cache Configuration: Instruction cache on; data cache on, copyback mode.
+Times Reported in: clock ticks: TMBCLK = system clock / 16.
+Timer Source: Timebase clock
+GCC Flags: -O4 -fno-keep-inline-functions -mcpu=(821/860)
+Console: Operates in polled mode on SMC2. No I/O through EPPC-Bug.
+
+
+Test Results
+------------
+
+Single processor tests: All tests passed, except the following ones:
+
+ - paranoia required the FPSP and the default variants of libm (and libc and
+ libgcc) for us. It may work with the msoft-float variants for you, but it
+ does require the FPSP.
+
+ - cpuuse and malloctest did not work.
+
+ - The stackchk test got an access fault exception before the RTEMS stack
+ checker had had a chance to detect the corrupted stack.
+
+
+Multi-processort tests: not applicable -- No MPCI layer yet.
+
+
+Timing tests:
+ See the times-mbx821 and times-860 files for the results of the
+ timing tests.
+
+
+Network tests:
+ Network driver is being implemented.
+
+
+
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/bsp_specs b/c/src/lib/libbsp/powerpc/mbx8xx/bsp_specs
new file mode 100644
index 0000000000..8ec022948d
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/bsp_specs
@@ -0,0 +1,26 @@
+%rename cpp old_cpp
+%rename lib old_lib
+%rename endfile old_endfile
+%rename startfile old_startfile
+%rename link old_link
+
+*cpp:
+%(old_cpp) %{qrtems: -D__embedded__} -Asystem(embedded)
+
+*lib:
+%{!qrtems: %(old_lib)} %{qrtems: --start-group \
+%{!qrtems_debug: -lrtemsall} %{qrtems_debug: -lrtemsall_g} \
+%{qjava: -lffi -lgcjgc -lzgcj -lgcj} %{qc++: -lstdc++} -lc -lgcc --end-group \
+%{!qnolinkcmds: -T linkcmds%s}}
+
+*startfile:
+%{!qrtems: %(old_startfile)} %{qrtems: \
+%{!qrtems_debug: } \
+%{qrtems_debug: } ecrti%O%s}
+
+*endfile:
+%{!qrtems: %(old_endfile)} %{qrtems: ecrtn%O%s}
+
+*link:
+%{!qrtems: %(old_link)} %{qrtems: -dc -dp -u __vectors -N -u start -e start}
+
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/configure.in b/c/src/lib/libbsp/powerpc/mbx8xx/configure.in
new file mode 100644
index 0000000000..e87fa11590
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/configure.in
@@ -0,0 +1,36 @@
+dnl Process this file with autoconf to produce a configure script.
+dnl
+dnl $Id$
+
+AC_PREREQ(2.13)
+AC_INIT(bsp_specs)
+RTEMS_TOP(../../../../../..)
+AC_CONFIG_AUX_DIR(../../../../../..)
+
+RTEMS_CANONICAL_TARGET_CPU
+AM_INIT_AUTOMAKE(rtems-c-src-lib-libbsp-powerpc-mbx8xx,$RTEMS_VERSION,no)
+AM_MAINTAINER_MODE
+
+RTEMS_ENABLE_LIBCDIR
+RTEMS_ENABLE_MULTIPROCESSING
+RTEMS_ENABLE_NETWORKING
+
+RTEMS_ENV_RTEMSBSP
+RTEMS_CHECK_CUSTOM_BSP(RTEMS_BSP)
+RTEMS_CHECK_BSP_CACHE(RTEMS_BSP)
+RTEMS_CHECK_MULTIPROCESSING(RTEMS_BSP)
+RTEMS_CHECK_NETWORKING
+RTEMS_CANONICAL_HOST
+
+RTEMS_PROJECT_ROOT
+AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes")
+AM_CONDITIONAL(HAS_MP,test "$HAS_MP" = "yes")
+
+# Explicitly list a Makefile here
+AC_OUTPUT(
+Makefile
+console/Makefile
+include/Makefile
+network/Makefile
+startup/Makefile
+wrapup/Makefile)
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/console/Makefile.am b/c/src/lib/libbsp/powerpc/mbx8xx/console/Makefile.am
new file mode 100644
index 0000000000..82b58ef82e
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/console/Makefile.am
@@ -0,0 +1,32 @@
+##
+## $Id$
+##
+
+AUTOMAKE_OPTIONS = foreign 1.4
+
+PGM = $(ARCH)/console.rel
+
+C_FILES = console.c
+C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o)
+
+OBJS = $(C_O_FILES)
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../../../../../../automake/lib.am
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+$(PGM): $(OBJS)
+ $(make-rel)
+
+# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
+
+all-local: $(ARCH) $(OBJS) $(PGM)
+
+.PRECIOUS: $(PGM)
+
+EXTRA_DIST = console.c
+
+include $(top_srcdir)/../../../../../../automake/local.am
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/console/console.c b/c/src/lib/libbsp/powerpc/mbx8xx/console/console.c
new file mode 100644
index 0000000000..c152d17321
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/console/console.c
@@ -0,0 +1,484 @@
+/*
+ * console.c
+ *
+ * This file contains the MBX8xx termios serial I/O package.
+ * Only asynchronous I/O is supported.
+ *
+ * The SCCs and SMCs are assigned as follows
+ *
+ * Channel Device Minor Note
+ * SMC1 /dev/tty0 0
+ * SMC2 /dev/tty1 1
+ * SCC1 2 N/A. Hardwired as ethernet port
+ * SCC2 /dev/tty2 3
+ * SCC3 /dev/tty3 4
+ * SCC4 /dev/tty4 5
+ *
+ * All ports support termios. All I/O is interrupt-driven, unless EPPCBug
+ * is used to do the I/O. To use EPPCBug, define the EPPCBUG_SMC1
+ * manifest constant in the configuration file (mbx8xx.cfg). EPPCBug I/O
+ * is currently limited to the EPPCBug debug console. This is a limitation
+ * of firmware revision 1.1. Later firmware should be able to do I/O
+ * through any port.This code assumes that the EPPCBug console is the
+ * default: SMC1.
+ *
+ * TO RUN THE TESTS, USE POLLED I/O THROUGH EPPCBUG. Some tests play with
+ * the interrupt masks and turn off I/O. Those tests will hang with when
+ * interrupt-driven I/O is used.
+ *
+ * Set CONSOLE_MINOR to the appropriate device minor number in the
+ * config file. This allows the RTEMS application console to be different
+ * from the EPPBug debug console or the GDB stup I/O port.
+ *
+ * This driver handles all five available serial ports: it distinguishes
+ * the sub-devices using minor device numbers. It is not possible to have
+ * other protocols running on the other ports when this driver is used as
+ * currently written.
+ *
+ * Based on code (alloc860.c in eth_comm port) by
+ * Jay Monkman (jmonkman@frasca.com),
+ * Copyright (C) 1998 by Frasca International, Inc.
+ *
+ * Modifications by Darlene Stewart <Darlene.Stewart@iit.nrc.ca>
+ * and Charles-Antoine Gauthier <charles.gauthier@iit.nrc.ca>.
+ * Copyright (c) 1999, National Research Council of Canada
+ *
+ */
+#include <stdarg.h>
+#include <stdio.h>
+#include <bsp.h> /* Must be before libio.h */
+#include <rtems/libio.h>
+#include <termios.h>
+
+static int _EPPCBug_pollRead( int minor );
+static int _EPPCBug_pollWrite( int minor, const char *buf, int len );
+
+
+/*
+ * _EPPCBug_pollRead
+ *
+ * Read a character from the EPPCBug console, and return it. Return -1
+ * if there is no character in the input FIFO.
+ *
+ * Input parameters:
+ * minor - selected channel
+ *
+ * Output parameters: NONE
+ *
+ * Return value: char returned as positive signed int
+ * -1 if no character is present in the input FIFO.
+ */
+int _EPPCBug_pollRead(
+ int minor
+)
+{
+ extern volatile m8xx_t m8xx;
+
+ char c;
+ volatile int simask; /* We must read and write m8xx.simask */
+ int retval;
+ ISR_Level level;
+
+ struct {
+ int clun;
+ int dlun;
+ char * inbuf;
+ int nbytes_requested;
+ int reserved;
+ } volatile input_params;
+
+ struct {
+ int status;
+ union {
+ struct {
+ int input_char_available;
+ int output_possible;
+ int break_detected;
+ int modem_status;
+ } stat;
+ struct {
+ int nbytes_received;
+ } read;
+ } u;
+ } volatile output_params;
+
+ retval = -1;
+
+ /* Input through EPPCBug console */
+ input_params.clun = 0;
+ input_params.dlun = 0;
+ input_params.reserved = 0;
+
+ _ISR_Disable( level );
+ simask = m8xx.simask;
+
+ /* Check for a char in the input FIFO using .CIO_STAT */
+ asm volatile( "li 10,0x202
+ mr 3, %0
+ mr 4, %1
+ sc"
+ :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" );
+
+ if ( (output_params.status == 0) && output_params.u.stat.input_char_available) {
+
+ /* Read the char and return it */
+ input_params.inbuf = &c;
+ input_params.nbytes_requested = 1;
+
+ asm volatile( "li 10,0x200 /* Code for .CIO_READ */
+ mr 3, %0 /* Address of input_params */
+ mr 4, %1 /* Address of output_params */
+ sc" /* Call EPPCBUG */
+ :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" );
+
+ if ( (output_params.status == 0) && output_params.u.read.nbytes_received)
+ retval = (int)c;
+ }
+
+ m8xx.simask = simask;
+ _ISR_Enable( level );
+ return retval;
+}
+
+
+/*
+ * _EPPCBug_pollWrite
+ *
+ * Output buffer through EPPCBug. Returns only once every character has been
+ * sent (polled output).
+ *
+ * Input parameters:
+ * minor - selected channel
+ * buf - output buffer
+ * len - number of chars to output
+ *
+ * Output parameters: NONE
+ *
+ * Return value: IGNORED
+ */
+int _EPPCBug_pollWrite(
+ int minor,
+ const char *buf,
+ int len
+)
+{
+ extern volatile m8xx_t m8xx;
+
+ volatile int simask;
+ int i, retval;
+ ISR_Level level;
+
+ struct {
+ int clun;
+ int dlun;
+ const char * outbuf;
+ int nbytes_to_output;
+ int reserved;
+ } volatile input_params;
+
+ struct {
+ int status;
+ union {
+ struct {
+ int input_char_available;
+ int output_possible;
+ int break_detected;
+ int modem_status;
+ } stat;
+ struct {
+ int nbytes_sent;
+ } write;
+ } u;
+ } volatile output_params;
+
+ retval = -1;
+
+ /* Output through EPPCBug console */
+ input_params.clun = 0;
+ input_params.dlun = 0;
+ input_params.reserved = 0;
+
+ i = 0;
+
+ _ISR_Disable( level );
+ simask = m8xx.simask;
+
+ while (i < len) {
+ /* Wait for space in the output buffer */
+ do {
+ /* Check for space in the output FIFO */
+ asm volatile( "li 10,0x202 /* Code for .CIO_STAT */
+ mr 3, %0 /* Address of input_params */
+ mr 4, %1 /* Address of output_params */
+ sc" /* Call EPPCBUG */
+ :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" );
+
+ if (output_params.status)
+ goto error;
+ } while (!output_params.u.stat.output_possible);
+
+ /* Output the characters until done */
+ input_params.outbuf = &buf[i];
+ input_params.nbytes_to_output = len - i;
+
+ asm volatile( "li 10,0x201 /* Code for .CIO_WRITE */
+ mr 3, %0 /* Address of input_params */
+ mr 4, %1 /* Address of output_params */
+ sc" /* Call EPPCBUG */
+ :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" );
+
+ if (output_params.status)
+ goto error;
+
+ i += output_params.u.write.nbytes_sent;
+ }
+
+ /* Return something */
+ m8xx.simask = simask;
+ _ISR_Enable( level );
+ return RTEMS_SUCCESSFUL;
+
+error:
+ m8xx.simask = simask;
+ _ISR_Enable( level );
+ return -1;
+}
+
+
+/*
+ * Print functions: prototyped in bsp.h
+ * Debug printing on Channel 1
+ */
+
+void printk( char *fmt, ... )
+{
+ va_list ap; /* points to each unnamed argument in turn */
+ static char buf[256];
+ unsigned int level;
+
+ _CPU_ISR_Disable(level);
+
+ va_start(ap, fmt); /* make ap point to 1st unnamed arg */
+ vsprintf(buf, fmt, ap); /* send output to buffer */
+
+ BSP_output_string(buf); /* print buffer -- Channel 1 */
+
+ va_end(ap); /* clean up and re-enable interrupts */
+ _CPU_ISR_Enable(level);
+}
+
+
+void BSP_output_string( char * buf )
+{
+ int len = strlen(buf);
+ int minor; /* will be ignored */
+ rtems_status_code sc;
+
+ sc = _EPPCBug_pollWrite(minor, buf, len);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+}
+
+
+/*
+ ***************
+ * BOILERPLATE *
+ ***************
+ *
+ * All these functions are prototyped in rtems/c/src/lib/include/console.h.
+ */
+
+/*
+ * Initialize and register the device
+ */
+rtems_device_driver console_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ rtems_status_code status;
+
+ /*
+ * Set up TERMIOS
+ */
+ rtems_termios_initialize();
+
+ /*
+ * Do common initialization.
+ */
+ m8xx_uart_initialize();
+
+ /*
+ * Do device-specific initialization
+ */
+#ifndef EPPCBUG_SMC1
+ m8xx_uart_smc_initialize(SMC1_MINOR); /* /dev/tty0 */
+#endif /* EPPCBUG_SMC1 */
+
+ m8xx_uart_smc_initialize(SMC2_MINOR); /* /dev/tty1 */
+ m8xx_uart_scc_initialize(SCC2_MINOR); /* /dev/tty2 */
+
+#ifdef mpc860
+ m8xx_uart_scc_initialize(SCC3_MINOR); /* /dev/tty3 */
+ m8xx_uart_scc_initialize(SCC4_MINOR); /* /dev/tty4 */
+#endif /* mpc860 */
+
+ /*
+ * Set up interrupts
+ */
+ m8xx_uart_interrupts_initialize();
+
+ status = rtems_io_register_name ("/dev/tty0", major, SMC1_MINOR);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (status);
+
+ status = rtems_io_register_name ("/dev/tty1", major, SMC2_MINOR);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (status);
+
+ status = rtems_io_register_name ("/dev/tty2", major, SCC2_MINOR);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (status);
+
+#ifdef mpc860
+ status = rtems_io_register_name ("/dev/tty3", major, SCC3_MINOR);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (status);
+
+ status = rtems_io_register_name ("/dev/tty4", major, SCC4_MINOR);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (status);
+
+#endif /* mpc860 */
+
+ /* Now register the RTEMS console */
+ status = rtems_io_register_name ("/dev/console", major, CONSOLE_MINOR);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (status);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * Open the device
+ */
+rtems_device_driver console_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ /* Used to track termios private data for callbacks */
+ extern struct rtems_termios_tty *ttyp[];
+
+ volatile m8xxSCCRegisters_t *sccregs;
+ rtems_status_code sc;
+ rtems_libio_open_close_args_t *args = arg;
+
+#ifdef EPPCBUG_SMC1
+ static const rtems_termios_callbacks sccEPPCBugCallbacks = {
+ NULL, /* firstOpen */
+ NULL, /* lastClose */
+ _EPPCBug_pollRead, /* pollRead */
+ _EPPCBug_pollWrite, /* write */
+ NULL, /* stopRemoteTx */
+ NULL, /* startRemoteTx */
+ 0 /* outputUsesInterrupts */
+ };
+#endif
+
+#ifdef UARTS_USE_INTERRUPTS
+ static const rtems_termios_callbacks intrCallbacks = {
+ NULL, /* firstOpen */
+ NULL, /* lastClose */
+ NULL, /* pollRead */
+ m8xx_uart_write, /* write */
+ m8xx_uart_setAttributes, /* setAttributes */
+ NULL, /* stopRemoteTx */
+ NULL, /* startRemoteTx */
+ 1 /* outputUsesInterrupts */
+ };
+#else
+ static const rtems_termios_callbacks pollCallbacks = {
+ NULL, /* firstOpen */
+ NULL, /* lastClose */
+ m8xx_uart_pollRead, /* pollRead */
+ m8xx_uart_pollWrite, /* write */
+ m8xx_uart_setAttributes, /* setAttributes */
+ NULL, /* stopRemoteTx */
+ NULL, /* startRemoteTx */
+ 0 /* outputUsesInterrupts */
+ };
+#endif
+
+ if ( (minor < SMC1_MINOR) || (minor > NUM_PORTS-1) )
+ return RTEMS_INVALID_NUMBER;
+
+#ifdef EPPCBUG_SMC1
+ if (minor == SMC1_MINOR)
+ return rtems_termios_open (major, minor, arg, &sccEPPCBugCallbacks);
+#endif /* EPPCBUG_SMC1 */
+
+#ifdef UARTS_USE_INTERRUPTS
+ sc = rtems_termios_open (major, minor, arg, &intrCallbacks);
+ ttyp[minor] = args->iop->data1; /* Keep cookie returned by termios_open */
+#else
+ sc = rtems_termios_open (major, minor, arg, &pollCallbacks);
+#endif
+ return sc;
+}
+
+
+/*
+ * Close the device
+ */
+rtems_device_driver console_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ return rtems_termios_close (arg);
+}
+
+
+/*
+ * Read from the device
+ */
+rtems_device_driver console_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ return rtems_termios_read(arg);
+}
+
+
+/*
+ * Write to the device
+ */
+rtems_device_driver console_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ return rtems_termios_write(arg);
+}
+
+
+/*
+ * Handle ioctl request.
+ */
+rtems_device_driver console_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ return rtems_termios_ioctl (arg);
+}
+
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/include/Makefile.am b/c/src/lib/libbsp/powerpc/mbx8xx/include/Makefile.am
new file mode 100644
index 0000000000..ac0bb3566f
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/include/Makefile.am
@@ -0,0 +1,23 @@
+##
+## $Id$
+##
+
+AUTOMAKE_OPTIONS = foreign 1.4
+
+H_FILES = bsp.h coverhd.h
+
+$(PROJECT_INCLUDE):
+ $(mkinstalldirs) $@
+
+$(PROJECT_INCLUDE)/bsp.h: bsp.h
+ $(INSTALL_DATA) $< $@
+
+$(PROJECT_INCLUDE)/coverhd.h: coverhd.h
+ $(INSTALL_DATA) $< $@
+
+PREINSTALL_FILES += $(PROJECT_INCLUDE) $(PROJECT_INCLUDE)/bsp.h \
+ $(PROJECT_INCLUDE)/coverhd.h
+
+all-local: $(PREINSTALL_FILES)
+
+include $(top_srcdir)/../../../../../../automake/local.am
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/include/bsp.h b/c/src/lib/libbsp/powerpc/mbx8xx/include/bsp.h
new file mode 100644
index 0000000000..df5d911fb0
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/include/bsp.h
@@ -0,0 +1,121 @@
+/* bsp.h
+ *
+ * This include file contains all board IO definitions.
+ *
+ * This file includes definitions for the MBX860 and MBX821.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#ifndef __MBX8xx_h
+#define __MBX8xx_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <console.h>
+#include <clockdrv.h>
+#include <mpc8xx.h>
+#include <mpc8xx/cpm.h>
+#include <mpc8xx/mmu.h>
+#include <mpc8xx/console.h>
+
+/*
+ * Network driver configuration
+ */
+struct rtems_bsdnet_ifconfig;
+extern int rtems_enet_driver_attach (struct rtems_bsdnet_ifconfig *config);
+#define RTEMS_BSP_NETWORK_DRIVER_NAME "scc1"
+#define RTEMS_BSP_NETWORK_DRIVER_ATTACH rtems_enet_driver_attach
+
+/*
+ * We need to decide how much memory will be non-cacheable. This
+ * will mainly be memory that will be used in DMA (network and serial
+ * buffers).
+ */
+#define NOCACHE_MEM_SIZE 512*1024
+
+/*
+ * Define the time limits for RTEMS Test Suite test durations.
+ * Long test and short test duration limits are provided. These
+ * values are in seconds and need to be converted to ticks for the
+ * application.
+ *
+ */
+
+#define MAX_LONG_TEST_DURATION 300 /* 5 minutes = 300 seconds */
+#define MAX_SHORT_TEST_DURATION 3 /* 3 seconds */
+
+/*
+ * Stuff for Time Test 27
+ */
+
+#define MUST_WAIT_FOR_INTERRUPT 0
+
+#define Install_tm27_vector( handler ) set_vector( (handler), 0, 1 )
+
+#define Cause_tm27_intr()
+
+#define Clear_tm27_intr()
+
+#define Lower_tm27_intr()
+
+/* Constants -- THESE SHOULD BE DEFINED IN THE LINKER SCRIPT */
+
+#define RAM_START 0
+#define RAM_END 0x100000
+
+/* miscellaneous stuff assumed to exist */
+
+extern rtems_configuration_table BSP_Configuration;
+
+/*
+ * Device Driver Table Entries
+ */
+
+/*
+ * NOTE: Use the standard Console driver entry
+ */
+
+/*
+ * NOTE: Use the standard Clock driver entry
+ */
+
+/*
+ * How many libio files we want
+ */
+
+#define BSP_LIBIO_MAX_FDS 20
+
+/* functions */
+
+void bsp_cleanup( void );
+
+rtems_isr_entry set_vector( /* returns old vector */
+ rtems_isr_entry handler, /* isr routine */
+ rtems_vector_number vector, /* vector number */
+ int type /* RTEMS or RAW intr */
+);
+
+/*
+ * Debug print functions: implemented in console.c
+ */
+void printk( char *fmt, ... );
+void BSP_output_string( char * buf );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/include/coverhd.h b/c/src/lib/libbsp/powerpc/mbx8xx/include/coverhd.h
new file mode 100644
index 0000000000..37b2b3a5f1
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/include/coverhd.h
@@ -0,0 +1,366 @@
+/* coverhd.h
+ *
+ * This include file has defines to represent the overhead associated
+ * with calling a particular directive from C. These are used in the
+ * Timing Test Suite to ignore the overhead required to pass arguments
+ * to directives. On some CPUs and/or target boards, this overhead
+ * is significant and makes it difficult to distinguish internal
+ * RTEMS execution time from that used to call the directive.
+ * This file should be updated after running the C overhead timing
+ * test. Once this update has been performed, the RTEMS Time Test
+ * Suite should be rebuilt to account for these overhead times in the
+ * timing results.
+ *
+ * NOTE: If these are all zero, then the times reported include
+ * all calling overhead including passing of arguments.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#ifndef __COVERHD_h
+#define __COVERHD_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/targopts.h>
+
+#if ( defined(mbx821_001) || defined(mbx821_001b) || defined(mbx860_001b) )
+#if defined( INSTRUCTION_CACHE_ENABLE )
+/*
+ * 50 MHz processor, cache enabled.
+ */
+#define CALLING_OVERHEAD_INITIALIZE_EXECUTIVE 0
+#define CALLING_OVERHEAD_SHUTDOWN_EXECUTIVE 0
+#define CALLING_OVERHEAD_TASK_CREATE 1
+#define CALLING_OVERHEAD_TASK_IDENT 0
+#define CALLING_OVERHEAD_TASK_START 0
+#define CALLING_OVERHEAD_TASK_RESTART 0
+#define CALLING_OVERHEAD_TASK_DELETE 0
+#define CALLING_OVERHEAD_TASK_SUSPEND 0
+#define CALLING_OVERHEAD_TASK_RESUME 0
+#define CALLING_OVERHEAD_TASK_SET_PRIORITY 0
+#define CALLING_OVERHEAD_TASK_MODE 0
+#define CALLING_OVERHEAD_TASK_GET_NOTE 0
+#define CALLING_OVERHEAD_TASK_SET_NOTE 0
+#define CALLING_OVERHEAD_TASK_WAKE_WHEN 1
+#define CALLING_OVERHEAD_TASK_WAKE_AFTER 0
+#define CALLING_OVERHEAD_INTERRUPT_CATCH 0
+#define CALLING_OVERHEAD_CLOCK_GET 1
+#define CALLING_OVERHEAD_CLOCK_SET 1
+#define CALLING_OVERHEAD_CLOCK_TICK 0
+
+#define CALLING_OVERHEAD_TIMER_CREATE 0
+#define CALLING_OVERHEAD_TIMER_IDENT 0
+#define CALLING_OVERHEAD_TIMER_DELETE 0
+#define CALLING_OVERHEAD_TIMER_FIRE_AFTER 0
+#define CALLING_OVERHEAD_TIMER_FIRE_WHEN 1
+#define CALLING_OVERHEAD_TIMER_RESET 0
+#define CALLING_OVERHEAD_TIMER_CANCEL 0
+#define CALLING_OVERHEAD_SEMAPHORE_CREATE 0
+#define CALLING_OVERHEAD_SEMAPHORE_IDENT 0
+#define CALLING_OVERHEAD_SEMAPHORE_DELETE 0
+#define CALLING_OVERHEAD_SEMAPHORE_OBTAIN 0
+#define CALLING_OVERHEAD_SEMAPHORE_RELEASE 0
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_CREATE 0
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_IDENT 0
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_DELETE 0
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_SEND 0
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_URGENT 0
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_BROADCAST 0
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_RECEIVE 0
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_FLUSH 0
+
+#define CALLING_OVERHEAD_EVENT_SEND 0
+#define CALLING_OVERHEAD_EVENT_RECEIVE 0
+#define CALLING_OVERHEAD_SIGNAL_CATCH 0
+#define CALLING_OVERHEAD_SIGNAL_SEND 0
+#define CALLING_OVERHEAD_PARTITION_CREATE 1
+#define CALLING_OVERHEAD_PARTITION_IDENT 0
+#define CALLING_OVERHEAD_PARTITION_DELETE 0
+#define CALLING_OVERHEAD_PARTITION_GET_BUFFER 0
+#define CALLING_OVERHEAD_PARTITION_RETURN_BUFFER 0
+#define CALLING_OVERHEAD_REGION_CREATE 1
+#define CALLING_OVERHEAD_REGION_IDENT 0
+#define CALLING_OVERHEAD_REGION_DELETE 0
+#define CALLING_OVERHEAD_REGION_GET_SEGMENT 0
+#define CALLING_OVERHEAD_REGION_RETURN_SEGMENT 0
+#define CALLING_OVERHEAD_PORT_CREATE 0
+#define CALLING_OVERHEAD_PORT_IDENT 0
+#define CALLING_OVERHEAD_PORT_DELETE 0
+#define CALLING_OVERHEAD_PORT_EXTERNAL_TO_INTERNAL 0
+#define CALLING_OVERHEAD_PORT_INTERNAL_TO_EXTERNAL 0
+
+#define CALLING_OVERHEAD_IO_INITIALIZE 0
+#define CALLING_OVERHEAD_IO_OPEN 0
+#define CALLING_OVERHEAD_IO_CLOSE 0
+#define CALLING_OVERHEAD_IO_READ 0
+#define CALLING_OVERHEAD_IO_WRITE 0
+#define CALLING_OVERHEAD_IO_CONTROL 0
+#define CALLING_OVERHEAD_FATAL_ERROR_OCCURRED 0
+#define CALLING_OVERHEAD_RATE_MONOTONIC_CREATE 0
+#define CALLING_OVERHEAD_RATE_MONOTONIC_IDENT 0
+#define CALLING_OVERHEAD_RATE_MONOTONIC_DELETE 0
+#define CALLING_OVERHEAD_RATE_MONOTONIC_CANCEL 0
+#define CALLING_OVERHEAD_RATE_MONOTONIC_PERIOD 0
+#define CALLING_OVERHEAD_MULTIPROCESSING_ANNOUNCE 0
+
+#else
+/*
+ * 50 MHz processor, cache disabled.
+ */
+#define CALLING_OVERHEAD_INITIALIZE_EXECUTIVE 4
+#define CALLING_OVERHEAD_SHUTDOWN_EXECUTIVE 4
+#define CALLING_OVERHEAD_TASK_CREATE 7
+#define CALLING_OVERHEAD_TASK_IDENT 6
+#define CALLING_OVERHEAD_TASK_START 5
+#define CALLING_OVERHEAD_TASK_RESTART 5
+#define CALLING_OVERHEAD_TASK_DELETE 4
+#define CALLING_OVERHEAD_TASK_SUSPEND 4
+#define CALLING_OVERHEAD_TASK_RESUME 4
+#define CALLING_OVERHEAD_TASK_SET_PRIORITY 5
+#define CALLING_OVERHEAD_TASK_MODE 5
+#define CALLING_OVERHEAD_TASK_GET_NOTE 5
+#define CALLING_OVERHEAD_TASK_SET_NOTE 5
+#define CALLING_OVERHEAD_TASK_WAKE_WHEN 19
+#define CALLING_OVERHEAD_TASK_WAKE_AFTER 4
+#define CALLING_OVERHEAD_INTERRUPT_CATCH 5
+#define CALLING_OVERHEAD_CLOCK_GET 20
+#define CALLING_OVERHEAD_CLOCK_SET 19
+#define CALLING_OVERHEAD_CLOCK_TICK 3
+
+#define CALLING_OVERHEAD_TIMER_CREATE 5
+#define CALLING_OVERHEAD_TIMER_IDENT 4
+#define CALLING_OVERHEAD_TIMER_DELETE 5
+#define CALLING_OVERHEAD_TIMER_FIRE_AFTER 6
+#define CALLING_OVERHEAD_TIMER_FIRE_WHEN 21
+#define CALLING_OVERHEAD_TIMER_RESET 4
+#define CALLING_OVERHEAD_TIMER_CANCEL 4
+#define CALLING_OVERHEAD_SEMAPHORE_CREATE 6
+#define CALLING_OVERHEAD_SEMAPHORE_IDENT 4
+#define CALLING_OVERHEAD_SEMAPHORE_DELETE 6
+#define CALLING_OVERHEAD_SEMAPHORE_OBTAIN 5
+#define CALLING_OVERHEAD_SEMAPHORE_RELEASE 4
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_CREATE 6
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_IDENT 6
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_DELETE 4
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_SEND 5
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_URGENT 5
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_BROADCAST 5
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_RECEIVE 6
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_FLUSH 5
+
+#define CALLING_OVERHEAD_EVENT_SEND 5
+#define CALLING_OVERHEAD_EVENT_RECEIVE 5
+#define CALLING_OVERHEAD_SIGNAL_CATCH 4
+#define CALLING_OVERHEAD_SIGNAL_SEND 5
+#define CALLING_OVERHEAD_PARTITION_CREATE 7
+#define CALLING_OVERHEAD_PARTITION_IDENT 6
+#define CALLING_OVERHEAD_PARTITION_DELETE 4
+#define CALLING_OVERHEAD_PARTITION_GET_BUFFER 5
+#define CALLING_OVERHEAD_PARTITION_RETURN_BUFFER 5
+#define CALLING_OVERHEAD_REGION_CREATE 7
+#define CALLING_OVERHEAD_REGION_IDENT 5
+#define CALLING_OVERHEAD_REGION_DELETE 4
+#define CALLING_OVERHEAD_REGION_GET_SEGMENT 6
+#define CALLING_OVERHEAD_REGION_RETURN_SEGMENT 5
+#define CALLING_OVERHEAD_PORT_CREATE 6
+#define CALLING_OVERHEAD_PORT_IDENT 5
+#define CALLING_OVERHEAD_PORT_DELETE 4
+#define CALLING_OVERHEAD_PORT_EXTERNAL_TO_INTERNAL 6
+#define CALLING_OVERHEAD_PORT_INTERNAL_TO_EXTERNAL 6
+
+#define CALLING_OVERHEAD_IO_INITIALIZE 6
+#define CALLING_OVERHEAD_IO_OPEN 6
+#define CALLING_OVERHEAD_IO_CLOSE 6
+#define CALLING_OVERHEAD_IO_READ 6
+#define CALLING_OVERHEAD_IO_WRITE 6
+#define CALLING_OVERHEAD_IO_CONTROL 6
+#define CALLING_OVERHEAD_FATAL_ERROR_OCCURRED 4
+#define CALLING_OVERHEAD_RATE_MONOTONIC_CREATE 5
+#define CALLING_OVERHEAD_RATE_MONOTONIC_IDENT 5
+#define CALLING_OVERHEAD_RATE_MONOTONIC_DELETE 4
+#define CALLING_OVERHEAD_RATE_MONOTONIC_CANCEL 4
+#define CALLING_OVERHEAD_RATE_MONOTONIC_PERIOD 5
+#define CALLING_OVERHEAD_MULTIPROCESSING_ANNOUNCE 3
+
+#endif /* defined( INSTRUCTION_CACHE_ENABLE ) */
+
+#else
+#if defined( INSTRUCTION_CACHE_ENABLE )
+/*
+ * 40 MHz processor, cache enabled.
+ */
+#define CALLING_OVERHEAD_INITIALIZE_EXECUTIVE 0
+#define CALLING_OVERHEAD_SHUTDOWN_EXECUTIVE 1
+#define CALLING_OVERHEAD_TASK_CREATE 1
+#define CALLING_OVERHEAD_TASK_IDENT 0
+#define CALLING_OVERHEAD_TASK_START 0
+#define CALLING_OVERHEAD_TASK_RESTART 0
+#define CALLING_OVERHEAD_TASK_DELETE 0
+#define CALLING_OVERHEAD_TASK_SUSPEND 0
+#define CALLING_OVERHEAD_TASK_RESUME 0
+#define CALLING_OVERHEAD_TASK_SET_PRIORITY 0
+#define CALLING_OVERHEAD_TASK_MODE 0
+#define CALLING_OVERHEAD_TASK_GET_NOTE 0
+#define CALLING_OVERHEAD_TASK_SET_NOTE 0
+#define CALLING_OVERHEAD_TASK_WAKE_WHEN 1
+#define CALLING_OVERHEAD_TASK_WAKE_AFTER 0
+#define CALLING_OVERHEAD_INTERRUPT_CATCH 0
+#define CALLING_OVERHEAD_CLOCK_GET 1
+#define CALLING_OVERHEAD_CLOCK_SET 1
+#define CALLING_OVERHEAD_CLOCK_TICK 0
+
+#define CALLING_OVERHEAD_TIMER_CREATE 0
+#define CALLING_OVERHEAD_TIMER_IDENT 0
+#define CALLING_OVERHEAD_TIMER_DELETE 0
+#define CALLING_OVERHEAD_TIMER_FIRE_AFTER 0
+#define CALLING_OVERHEAD_TIMER_FIRE_WHEN 1
+#define CALLING_OVERHEAD_TIMER_RESET 0
+#define CALLING_OVERHEAD_TIMER_CANCEL 0
+#define CALLING_OVERHEAD_SEMAPHORE_CREATE 0
+#define CALLING_OVERHEAD_SEMAPHORE_IDENT 0
+#define CALLING_OVERHEAD_SEMAPHORE_DELETE 0
+#define CALLING_OVERHEAD_SEMAPHORE_OBTAIN 0
+#define CALLING_OVERHEAD_SEMAPHORE_RELEASE 0
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_CREATE 0
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_IDENT 0
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_DELETE 0
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_SEND 0
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_URGENT 0
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_BROADCAST 0
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_RECEIVE 0
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_FLUSH 0
+
+#define CALLING_OVERHEAD_EVENT_SEND 0
+#define CALLING_OVERHEAD_EVENT_RECEIVE 0
+#define CALLING_OVERHEAD_SIGNAL_CATCH 0
+#define CALLING_OVERHEAD_SIGNAL_SEND 0
+#define CALLING_OVERHEAD_PARTITION_CREATE 1
+#define CALLING_OVERHEAD_PARTITION_IDENT 0
+#define CALLING_OVERHEAD_PARTITION_DELETE 0
+#define CALLING_OVERHEAD_PARTITION_GET_BUFFER 0
+#define CALLING_OVERHEAD_PARTITION_RETURN_BUFFER 0
+#define CALLING_OVERHEAD_REGION_CREATE 1
+#define CALLING_OVERHEAD_REGION_IDENT 0
+#define CALLING_OVERHEAD_REGION_DELETE 0
+#define CALLING_OVERHEAD_REGION_GET_SEGMENT 0
+#define CALLING_OVERHEAD_REGION_RETURN_SEGMENT 0
+#define CALLING_OVERHEAD_PORT_CREATE 2
+#define CALLING_OVERHEAD_PORT_IDENT 0
+#define CALLING_OVERHEAD_PORT_DELETE 0
+#define CALLING_OVERHEAD_PORT_EXTERNAL_TO_INTERNAL 0
+#define CALLING_OVERHEAD_PORT_INTERNAL_TO_EXTERNAL 0
+
+#define CALLING_OVERHEAD_IO_INITIALIZE 0
+#define CALLING_OVERHEAD_IO_OPEN 0
+#define CALLING_OVERHEAD_IO_CLOSE 0
+#define CALLING_OVERHEAD_IO_READ 0
+#define CALLING_OVERHEAD_IO_WRITE 0
+#define CALLING_OVERHEAD_IO_CONTROL 0
+#define CALLING_OVERHEAD_FATAL_ERROR_OCCURRED 0
+#define CALLING_OVERHEAD_RATE_MONOTONIC_CREATE 0
+#define CALLING_OVERHEAD_RATE_MONOTONIC_IDENT 0
+#define CALLING_OVERHEAD_RATE_MONOTONIC_DELETE 0
+#define CALLING_OVERHEAD_RATE_MONOTONIC_CANCEL 0
+#define CALLING_OVERHEAD_RATE_MONOTONIC_PERIOD 0
+#define CALLING_OVERHEAD_MULTIPROCESSING_ANNOUNCE 0
+
+#else
+/*
+ * 40 MHz processor, cache disabled.
+ */
+#define CALLING_OVERHEAD_INITIALIZE_EXECUTIVE 4
+#define CALLING_OVERHEAD_SHUTDOWN_EXECUTIVE 3
+#define CALLING_OVERHEAD_TASK_CREATE 6
+#define CALLING_OVERHEAD_TASK_IDENT 5
+#define CALLING_OVERHEAD_TASK_START 5
+#define CALLING_OVERHEAD_TASK_RESTART 4
+#define CALLING_OVERHEAD_TASK_DELETE 4
+#define CALLING_OVERHEAD_TASK_SUSPEND 4
+#define CALLING_OVERHEAD_TASK_RESUME 4
+#define CALLING_OVERHEAD_TASK_SET_PRIORITY 5
+#define CALLING_OVERHEAD_TASK_MODE 4
+#define CALLING_OVERHEAD_TASK_GET_NOTE 5
+#define CALLING_OVERHEAD_TASK_SET_NOTE 5
+#define CALLING_OVERHEAD_TASK_WAKE_WHEN 17
+#define CALLING_OVERHEAD_TASK_WAKE_AFTER 3
+#define CALLING_OVERHEAD_INTERRUPT_CATCH 5
+#define CALLING_OVERHEAD_CLOCK_GET 17
+#define CALLING_OVERHEAD_CLOCK_SET 17
+#define CALLING_OVERHEAD_CLOCK_TICK 3
+
+#define CALLING_OVERHEAD_TIMER_CREATE 4
+#define CALLING_OVERHEAD_TIMER_IDENT 4
+#define CALLING_OVERHEAD_TIMER_DELETE 5
+#define CALLING_OVERHEAD_TIMER_FIRE_AFTER 5
+#define CALLING_OVERHEAD_TIMER_FIRE_WHEN 19
+#define CALLING_OVERHEAD_TIMER_RESET 4
+#define CALLING_OVERHEAD_TIMER_CANCEL 4
+#define CALLING_OVERHEAD_SEMAPHORE_CREATE 6
+#define CALLING_OVERHEAD_SEMAPHORE_IDENT 4
+#define CALLING_OVERHEAD_SEMAPHORE_DELETE 5
+#define CALLING_OVERHEAD_SEMAPHORE_OBTAIN 5
+#define CALLING_OVERHEAD_SEMAPHORE_RELEASE 4
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_CREATE 5
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_IDENT 5
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_DELETE 4
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_SEND 4
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_URGENT 4
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_BROADCAST 5
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_RECEIVE 5
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_FLUSH 4
+
+#define CALLING_OVERHEAD_EVENT_SEND 5
+#define CALLING_OVERHEAD_EVENT_RECEIVE 5
+#define CALLING_OVERHEAD_SIGNAL_CATCH 4
+#define CALLING_OVERHEAD_SIGNAL_SEND 4
+#define CALLING_OVERHEAD_PARTITION_CREATE 6
+#define CALLING_OVERHEAD_PARTITION_IDENT 5
+#define CALLING_OVERHEAD_PARTITION_DELETE 4
+#define CALLING_OVERHEAD_PARTITION_GET_BUFFER 5
+#define CALLING_OVERHEAD_PARTITION_RETURN_BUFFER 5
+#define CALLING_OVERHEAD_REGION_CREATE 6
+#define CALLING_OVERHEAD_REGION_IDENT 5
+#define CALLING_OVERHEAD_REGION_DELETE 4
+#define CALLING_OVERHEAD_REGION_GET_SEGMENT 6
+#define CALLING_OVERHEAD_REGION_RETURN_SEGMENT 5
+#define CALLING_OVERHEAD_PORT_CREATE 6
+#define CALLING_OVERHEAD_PORT_IDENT 5
+#define CALLING_OVERHEAD_PORT_DELETE 4
+#define CALLING_OVERHEAD_PORT_EXTERNAL_TO_INTERNAL 5
+#define CALLING_OVERHEAD_PORT_INTERNAL_TO_EXTERNAL 5
+
+#define CALLING_OVERHEAD_IO_INITIALIZE 5
+#define CALLING_OVERHEAD_IO_OPEN 5
+#define CALLING_OVERHEAD_IO_CLOSE 5
+#define CALLING_OVERHEAD_IO_READ 5
+#define CALLING_OVERHEAD_IO_WRITE 5
+#define CALLING_OVERHEAD_IO_CONTROL 5
+#define CALLING_OVERHEAD_FATAL_ERROR_OCCURRED 3
+#define CALLING_OVERHEAD_RATE_MONOTONIC_CREATE 4
+#define CALLING_OVERHEAD_RATE_MONOTONIC_IDENT 5
+#define CALLING_OVERHEAD_RATE_MONOTONIC_DELETE 4
+#define CALLING_OVERHEAD_RATE_MONOTONIC_CANCEL 4
+#define CALLING_OVERHEAD_RATE_MONOTONIC_PERIOD 4
+#define CALLING_OVERHEAD_MULTIPROCESSING_ANNOUNCE 3
+
+#endif /* defined( INSTRUCTION_CACHE_ENABLE ) */
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/network/Makefile.am b/c/src/lib/libbsp/powerpc/mbx8xx/network/Makefile.am
new file mode 100644
index 0000000000..795c36566f
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/network/Makefile.am
@@ -0,0 +1,36 @@
+##
+## $Id$
+##
+
+AUTOMAKE_OPTIONS = foreign 1.4
+
+PGM = $(ARCH)/network.rel
+
+C_FILES = network.c
+C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o)
+
+OBJS = $(C_O_FILES)
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../../../../../../automake/lib.am
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+AM_CPPFLAGS += -D__INSIDE_RTEMS_BSD_TCPIP_STACK__
+
+$(PGM): $(OBJS)
+ $(make-rel)
+
+# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
+
+if HAS_NETWORKING
+all-local: $(ARCH) $(OBJS) $(PGM)
+endif
+
+.PRECIOUS: $(PGM)
+
+EXTRA_DIST = network.c
+
+include $(top_srcdir)/../../../../../../automake/local.am
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/network/network.c b/c/src/lib/libbsp/powerpc/mbx8xx/network/network.c
new file mode 100644
index 0000000000..aaa477282f
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/network/network.c
@@ -0,0 +1,1702 @@
+/*
+ * RTEMS/TCPIP driver for MPC8xx SCC1 Ethernet
+ *
+ * Modified for MPC860 by Jay Monkman (jmonkman@frasca.com)
+ *
+ * This supports Ethernet on either SCC1 or the FEC of the MPC860T.
+ * Right now, we only do 10 Mbps, even with the FEC. The function
+ * rtems_enet_driver_attach determines which one to use. Currently,
+ * only one may be used at a time.
+ *
+ * Based on the MC68360 network driver by
+ * W. Eric Norum
+ * Saskatchewan Accelerator Laboratory
+ * University of Saskatchewan
+ * Saskatoon, Saskatchewan, CANADA
+ * eric@skatter.usask.ca
+ *
+ * This supports ethernet on SCC1. Right now, we only do 10 Mbps.
+ *
+ * Modifications by Darlene Stewart <Darlene.Stewart@iit.nrc.ca>
+ * and Charles-Antoine Gauthier <charles.gauthier@iit.nrc.ca>
+ * Copyright (c) 1999, National Research Council of Canada
+ *
+ * $Id$
+ */
+#include <bsp.h>
+#include <stdio.h>
+#include <rtems/error.h>
+#include <rtems/rtems_bsdnet.h>
+
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+/*
+ * Number of interfaces supported by this driver
+ */
+#define NIFACES 1
+
+/*
+ * Default number of buffer descriptors set aside for this driver.
+ * The number of transmit buffer descriptors has to be quite large
+ * since a single frame often uses four or more buffer descriptors.
+ */
+#define RX_BUF_COUNT 32
+#define TX_BUF_COUNT 8
+#define TX_BD_PER_BUF 4
+
+/*
+ * RTEMS event used by interrupt handler to signal daemons.
+ * This must *not* be the same event used by the TCP/IP task synchronization.
+ */
+#define INTERRUPT_EVENT RTEMS_EVENT_1
+
+/*
+ * RTEMS event used to start transmit daemon.
+ * This must not be the same as INTERRUPT_EVENT.
+ */
+#define START_TRANSMIT_EVENT RTEMS_EVENT_2
+
+/*
+ * Receive buffer size -- Allow for a full ethernet packet plus CRC (1518).
+ * Round off to nearest multiple of RBUF_ALIGN.
+ */
+#define MAX_MTU_SIZE 1518
+#define RBUF_ALIGN 4
+#define RBUF_SIZE ((MAX_MTU_SIZE + RBUF_ALIGN) & ~RBUF_ALIGN)
+
+#if (MCLBYTES < RBUF_SIZE)
+# error "Driver must have MCLBYTES > RBUF_SIZE"
+#endif
+
+extern unsigned32 simask_copy;
+
+/*
+ * Per-device data
+ */
+struct m8xx_enet_struct {
+ struct arpcom arpcom;
+ struct mbuf **rxMbuf;
+ struct mbuf **txMbuf;
+ int acceptBroadcast;
+ int rxBdCount;
+ int txBdCount;
+ int txBdHead;
+ int txBdTail;
+ int txBdActiveCount;
+ m8xxBufferDescriptor_t *rxBdBase;
+ m8xxBufferDescriptor_t *txBdBase;
+ rtems_id rxDaemonTid;
+ rtems_id txDaemonTid;
+
+ /*
+ * Statistics
+ */
+ unsigned long rxInterrupts;
+ unsigned long rxNotFirst;
+ unsigned long rxNotLast;
+ unsigned long rxGiant;
+ unsigned long rxNonOctet;
+ unsigned long rxRunt;
+ unsigned long rxBadCRC;
+ unsigned long rxOverrun;
+ unsigned long rxCollision;
+
+ unsigned long txInterrupts;
+ unsigned long txDeferred;
+ unsigned long txHeartbeat;
+ unsigned long txLateCollision;
+ unsigned long txRetryLimit;
+ unsigned long txUnderrun;
+ unsigned long txLostCarrier;
+ unsigned long txRawWait;
+};
+static struct m8xx_enet_struct enet_driver[NIFACES];
+
+
+/*
+ * SCC1 interrupt handler
+ */
+static rtems_isr
+m8xx_scc1_interrupt_handler (rtems_vector_number v)
+{
+ /* Frame received? */
+ if ((m8xx.scc1.sccm & 0x8) && (m8xx.scc1.scce & 0x8)) {
+ m8xx.scc1.scce = 0x8; /* Clear receive frame int */
+ m8xx.scc1.sccm &= ~0x8; /* Disable receive frame ints */
+ enet_driver[0].rxInterrupts++; /* Rx int has occurred */
+ rtems_event_send (enet_driver[0].rxDaemonTid, INTERRUPT_EVENT);
+ }
+
+ /* Buffer transmitted or transmitter error? */
+ if ((m8xx.scc1.sccm & 0x12) && (m8xx.scc1.scce & 0x12)) {
+ m8xx.scc1.scce = 0x12; /* Clear Tx int */
+ m8xx.scc1.sccm &= ~0x12; /* Disable Tx ints */
+ enet_driver[0].txInterrupts++; /* Tx int has occurred */
+ rtems_event_send (enet_driver[0].txDaemonTid, INTERRUPT_EVENT);
+ }
+ m8xx.cisr = 1UL << 30; /* Clear SCC1 interrupt-in-service bit */
+}
+
+#ifdef MPC860T
+/*
+ * FEC interrupt handler
+ */
+static rtems_isr
+m860_fec_interrupt_handler (rtems_vector_number v)
+{
+ /*
+ * Frame received?
+ */
+ if (m8xx.fec.ievent & M8xx_FEC_IEVENT_RFINT) {
+ m8xx.fec.ievent = M8xx_FEC_IEVENT_RFINT;
+ enet_driver[0].rxInterrupts++;
+ rtems_event_send (enet_driver[0].rxDaemonTid, INTERRUPT_EVENT);
+ }
+
+ /*
+ * Buffer transmitted or transmitter error?
+ */
+ if (m8xx.fec.ievent & M8xx_FEC_IEVENT_TFINT) {
+ m8xx.fec.ievent = M8xx_FEC_IEVENT_TFINT;
+ enet_driver[0].txInterrupts++;
+ rtems_event_send (enet_driver[0].txDaemonTid, INTERRUPT_EVENT);
+ }
+}
+#endif
+
+
+/*
+ * Initialize the ethernet hardware
+ */
+static void
+m8xx_enet_initialize (struct m8xx_enet_struct *sc)
+{
+ int i;
+ unsigned char *hwaddr;
+ rtems_status_code status;
+ rtems_isr_entry old_handler;
+
+ /*
+ * Configure port A
+ * PA15 is enet RxD. Set PAPAR(15) to 1, PADIR(15) to 0.
+ * PA14 is enet TxD. Set PAPAR(14) to 1, PADIR(14) to 0, PAODR(14) to 0.
+ * PA7 is input CLK1. Set PAPAR(7) to 1, PADIR(7) to 0.
+ * PA6 is input CLK2. Set PAPAR(6) to 1, PADIR(6) to 0.
+ */
+ m8xx.papar |= 0x303;
+ m8xx.padir &= ~0x303;
+ m8xx.paodr &= ~0x2;
+
+ /*
+ * Configure port C
+ * PC11 is CTS1*. Set PCPAR(11) to 0, PCDIR(11) to 0, and PCSO(11) to 1.
+ * PC10 is CD1*. Set PCPAR(10) to 0, PCDIR(10) to 0, and PCSO(10) to 1.
+ */
+ m8xx.pcpar &= ~0x30;
+ m8xx.pcdir &= ~0x30;
+ m8xx.pcso |= 0x30;
+
+ /*
+ * Connect CLK1 and CLK2 to SCC1 in the SICR.
+ * CLK1 is TxClk, CLK2 is RxClk. No grant mechanism, SCC1 is directly
+ * connected to the NMSI pins.
+ * R1CS = 0b101 (CLK2)
+ * T1CS = 0b100 (CLK1)
+ */
+ m8xx.sicr |= 0x2C;
+
+ /*
+ * Initialize SDMA configuration register
+ */
+ m8xx.sdcr = 1;
+
+ /*
+ * Allocate mbuf pointers
+ */
+ sc->rxMbuf = malloc (sc->rxBdCount * sizeof *sc->rxMbuf,
+ M_MBUF, M_NOWAIT);
+ sc->txMbuf = malloc (sc->txBdCount * sizeof *sc->txMbuf,
+ M_MBUF, M_NOWAIT);
+ if (!sc->rxMbuf || !sc->txMbuf)
+ rtems_panic ("No memory for mbuf pointers");
+
+ /*
+ * Set receiver and transmitter buffer descriptor bases
+ */
+ sc->rxBdBase = m8xx_bd_allocate(sc->rxBdCount);
+ sc->txBdBase = m8xx_bd_allocate(sc->txBdCount);
+ m8xx.scc1p.rbase = (char *)sc->rxBdBase - (char *)&m8xx;
+ m8xx.scc1p.tbase = (char *)sc->txBdBase - (char *)&m8xx;
+
+ /*
+ * Send "Init parameters" command
+ */
+ m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SCC1);
+
+ /*
+ * Set receive and transmit function codes
+ */
+ m8xx.scc1p.rfcr = M8xx_RFCR_MOT | M8xx_RFCR_DMA_SPACE(0);
+ m8xx.scc1p.tfcr = M8xx_TFCR_MOT | M8xx_TFCR_DMA_SPACE(0);
+
+ /*
+ * Set maximum receive buffer length
+ */
+ m8xx.scc1p.mrblr = RBUF_SIZE;
+
+ /*
+ * Set CRC parameters
+ */
+ m8xx.scc1p.un.ethernet.c_pres = 0xFFFFFFFF;
+ m8xx.scc1p.un.ethernet.c_mask = 0xDEBB20E3;
+
+ /*
+ * Clear diagnostic counters
+ */
+ m8xx.scc1p.un.ethernet.crcec = 0;
+ m8xx.scc1p.un.ethernet.alec = 0;
+ m8xx.scc1p.un.ethernet.disfc = 0;
+
+ /*
+ * Set pad value
+ */
+ m8xx.scc1p.un.ethernet.pads = 0x8888;
+
+ /*
+ * Set retry limit
+ */
+ m8xx.scc1p.un.ethernet.ret_lim = 15;
+
+ /*
+ * Set maximum and minimum frame length
+ */
+ m8xx.scc1p.un.ethernet.mflr = 1518;
+ m8xx.scc1p.un.ethernet.minflr = 64;
+ m8xx.scc1p.un.ethernet.maxd1 = MAX_MTU_SIZE;
+ m8xx.scc1p.un.ethernet.maxd2 = MAX_MTU_SIZE;
+
+ /*
+ * Clear group address hash table
+ */
+ m8xx.scc1p.un.ethernet.gaddr1 = 0;
+ m8xx.scc1p.un.ethernet.gaddr2 = 0;
+ m8xx.scc1p.un.ethernet.gaddr3 = 0;
+ m8xx.scc1p.un.ethernet.gaddr4 = 0;
+
+ /*
+ * Set our physical address
+ */
+ hwaddr = sc->arpcom.ac_enaddr;
+
+ m8xx.scc1p.un.ethernet.paddr_h = (hwaddr[5] << 8) | hwaddr[4];
+ m8xx.scc1p.un.ethernet.paddr_m = (hwaddr[3] << 8) | hwaddr[2];
+ m8xx.scc1p.un.ethernet.paddr_l = (hwaddr[1] << 8) | hwaddr[0];
+
+ /*
+ * Aggressive retry
+ */
+ m8xx.scc1p.un.ethernet.p_per = 0;
+
+ /*
+ * Clear individual address hash table
+ */
+ m8xx.scc1p.un.ethernet.iaddr1 = 0;
+ m8xx.scc1p.un.ethernet.iaddr2 = 0;
+ m8xx.scc1p.un.ethernet.iaddr3 = 0;
+ m8xx.scc1p.un.ethernet.iaddr4 = 0;
+
+ /*
+ * Clear temp address
+ */
+ m8xx.scc1p.un.ethernet.taddr_l = 0;
+ m8xx.scc1p.un.ethernet.taddr_m = 0;
+ m8xx.scc1p.un.ethernet.taddr_h = 0;
+
+ /*
+ * Set up receive buffer descriptors
+ */
+ for (i = 0 ; i < sc->rxBdCount ; i++) {
+ (sc->rxBdBase + i)->status = 0;
+ }
+
+ /*
+ * Set up transmit buffer descriptors
+ */
+ for (i = 0 ; i < sc->txBdCount ; i++) {
+ (sc->txBdBase + i)->status = 0;
+ sc->txMbuf[i] = NULL;
+ }
+ sc->txBdHead = sc->txBdTail = 0;
+ sc->txBdActiveCount = 0;
+
+ /*
+ * Clear any outstanding events
+ */
+ m8xx.scc1.scce = 0xFFFF;
+
+ /*
+ * Set up interrupts
+ */
+ status = rtems_interrupt_catch (m8xx_scc1_interrupt_handler,
+ PPC_IRQ_CPM_SCC1,
+ &old_handler);
+ if (status != RTEMS_SUCCESSFUL) {
+ rtems_panic ("Can't attach M8xx SCC1 interrupt handler: %s\n",
+ rtems_status_text (status));
+ }
+ m8xx.scc1.sccm = 0; /* No interrupts unmasked till necessary */
+ m8xx.cimr |= (1UL << 30); /* Enable SCC1 interrupt */
+
+ /*
+ * Set up General SCC Mode Register
+ * Ethernet configuration
+ */
+ m8xx.scc1.gsmr_h = 0x0;
+ m8xx.scc1.gsmr_l = 0x1088000c;
+
+ /*
+ * Set up data synchronization register
+ * Ethernet synchronization pattern
+ */
+ m8xx.scc1.dsr = 0xd555;
+
+ /*
+ * Set up protocol-specific mode register
+ * No Heartbeat check
+ * No force collision
+ * Discard short frames
+ * Individual address mode
+ * Ethernet CRC
+ * Not promisuous
+ * Ignore/accept broadcast packets as specified
+ * Normal backoff timer
+ * No loopback
+ * No input sample at end of frame
+ * 64-byte limit for late collision
+ * Wait 22 bits before looking for start of frame delimiter
+ * Disable full-duplex operation
+ */
+ m8xx.scc1.psmr = 0x080A | (sc->acceptBroadcast ? 0 : 0x100);
+
+ /*
+ * Enable the TENA (RTS1*) pin
+ */
+ m8xx.pcpar |= 0x1;
+ m8xx.pcdir &= ~0x1;
+
+
+ /*
+ * Set up interrupts
+ * FIXME: DANGER: WARNING:
+ * CICR and SIMASK must be set in any module that uses
+ * the CPM. Currently those are console-generic.c and
+ * network.c. If the registers are not set the same
+ * in both places, strange things may happen.
+ * If they are only set in one place, then an application
+ * that uses only the other module won't work correctly.
+ * Put this comment in each module that sets these 2 registers
+ */
+#ifdef mpc860
+ m8xx.cicr = 0x00e43f80; /* SCaP=SCC1, SCbP=SCC2, SCcP=SCC3,
+ SCdP=SCC4, IRL=1, HP=PC15, IEN=1 */
+#else
+ m8xx.cicr = 0x00043F80; /* SCaP=SCC1, SCbP=SCC2, IRL=1, HP=PC15, IEN=1 */
+#endif
+ simask_copy = m8xx.simask | M8xx_SIMASK_LVM1; /* Enable level interrupts */
+ m8xx.simask |= M8xx_SIMASK_LVM1; /* Enable level interrupts */
+
+ /*
+ * Enable receiver and transmitter
+ */
+ m8xx.scc1.gsmr_l = 0x1088003c;
+}
+
+
+#ifdef MPC860T
+static void
+m860_fec_initialize_hardware (struct m860_enet_struct *sc)
+{
+ int i;
+ unsigned char *hwaddr;
+ rtems_status_code status;
+ rtems_isr_entry old_handler;
+
+ /*
+ * Issue reset to FEC
+ */
+ m8xx.fec.ecntrl=0x1;
+
+ /*
+ * Put ethernet transciever in reset
+ */
+ m8xx.pgcra |= 0x80;
+
+ /*
+ * Configure I/O ports
+ */
+ m8xx.pdpar = 0x1fff;
+ m8xx.pddir = 0x1c58;
+
+ /*
+ * Take ethernet transciever out of reset
+ */
+ m8xx.pgcra &= ~0x80;
+
+
+ /*
+ * Set SIU interrupt level to LVL2
+ *
+ */
+ m8xx.fec.ivec = 0x02 << 29;
+
+ /*
+ * Set the TX and RX fifo sizes. For now, we'll split it evenly
+ */
+ /* If you uncomment these, the FEC will not work right.
+ m8xx.fec.r_fstart = ((m8xx.fec.r_bound & 0x3ff) >> 2) & 0x3ff;
+ m8xx.fec.x_fstart = 0;
+ */
+
+ /*
+ * Set our physical address
+ */
+ hwaddr = sc->arpcom.ac_enaddr;
+
+ m8xx.fec.addr_low = (hwaddr[0] << 24) | (hwaddr[1] << 16) |
+ (hwaddr[2] << 8) | (hwaddr[3] << 0);
+ m8xx.fec.addr_high = (hwaddr[4] << 24) | (hwaddr[5] << 16);
+
+ /*
+ * Clear the hash table
+ */
+ m8xx.fec.hash_table_high = 0;
+ m8xx.fec.hash_table_low = 0;
+
+ /*
+ * Set up receive buffer size
+ */
+ m8xx.fec.r_buf_size = 0x5f0; /* set to 1520 */
+
+ /*
+ * Allocate mbuf pointers
+ */
+ sc->rxMbuf = malloc (sc->rxBdCount * sizeof *sc->rxMbuf,
+ M_MBUF, M_NOWAIT);
+ sc->txMbuf = malloc (sc->txBdCount * sizeof *sc->txMbuf,
+ M_MBUF, M_NOWAIT);
+ if (!sc->rxMbuf || !sc->txMbuf)
+ rtems_panic ("No memory for mbuf pointers");
+
+ /*
+ * Set receiver and transmitter buffer descriptor bases
+ */
+ sc->rxBdBase = m8xx_bd_allocate(sc->rxBdCount);
+ sc->txBdBase = m8xx_bd_allocate(sc->txBdCount);
+ m8xx.fec.r_des_start = (int)sc->rxBdBase;
+ m8xx.fec.x_des_start = (int)sc->txBdBase;
+
+ /*
+ * Set up Receive Control Register:
+ * Not promiscuous mode
+ * MII mode
+ * Half duplex
+ * No loopback
+ */
+ m8xx.fec.r_cntrl = 0x00000006;
+
+ /*
+ * Set up Transmit Control Register:
+ * Half duplex
+ * No heartbeat
+ */
+ m8xx.fec.x_cntrl = 0x00000000;
+
+ /*
+ * Set up DMA function code:
+ * Big-endian
+ * DMA functino code = 0
+ */
+ m8xx.fec.fun_code = 0x78000000;
+
+ /*
+ * Initialize SDMA configuration register
+ * SDMA ignores FRZ
+ * FEC not aggressive
+ * FEC arbitration ID = 0 => U-bus arbitration = 6
+ * RISC arbitration ID = 1 => U-bus arbitration = 5
+ */
+ m8xx.sdcr = 1;
+
+ /*
+ * Set MII speed to 2.5 MHz for 25 Mhz system clock
+ */
+ m8xx.fec.mii_speed = 0x0a;
+ m8xx.fec.mii_data = 0x58021000;
+
+ /*
+ * Set up receive buffer descriptors
+ */
+ for (i = 0 ; i < sc->rxBdCount ; i++)
+ (sc->rxBdBase + i)->status = 0;
+
+ /*
+ * Set up transmit buffer descriptors
+ */
+ for (i = 0 ; i < sc->txBdCount ; i++) {
+ (sc->txBdBase + i)->status = 0;
+ sc->txMbuf[i] = NULL;
+ }
+ sc->txBdHead = sc->txBdTail = 0;
+ sc->txBdActiveCount = 0;
+
+
+
+ /*
+ * Mask all FEC interrupts and clear events
+ */
+ m8xx.fec.imask = M8xx_FEC_IEVENT_TFINT |
+ M8xx_FEC_IEVENT_RFINT;
+ m8xx.fec.ievent = ~0;
+
+ /*
+ * Set up interrupts
+ */
+ status = rtems_interrupt_catch (m860_fec_interrupt_handler,
+ PPC_IRQ_LVL2,
+ &old_handler);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_panic ("Can't attach M860 FEC interrupt handler: %s\n",
+ rtems_status_text (status));
+
+}
+#endif
+
+
+/*
+ * Soak up buffer descriptors that have been sent.
+ * Note that a buffer descriptor can't be retired as soon as it becomes
+ * ready. The MPC860 manual (MPC860UM/AD 07/98 Rev.1) and the MPC821
+ * manual state that, "If an Ethernet frame is made up of multiple
+ * buffers, the user should not reuse the first buffer descriptor until
+ * the last buffer descriptor of the frame has had its ready bit cleared
+ * by the CPM".
+ */
+static void
+m8xx_Enet_retire_tx_bd (struct m8xx_enet_struct *sc)
+{
+ rtems_unsigned16 status;
+ int i;
+ int nRetired;
+ struct mbuf *m, *n;
+
+ i = sc->txBdTail;
+ nRetired = 0;
+ while ((sc->txBdActiveCount != 0)
+ && (((status = (sc->txBdBase + i)->status) & M8xx_BD_READY) == 0)) {
+ /*
+ * See if anything went wrong
+ */
+ if (status & (M8xx_BD_DEFER |
+ M8xx_BD_HEARTBEAT |
+ M8xx_BD_LATE_COLLISION |
+ M8xx_BD_RETRY_LIMIT |
+ M8xx_BD_UNDERRUN |
+ M8xx_BD_CARRIER_LOST)) {
+ /*
+ * Check for errors which stop the transmitter.
+ */
+ if (status & (M8xx_BD_LATE_COLLISION |
+ M8xx_BD_RETRY_LIMIT |
+ M8xx_BD_UNDERRUN)) {
+ if (status & M8xx_BD_LATE_COLLISION)
+ enet_driver[0].txLateCollision++;
+ if (status & M8xx_BD_RETRY_LIMIT)
+ enet_driver[0].txRetryLimit++;
+ if (status & M8xx_BD_UNDERRUN)
+ enet_driver[0].txUnderrun++;
+
+ /*
+ * Restart the transmitter
+ */
+ /* FIXME: this should get executed only if using the SCC */
+ m8xx_cp_execute_cmd (M8xx_CR_OP_RESTART_TX | M8xx_CR_CHAN_SCC1);
+ }
+ if (status & M8xx_BD_DEFER)
+ enet_driver[0].txDeferred++;
+ if (status & M8xx_BD_HEARTBEAT)
+ enet_driver[0].txHeartbeat++;
+ if (status & M8xx_BD_CARRIER_LOST)
+ enet_driver[0].txLostCarrier++;
+ }
+ nRetired++;
+ if (status & M8xx_BD_LAST) {
+ /*
+ * A full frame has been transmitted.
+ * Free all the associated buffer descriptors.
+ */
+ sc->txBdActiveCount -= nRetired;
+ while (nRetired) {
+ nRetired--;
+ m = sc->txMbuf[sc->txBdTail];
+ MFREE (m, n);
+ if (++sc->txBdTail == sc->txBdCount)
+ sc->txBdTail = 0;
+ }
+ }
+ if (++i == sc->txBdCount)
+ i = 0;
+ }
+}
+
+/*
+ * reader task
+ */
+static void
+scc_rxDaemon (void *arg)
+{
+ struct m8xx_enet_struct *sc = (struct m8xx_enet_struct *)arg;
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ struct mbuf *m;
+ rtems_unsigned16 status;
+ m8xxBufferDescriptor_t *rxBd;
+ int rxBdIndex;
+
+ /*
+ * Allocate space for incoming packets and start reception
+ */
+ for (rxBdIndex = 0 ; ;) {
+ rxBd = sc->rxBdBase + rxBdIndex;
+ MGETHDR (m, M_WAIT, MT_DATA);
+ MCLGET (m, M_WAIT);
+ m->m_pkthdr.rcvif = ifp;
+ sc->rxMbuf[rxBdIndex] = m;
+ rxBd->buffer = mtod (m, void *);
+ rxBd->status = M8xx_BD_EMPTY | M8xx_BD_INTERRUPT;
+ if (++rxBdIndex == sc->rxBdCount) {
+ rxBd->status |= M8xx_BD_WRAP;
+ break;
+ }
+ }
+
+ /*
+ * Input packet handling loop
+ */
+ rxBdIndex = 0;
+ for (;;) {
+ rxBd = sc->rxBdBase + rxBdIndex;
+
+ /*
+ * Wait for packet if there's not one ready
+ */
+ if ((status = rxBd->status) & M8xx_BD_EMPTY) {
+ /*
+ * Clear old events
+ */
+ m8xx.scc1.scce = 0x8;
+
+ /*
+ * Wait for packet
+ * Note that the buffer descriptor is checked
+ * *before* the event wait -- this catches the
+ * possibility that a packet arrived between the
+ * `if' above, and the clearing of the event register.
+ */
+ while ((status = rxBd->status) & M8xx_BD_EMPTY) {
+ rtems_event_set events;
+
+ /*
+ * Unmask RXF (Full frame received) event
+ */
+ m8xx.scc1.sccm |= 0x8;
+
+ rtems_bsdnet_event_receive (INTERRUPT_EVENT,
+ RTEMS_WAIT|RTEMS_EVENT_ANY,
+ RTEMS_NO_TIMEOUT,
+ &events);
+ }
+ }
+
+ /*
+ * Check that packet is valid
+ */
+ if ((status & (M8xx_BD_LAST |
+ M8xx_BD_FIRST_IN_FRAME |
+ M8xx_BD_LONG |
+ M8xx_BD_NONALIGNED |
+ M8xx_BD_SHORT |
+ M8xx_BD_CRC_ERROR |
+ M8xx_BD_OVERRUN |
+ M8xx_BD_COLLISION)) ==
+ (M8xx_BD_LAST |
+ M8xx_BD_FIRST_IN_FRAME)) {
+ /*
+ * Pass the packet up the chain.
+ * FIXME: Packet filtering hook could be done here.
+ */
+ struct ether_header *eh;
+
+ /*
+ * Invalidate the buffer for this descriptor
+ */
+ rtems_invalidate_multiple_data_cache_lines(rxBd->buffer, rxBd->length);
+
+ m = sc->rxMbuf[rxBdIndex];
+ m->m_len = m->m_pkthdr.len = rxBd->length -
+ sizeof(rtems_unsigned32) -
+ sizeof(struct ether_header);
+ eh = mtod (m, struct ether_header *);
+ m->m_data += sizeof(struct ether_header);
+ ether_input (ifp, eh, m);
+
+ /*
+ * Allocate a new mbuf
+ */
+ MGETHDR (m, M_WAIT, MT_DATA);
+ MCLGET (m, M_WAIT);
+ m->m_pkthdr.rcvif = ifp;
+ sc->rxMbuf[rxBdIndex] = m;
+ rxBd->buffer = mtod (m, void *);
+ }
+ else {
+ /*
+ * Something went wrong with the reception
+ */
+ if (!(status & M8xx_BD_LAST))
+ sc->rxNotLast++;
+ if (!(status & M8xx_BD_FIRST_IN_FRAME))
+ sc->rxNotFirst++;
+ if (status & M8xx_BD_LONG)
+ sc->rxGiant++;
+ if (status & M8xx_BD_NONALIGNED)
+ sc->rxNonOctet++;
+ if (status & M8xx_BD_SHORT)
+ sc->rxRunt++;
+ if (status & M8xx_BD_CRC_ERROR)
+ sc->rxBadCRC++;
+ if (status & M8xx_BD_OVERRUN)
+ sc->rxOverrun++;
+ if (status & M8xx_BD_COLLISION)
+ sc->rxCollision++;
+ }
+
+ /*
+ * Reenable the buffer descriptor
+ */
+ rxBd->status = (status & (M8xx_BD_WRAP | M8xx_BD_INTERRUPT)) |
+ M8xx_BD_EMPTY;
+
+ /*
+ * Move to next buffer descriptor
+ */
+ if (++rxBdIndex == sc->rxBdCount)
+ rxBdIndex = 0;
+ }
+}
+
+
+#ifdef MPC860T
+static void
+fec_rxDaemon (void *arg)
+{
+ struct m8xx_enet_struct *sc = (struct m8xx_enet_struct *)arg;
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ struct mbuf *m;
+ rtems_unsigned16 status;
+ m8xxBufferDescriptor_t *rxBd;
+ int rxBdIndex;
+
+ /*
+ * Allocate space for incoming packets and start reception
+ */
+ for (rxBdIndex = 0 ; ;) {
+ rxBd = sc->rxBdBase + rxBdIndex;
+ MGETHDR (m, M_WAIT, MT_DATA);
+ MCLGET (m, M_WAIT);
+ m->m_pkthdr.rcvif = ifp;
+ sc->rxMbuf[rxBdIndex] = m;
+ rxBd->buffer = mtod (m, void *);
+ rxBd->status = M8xx_BD_EMPTY;
+ m8xx.fec.r_des_active = 0x1000000;
+ if (++rxBdIndex == sc->rxBdCount) {
+ rxBd->status |= M8xx_BD_WRAP;
+ break;
+ }
+ }
+
+ /*
+ * Input packet handling loop
+ */
+ rxBdIndex = 0;
+ for (;;) {
+ rxBd = sc->rxBdBase + rxBdIndex;
+
+ /*
+ * Wait for packet if there's not one ready
+ */
+ if ((status = rxBd->status) & M8xx_BD_EMPTY) {
+ /*
+ * Clear old events
+ */
+ m8xx.fec.ievent = M8xx_FEC_IEVENT_RFINT;
+
+ /*
+ * Wait for packet
+ * Note that the buffer descriptor is checked
+ * *before* the event wait -- this catches the
+ * possibility that a packet arrived between the
+ * `if' above, and the clearing of the event register.
+ */
+ while ((status = rxBd->status) & M8xx_BD_EMPTY) {
+ rtems_event_set events;
+
+ /*
+ * Unmask RXF (Full frame received) event
+ */
+ m8xx.fec.ievent |= M8xx_FEC_IEVENT_RFINT;
+
+ rtems_bsdnet_event_receive (INTERRUPT_EVENT,
+ RTEMS_WAIT|RTEMS_EVENT_ANY,
+ RTEMS_NO_TIMEOUT,
+ &events);
+ }
+ }
+
+ /*
+ * Check that packet is valid
+ */
+ if (status & M8xx_BD_LAST) {
+ /*
+ * Pass the packet up the chain.
+ * FIXME: Packet filtering hook could be done here.
+ */
+ struct ether_header *eh;
+
+ /*
+ * Invalidate the buffer for this descriptor
+ */
+ rtems_invalidate_multiple_data_cache_lines(rxBd->buffer, rxBd->length);
+
+ m = sc->rxMbuf[rxBdIndex];
+ m->m_len = m->m_pkthdr.len = rxBd->length -
+ sizeof(rtems_unsigned32) -
+ sizeof(struct ether_header);
+ eh = mtod (m, struct ether_header *);
+ m->m_data += sizeof(struct ether_header);
+ ether_input (ifp, eh, m);
+
+ /*
+ * Allocate a new mbuf
+ */
+ MGETHDR (m, M_WAIT, MT_DATA);
+ MCLGET (m, M_WAIT);
+ m->m_pkthdr.rcvif = ifp;
+ sc->rxMbuf[rxBdIndex] = m;
+ rxBd->buffer = mtod (m, void *);
+ }
+ else {
+ /*
+ * Something went wrong with the reception
+ */
+ if (!(status & M8xx_BD_LAST))
+ sc->rxNotLast++;
+ if (status & M8xx_BD_LONG)
+ sc->rxGiant++;
+ if (status & M8xx_BD_NONALIGNED)
+ sc->rxNonOctet++;
+ if (status & M8xx_BD_SHORT)
+ sc->rxRunt++;
+ if (status & M8xx_BD_CRC_ERROR)
+ sc->rxBadCRC++;
+ if (status & M8xx_BD_OVERRUN)
+ sc->rxOverrun++;
+ if (status & M8xx_BD_COLLISION)
+ sc->rxCollision++;
+ }
+ /*
+ * Reenable the buffer descriptor
+ */
+ rxBd->status = (status & M8xx_BD_WRAP) |
+ M8xx_BD_EMPTY;
+ m8xx.fec.r_des_active = 0x1000000;
+ /*
+ * Move to next buffer descriptor
+ */
+ if (++rxBdIndex == sc->rxBdCount)
+ rxBdIndex = 0;
+ }
+}
+#endif
+
+
+static void
+scc_sendpacket (struct ifnet *ifp, struct mbuf *m)
+{
+ struct m8xx_enet_struct *sc = ifp->if_softc;
+ volatile m8xxBufferDescriptor_t *firstTxBd, *txBd;
+ struct mbuf *l = NULL;
+ rtems_unsigned16 status;
+ int nAdded;
+
+ /*
+ * Free up buffer descriptors
+ */
+ m8xx_Enet_retire_tx_bd (sc);
+
+ /*
+ * Set up the transmit buffer descriptors.
+ * No need to pad out short packets since the
+ * hardware takes care of that automatically.
+ * No need to copy the packet to a contiguous buffer
+ * since the hardware is capable of scatter/gather DMA.
+ */
+ nAdded = 0;
+ txBd = firstTxBd = sc->txBdBase + sc->txBdHead;
+ for (;;) {
+ /*
+ * Wait for buffer descriptor to become available.
+ */
+ if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
+ /*
+ * Clear old events
+ */
+ m8xx.scc1.scce = 0x12;
+
+ /*
+ * Wait for buffer descriptor to become available.
+ * Note that the buffer descriptors are checked
+ * *before* * entering the wait loop -- this catches
+ * the possibility that a buffer descriptor became
+ * available between the `if' above, and the clearing
+ * of the event register.
+ * This is to catch the case where the transmitter
+ * stops in the middle of a frame -- and only the
+ * last buffer descriptor in a frame can generate
+ * an interrupt.
+ */
+ m8xx_Enet_retire_tx_bd (sc);
+ while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
+ rtems_event_set events;
+
+ /*
+ * Unmask TXB (buffer transmitted) and
+ * TXE (transmitter error) events.
+ */
+ m8xx.scc1.sccm |= 0x12;
+ rtems_bsdnet_event_receive (INTERRUPT_EVENT,
+ RTEMS_WAIT|RTEMS_EVENT_ANY,
+ RTEMS_NO_TIMEOUT,
+ &events);
+ m8xx_Enet_retire_tx_bd (sc);
+ }
+ }
+
+ /*
+ * Don't set the READY flag till the
+ * whole packet has been readied.
+ */
+ status = nAdded ? M8xx_BD_READY : 0;
+
+ /*
+ * FIXME: Why not deal with empty mbufs at at higher level?
+ * The IP fragmentation routine in ip_output
+ * can produce packet fragments with zero length.
+ * I think that ip_output should be changed to get
+ * rid of these zero-length mbufs, but for now,
+ * I'll deal with them here.
+ */
+ if (m->m_len) {
+ /*
+ * Fill in the buffer descriptor
+ */
+ txBd->buffer = mtod (m, void *);
+ txBd->length = m->m_len;
+
+ /*
+ * Flush the buffer for this descriptor
+ */
+ rtems_flush_multiple_data_cache_lines(txBd->buffer, txBd->length);
+
+ sc->txMbuf[sc->txBdHead] = m;
+ nAdded++;
+ if (++sc->txBdHead == sc->txBdCount) {
+ status |= M8xx_BD_WRAP;
+ sc->txBdHead = 0;
+ }
+ l = m;
+ m = m->m_next;
+ }
+ else {
+ /*
+ * Just toss empty mbufs
+ */
+ struct mbuf *n;
+ MFREE (m, n);
+ m = n;
+ if (l != NULL)
+ l->m_next = m;
+ }
+
+ /*
+ * Set the transmit buffer status.
+ * Break out of the loop if this mbuf is the last in the frame.
+ */
+ if (m == NULL) {
+ if (nAdded) {
+ status |= M8xx_BD_PAD | M8xx_BD_LAST | M8xx_BD_TX_CRC | M8xx_BD_INTERRUPT;
+ txBd->status = status;
+ firstTxBd->status |= M8xx_BD_READY;
+ sc->txBdActiveCount += nAdded;
+ }
+ break;
+ }
+ txBd->status = status;
+ txBd = sc->txBdBase + sc->txBdHead;
+ }
+}
+
+
+#ifdef MPC860T
+static void
+fec_sendpacket (struct ifnet *ifp, struct mbuf *m)
+{
+ struct m8xx_enet_struct *sc = ifp->if_softc;
+ volatile m8xxBufferDescriptor_t *firstTxBd, *txBd;
+ /* struct mbuf *l = NULL; */
+ rtems_unsigned16 status;
+ int nAdded;
+
+ /*
+ * Free up buffer descriptors
+ */
+ m8xx_Enet_retire_tx_bd (sc);
+
+ /*
+ * Set up the transmit buffer descriptors.
+ * No need to pad out short packets since the
+ * hardware takes care of that automatically.
+ * No need to copy the packet to a contiguous buffer
+ * since the hardware is capable of scatter/gather DMA.
+ */
+ nAdded = 0;
+ txBd = firstTxBd = sc->txBdBase + sc->txBdHead;
+ for (;;) {
+ /*
+ * Wait for buffer descriptor to become available.
+ */
+ if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
+ /*
+ * Clear old events
+ */
+ m8xx.fec.ievent = M8xx_FEC_IEVENT_TFINT;
+
+ /*
+ * Wait for buffer descriptor to become available.
+ * Note that the buffer descriptors are checked
+ * *before* * entering the wait loop -- this catches
+ * the possibility that a buffer descriptor became
+ * available between the `if' above, and the clearing
+ * of the event register.
+ * This is to catch the case where the transmitter
+ * stops in the middle of a frame -- and only the
+ * last buffer descriptor in a frame can generate
+ * an interrupt.
+ */
+ m8xx_Enet_retire_tx_bd (sc);
+ while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
+ rtems_event_set events;
+
+ /*
+ * Unmask TXB (buffer transmitted) and
+ * TXE (transmitter error) events.
+ */
+ m8xx.fec.ievent |= M8xx_FEC_IEVENT_TFINT;
+ rtems_bsdnet_event_receive (INTERRUPT_EVENT,
+ RTEMS_WAIT|RTEMS_EVENT_ANY,
+ RTEMS_NO_TIMEOUT,
+ &events);
+ m8xx_Enet_retire_tx_bd (sc);
+ }
+ }
+
+ /*
+ * Don't set the READY flag till the
+ * whole packet has been readied.
+ */
+ status = nAdded ? M8xx_BD_READY : 0;
+
+ /*
+ * FIXME: Why not deal with empty mbufs at at higher level?
+ * The IP fragmentation routine in ip_output
+ * can produce packet fragments with zero length.
+ * I think that ip_output should be changed to get
+ * rid of these zero-length mbufs, but for now,
+ * I'll deal with them here.
+ */
+ if (m->m_len) {
+ /*
+ * Fill in the buffer descriptor
+ */
+ txBd->buffer = mtod (m, void *);
+ txBd->length = m->m_len;
+
+ /*
+ * Flush the buffer for this descriptor
+ */
+ rtems_flush_multiple_data_cache_lines(txBd->buffer, txBd->length);
+
+ sc->txMbuf[sc->txBdHead] = m;
+ nAdded++;
+ if (++sc->txBdHead == sc->txBdCount) {
+ status |= M8xx_BD_WRAP;
+ sc->txBdHead = 0;
+ }
+ /* l = m;*/
+ m = m->m_next;
+ }
+ else {
+ /*
+ * Just toss empty mbufs
+ */
+ struct mbuf *n;
+ MFREE (m, n);
+ m = n;
+ /*
+ if (l != NULL)
+ l->m_next = m;
+ */
+ }
+
+ /*
+ * Set the transmit buffer status.
+ * Break out of the loop if this mbuf is the last in the frame.
+ */
+ if (m == NULL) {
+ if (nAdded) {
+ status |= M8xx_BD_LAST | M8xx_BD_TX_CRC;
+ txBd->status = status;
+ firstTxBd->status |= M8xx_BD_READY;
+ m8xx.fec.x_des_active = 0x1000000;
+ sc->txBdActiveCount += nAdded;
+ }
+ break;
+ }
+ txBd->status = status;
+ txBd = sc->txBdBase + sc->txBdHead;
+ }
+}
+#endif
+
+
+/*
+ * Driver transmit daemon
+ */
+void
+scc_txDaemon (void *arg)
+{
+ struct m8xx_enet_struct *sc = (struct m8xx_enet_struct *)arg;
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ struct mbuf *m;
+ rtems_event_set events;
+
+ for (;;) {
+ /*
+ * Wait for packet
+ */
+ rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events);
+
+ /*
+ * Send packets till queue is empty
+ */
+ for (;;) {
+ /*
+ * Get the next mbuf chain to transmit.
+ */
+ IF_DEQUEUE(&ifp->if_snd, m);
+ if (!m)
+ break;
+ scc_sendpacket (ifp, m);
+ }
+ ifp->if_flags &= ~IFF_OACTIVE;
+ }
+}
+
+
+#ifdef MPC860T
+void
+fec_txDaemon (void *arg)
+{
+ struct m8xx_enet_struct *sc = (struct m8xx_enet_struct *)arg;
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ struct mbuf *m;
+ rtems_event_set events;
+
+ for (;;) {
+ /*
+ * Wait for packet
+ */
+ rtems_bsdnet_event_receive (START_TRANSMIT_EVENT,
+ RTEMS_EVENT_ANY | RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT,
+ &events);
+
+ /*
+ * Send packets till queue is empty
+ */
+ for (;;) {
+ /*
+ * Get the next mbuf chain to transmit.
+ */
+ IF_DEQUEUE(&ifp->if_snd, m);
+ if (!m)
+ break;
+ fec_sendpacket (ifp, m);
+ }
+ ifp->if_flags &= ~IFF_OACTIVE;
+ }
+}
+#endif
+
+
+/*
+ * Send packet (caller provides header).
+ */
+static void
+m8xx_enet_start (struct ifnet *ifp)
+{
+ struct m8xx_enet_struct *sc = ifp->if_softc;
+
+ rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT);
+ ifp->if_flags |= IFF_OACTIVE;
+}
+
+
+/*
+ * Initialize and start the device
+ */
+static void
+scc_init (void *arg)
+{
+ struct m8xx_enet_struct *sc = arg;
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+
+ if (sc->txDaemonTid == 0) {
+
+ /*
+ * Set up SCC hardware
+ */
+ m8xx_enet_initialize (sc);
+
+ /*
+ * Start driver tasks
+ */
+ sc->txDaemonTid = rtems_bsdnet_newproc ("SCtx", 4096, scc_txDaemon, sc);
+ sc->rxDaemonTid = rtems_bsdnet_newproc ("SCrx", 4096, scc_rxDaemon, sc);
+
+ }
+
+ /*
+ * Set flags appropriately
+ */
+ if (ifp->if_flags & IFF_PROMISC)
+ m8xx.scc1.psmr |= 0x200;
+ else
+ m8xx.scc1.psmr &= ~0x200;
+
+ /*
+ * Tell the world that we're running.
+ */
+ ifp->if_flags |= IFF_RUNNING;
+
+ /*
+ * Enable receiver and transmitter
+ */
+ m8xx.scc1.gsmr_l |= 0x30;
+}
+
+
+#ifdef MPC860T
+static void
+fec_init (void *arg)
+{
+ struct m8xx_enet_struct *sc = arg;
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+
+ if (sc->txDaemonTid == 0) {
+
+ /*
+ * Set up SCC hardware
+ */
+ m8xx_fec_initialize_hardware (sc);
+
+ /*
+ * Start driver tasks
+ */
+ sc->txDaemonTid = rtems_bsdnet_newproc ("SCtx", 4096, fec_txDaemon, sc);
+ sc->rxDaemonTid = rtems_bsdnet_newproc ("SCrx", 4096, fec_rxDaemon, sc);
+
+ }
+
+ /*
+ * Set flags appropriately
+ */
+ if (ifp->if_flags & IFF_PROMISC)
+ m8xx.fec.r_cntrl |= 0x8;
+ else
+ m8xx.fec.r_cntrl &= ~0x8;
+
+
+ /*
+ * Tell the world that we're running.
+ */
+ ifp->if_flags |= IFF_RUNNING;
+
+ /*
+ * Enable receiver and transmitter
+ */
+ m8xx.fec.ecntrl = 0x2;
+}
+#endif
+
+
+/*
+ * Stop the device
+ */
+static void
+scc_stop (struct m8xx_enet_struct *sc)
+{
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+
+ ifp->if_flags &= ~IFF_RUNNING;
+
+ /*
+ * Shut down receiver and transmitter
+ */
+ m8xx.scc1.gsmr_l &= ~0x30;
+}
+
+
+#ifdef MPC860T
+static void
+fec_stop (struct m8xx_enet_struct *sc)
+{
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+
+ ifp->if_flags &= ~IFF_RUNNING;
+
+ /*
+ * Shut down receiver and transmitter
+ */
+ m8xx.fec.ecntrl = 0x0;
+}
+#endif
+
+
+/*
+ * Show interface statistics
+ */
+static void
+enet_stats (struct m8xx_enet_struct *sc)
+{
+ printf (" Rx Interrupts:%-8lu", sc->rxInterrupts);
+ printf (" Not First:%-8lu", sc->rxNotFirst);
+ printf (" Not Last:%-8lu\n", sc->rxNotLast);
+ printf (" Giant:%-8lu", sc->rxGiant);
+ printf (" Runt:%-8lu", sc->rxRunt);
+ printf (" Non-octet:%-8lu\n", sc->rxNonOctet);
+ printf (" Bad CRC:%-8lu", sc->rxBadCRC);
+ printf (" Overrun:%-8lu", sc->rxOverrun);
+ printf (" Collision:%-8lu\n", sc->rxCollision);
+ printf (" Discarded:%-8lu\n", (unsigned long)m8xx.scc1p.un.ethernet.disfc);
+
+ printf (" Tx Interrupts:%-8lu", sc->txInterrupts);
+ printf (" Deferred:%-8lu", sc->txDeferred);
+ printf (" Missed Hearbeat:%-8lu\n", sc->txHeartbeat);
+ printf (" No Carrier:%-8lu", sc->txLostCarrier);
+ printf ("Retransmit Limit:%-8lu", sc->txRetryLimit);
+ printf (" Late Collision:%-8lu\n", sc->txLateCollision);
+ printf (" Underrun:%-8lu", sc->txUnderrun);
+ printf (" Raw output wait:%-8lu\n", sc->txRawWait);
+}
+
+
+/*
+ * Driver ioctl handler
+ */
+static int
+scc_ioctl (struct ifnet *ifp, int command, caddr_t data)
+{
+ struct m8xx_enet_struct *sc = ifp->if_softc;
+ int error = 0;
+
+ switch (command) {
+ case SIOCGIFADDR:
+ case SIOCSIFADDR:
+ ether_ioctl (ifp, command, data);
+ break;
+
+ case SIOCSIFFLAGS:
+ switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
+ case IFF_RUNNING:
+ scc_stop (sc);
+ break;
+
+ case IFF_UP:
+ scc_init (sc);
+ break;
+
+ case IFF_UP | IFF_RUNNING:
+ scc_stop (sc);
+ scc_init (sc);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case SIO_RTEMS_SHOW_STATS:
+ enet_stats (sc);
+ break;
+
+ /*
+ * FIXME: All sorts of multicast commands need to be added here!
+ */
+ default:
+ error = EINVAL;
+ break;
+ }
+ return error;
+}
+
+
+#ifdef MPC860T
+static int
+fec_ioctl (struct ifnet *ifp, int command, caddr_t data)
+{
+ struct m8xx_enet_struct *sc = ifp->if_softc;
+ int error = 0;
+
+ switch (command) {
+ case SIOCGIFADDR:
+ case SIOCSIFADDR:
+ ether_ioctl (ifp, command, data);
+ break;
+
+ case SIOCSIFFLAGS:
+ switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
+ case IFF_RUNNING:
+ fec_stop (sc);
+ break;
+
+ case IFF_UP:
+ fec_init (sc);
+ break;
+
+ case IFF_UP | IFF_RUNNING:
+ fec_stop (sc);
+ fec_init (sc);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case SIO_RTEMS_SHOW_STATS:
+ enet_stats (sc);
+ break;
+
+ /*
+ * FIXME: All sorts of multicast commands need to be added here!
+ */
+ default:
+ error = EINVAL;
+ break;
+ }
+ return error;
+}
+#endif
+
+
+/*
+ * Attach an SCC driver to the system
+ */
+int
+rtems_scc1_driver_attach (struct rtems_bsdnet_ifconfig *config)
+{
+ struct m8xx_enet_struct *sc;
+ struct ifnet *ifp;
+ int mtu;
+ int unitNumber;
+ char *unitName;
+
+ /*
+ * Parse driver name
+ */
+ if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0)
+ return 0;
+
+ /*
+ * Is driver free?
+ */
+ if ((unitNumber <= 0) || (unitNumber > NIFACES)) {
+ printf ("Bad SCC unit number.\n");
+ return 0;
+ }
+ sc = &enet_driver[unitNumber - 1];
+ ifp = &sc->arpcom.ac_if;
+ if (ifp->if_softc != NULL) {
+ printf ("Driver already in use.\n");
+ return 0;
+ }
+
+ /*
+ * Process options
+ */
+ if (config->hardware_address) {
+ memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
+ }
+ else {
+ /* FIXME to read the enaddr from NVRAM */
+ }
+
+ if (config->mtu)
+ mtu = config->mtu;
+ else
+ mtu = ETHERMTU;
+ if (config->rbuf_count)
+ sc->rxBdCount = config->rbuf_count;
+ else
+ sc->rxBdCount = RX_BUF_COUNT;
+ if (config->xbuf_count)
+ sc->txBdCount = config->xbuf_count;
+ else
+ sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF;
+ sc->acceptBroadcast = !config->ignore_broadcast;
+
+ /*
+ * Set up network interface values
+ */
+ ifp->if_softc = sc;
+ ifp->if_unit = unitNumber;
+ ifp->if_name = unitName;
+ ifp->if_mtu = mtu;
+ ifp->if_init = scc_init;
+ ifp->if_ioctl = scc_ioctl;
+ ifp->if_start = m8xx_enet_start;
+ ifp->if_output = ether_output;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
+ if (ifp->if_snd.ifq_maxlen == 0)
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
+
+ /*
+ * Attach the interface
+ */
+ if_attach (ifp);
+ ether_ifattach (ifp);
+ return 1;
+};
+
+
+#ifdef MPC860T
+int
+rtems_fec_driver_attach (struct rtems_bsdnet_ifconfig *config)
+{
+ struct m8xx_enet_struct *sc;
+ struct ifnet *ifp;
+ int mtu;
+ int unitNumber;
+ char *unitName;
+
+ /*
+ * Parse driver name
+ */
+ if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0)
+ return 0;
+
+ /*
+ * Is driver free?
+ */
+ if ((unitNumber <= 0) || (unitNumber > NIFACES)) {
+ printf ("Bad SCC unit number.\n");
+ return 0;
+ }
+ sc = &enet_driver[unitNumber - 1];
+ ifp = &sc->arpcom.ac_if;
+ if (ifp->if_softc != NULL) {
+ printf ("Driver already in use.\n");
+ return 0;
+ }
+
+ /*
+ * Process options
+ */
+ if (config->hardware_address) {
+ memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
+ }
+ else {
+ /* FIXME to read the enaddr from NVRAM */
+ }
+ if (config->mtu)
+ mtu = config->mtu;
+ else
+ mtu = ETHERMTU;
+ if (config->rbuf_count)
+ sc->rxBdCount = config->rbuf_count;
+ else
+ sc->rxBdCount = RX_BUF_COUNT;
+ if (config->xbuf_count)
+ sc->txBdCount = config->xbuf_count;
+ else
+ sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF;
+ sc->acceptBroadcast = !config->ignore_broadcast;
+
+ /*
+ * Set up network interface values
+ */
+ ifp->if_softc = sc;
+ ifp->if_unit = unitNumber;
+ ifp->if_name = unitName;
+ ifp->if_mtu = mtu;
+ ifp->if_init = fec_init;
+ ifp->if_ioctl = fec_ioctl;
+ ifp->if_start = m8xx_enet_start;
+ ifp->if_output = ether_output;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
+ if (ifp->if_snd.ifq_maxlen == 0)
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
+
+ /*
+ * Attach the interface
+ */
+ if_attach (ifp);
+ ether_ifattach (ifp);
+ return 1;
+};
+#endif
+
+
+int
+rtems_enet_driver_attach (struct rtems_bsdnet_ifconfig *config)
+{
+
+#ifdef MPC860T
+ if ((m8xx.fec.mii_data & 0xffff) == 0x2000) {
+/* rtems_scc1_driver_attach(config);*/
+ return rtems_fec_driver_attach(config);
+ }
+ else {
+#endif
+ return rtems_scc1_driver_attach(config);
+#ifdef MPC860T
+ }
+#endif
+}
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/startup/Makefile.am b/c/src/lib/libbsp/powerpc/mbx8xx/startup/Makefile.am
new file mode 100644
index 0000000000..3b2eb17f8d
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/startup/Makefile.am
@@ -0,0 +1,42 @@
+##
+## $Id$
+##
+
+AUTOMAKE_OPTIONS = foreign 1.4
+
+VPATH = @srcdir@:@srcdir@/../../../shared
+
+PGM = $(ARCH)/startup.rel
+
+C_FILES = bspclean.c bsplibc.c bsppost.c bspstart.c bootcard.c imbx8xx.c main.c \
+ mmutlbtab.c sbrk.c setvec.c gnatinstallhandler.c
+C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o)
+
+S_FILES = start.s
+S_O_FILES = $(S_FILES:%.s=$(ARCH)/%.o)
+
+OBJS = $(C_O_FILES) $(S_O_FILES)
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../../../../../../automake/lib.am
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+$(PGM): $(OBJS)
+ $(make-rel)
+
+$(PROJECT_RELEASE)/lib/linkcmds: linkcmds
+ $(INSTALL_DATA) $< $@
+
+# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
+TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/linkcmds
+
+all-local: $(ARCH) $(OBJS) $(PGM) $(TMPINSTALL_FILES)
+
+.PRECIOUS: $(PGM)
+
+EXTRA_DIST = bspstart.c imbx8xx.c linkcmds mmutlbtab.c setvec.c
+
+include $(top_srcdir)/../../../../../../automake/local.am
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/startup/bspstart.c b/c/src/lib/libbsp/powerpc/mbx8xx/startup/bspstart.c
new file mode 100644
index 0000000000..2180df9b44
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/startup/bspstart.c
@@ -0,0 +1,193 @@
+/* bspstart.c
+ *
+ * This set of routines starts the application. It includes application,
+ * board, and monitor specific initialization and configuration.
+ * The generic CPU dependent initialization has been performed
+ * before this routine is invoked.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * Modifications for MBX860:
+ * Copyright (c) 1999, National Research Council of Canada
+ *
+ * $Id$
+ */
+
+#include <bsp.h>
+#include <rtems/libio.h>
+
+#include <libcsupport.h>
+
+#include <string.h>
+
+#ifdef STACK_CHECKER_ON
+#include <stackchk.h>
+#endif
+
+/*
+ * The original table from the application (in ROM) and our copy of it with
+ * some changes. Configuration is defined in <confdefs.h>. Make sure that
+ * our configuration tables are uninitialized so that they get allocated in
+ * the .bss section (RAM).
+ */
+extern rtems_configuration_table Configuration;
+rtems_configuration_table BSP_Configuration;
+
+rtems_cpu_table Cpu_table;
+
+char *rtems_progname;
+
+/*
+ * Use the shared implementations of the following routines.
+ * Look in rtems/c/src/lib/libbsp/shared/bsppost.c and
+ * rtems/c/src/lib/libbsp/shared/bsplibc.c.
+ */
+void bsp_postdriver_hook(void);
+void bsp_libc_init( void *, unsigned32, int );
+
+/*
+ * bsp_pretasking_hook
+ *
+ * Called when RTEMS initialization is complete but before interrupts and
+ * tasking are enabled. Used to setup libc and install any BSP extensions.
+ *
+ * Must not use libc (to do io) from here, since drivers are not yet
+ * initialized.
+ *
+ * Installed in the rtems_cpu_table defined in
+ * rtems/c/src/exec/score/cpu/m68k/cpu.h in main() below. Called from
+ * rtems_initialize_executive() defined in rtems/c/src/exec/sapi/src/init.c
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values: NONE
+ */
+void bsp_pretasking_hook(void)
+{
+ /*
+ * These are assigned addresses in the linkcmds file for the BSP. This
+ * approach is better than having these defined as manifest constants and
+ * compiled into the kernel, but it is still not ideal when dealing with
+ * multiprocessor configuration in which each board as a different memory
+ * map. A better place for defining these symbols might be the makefiles.
+ * Consideration should also be given to developing an approach in which
+ * the kernel and the application can be linked and burned into ROM
+ * independently of each other.
+ */
+ extern unsigned char _HeapStart;
+ extern unsigned char _HeapEnd;
+
+ bsp_libc_init( &_HeapStart, &_HeapEnd - &_HeapStart, 0 );
+
+#ifdef STACK_CHECKER_ON
+ /*
+ * Initialize the stack bounds checker
+ * We can either turn it on here or from the app.
+ */
+
+ Stack_check_Initialize();
+#endif /* STACK_CHECKER_ON */
+
+#ifdef RTEMS_DEBUG
+ rtems_debug_enable( RTEMS_DEBUG_ALL_MASK );
+#endif
+}
+
+
+/*
+ * bsp_start()
+ *
+ * Board-specific initialization code. Called from the generic boot_card()
+ * function defined in rtems/c/src/lib/libbsp/shared/main.c. That function
+ * does some of the board independent initialization. It is called from the
+ * MBX8xx entry point _start() defined in
+ * rtems/c/src/lib/libbsp/powerpc/mbx8xx/startup/start.S
+ *
+ * _start() has set up a stack, has zeroed the .bss section, has turned off
+ * interrupts, and placed the processor in the supervisor mode. boot_card()
+ * has left the processor in that state when bsp_start() was called.
+ *
+ * RUNS WITH ADDRESS TRANSLATION AND CACHING TURNED OFF!
+ * ASSUMES THAT THE VIRTUAL ADDRESSES WILL BE IDENTICAL TO THE PHYSICAL
+ * ADDRESSES. Software-controlled address translation would be required
+ * otherwise.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values: NONE
+ */
+void bsp_start(void)
+{
+ extern void *_WorkspaceBase;
+
+ mmu_init();
+
+ /*
+ * Enable instruction and data caches. Do not force writethrough mode.
+ */
+ #ifdef INSTRUCTION_CACHE_ENABLE
+ rtems_enable_inst_cache();
+ #endif
+
+ #ifdef DATA_CACHE_ENABLE
+ rtems_enable_data_cache();
+ #endif
+
+ /*
+ * Allocate the memory for the RTEMS Work Space. This can come from
+ * a variety of places: hard coded address, malloc'ed from outside
+ * RTEMS world (e.g. simulator or primitive memory manager), or (as
+ * typically done by stock BSPs) by subtracting the required amount
+ * of work space from the last physical address on the CPU board.
+ *
+ * In this case, the memory is not malloc'ed. It is just
+ * "pulled from the air".
+ */
+ BSP_Configuration.work_space_start = (void *)&_WorkspaceBase;
+
+ /*
+ * initialize the CPU table for this BSP
+ */
+
+ Cpu_table.pretasking_hook = bsp_pretasking_hook; /* init libc, etc. */
+ Cpu_table.postdriver_hook = bsp_postdriver_hook;
+ if( Cpu_table.interrupt_stack_size < 4 * 1024 )
+ Cpu_table.interrupt_stack_size = 4 * 1024;
+
+ Cpu_table.clicks_per_usec = 1; /* for 4MHz extclk */
+ Cpu_table.serial_per_sec = 10000000;
+ Cpu_table.serial_external_clock = 1;
+ Cpu_table.serial_xon_xoff = 0;
+ Cpu_table.serial_cts_rts = 1;
+ Cpu_table.serial_rate = 9600;
+#if ( defined(mbx821_001) || defined(mbx821_001b) || defined(mbx860_001b) )
+ Cpu_table.clock_speed = 50000000;
+ Cpu_table.timer_average_overhead = 3;
+ Cpu_table.timer_least_valid = 3;
+#else
+ Cpu_table.clock_speed = 40000000;
+ Cpu_table.timer_average_overhead = 3;
+ Cpu_table.timer_least_valid = 3;
+#endif
+
+ /*
+ * Call this in case we use TERMIOS for console I/O
+ */
+ m8xx_uart_reserve_resources( &BSP_Configuration );
+
+ m8xx.scc2.sccm=0;
+ m8xx.scc2p.rbase=0;
+ m8xx.scc2p.tbase=0;
+ m8xx_cp_execute_cmd( M8xx_CR_OP_STOP_TX | M8xx_CR_CHAN_SCC2 );
+}
+
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/startup/bspstart.c.nocache b/c/src/lib/libbsp/powerpc/mbx8xx/startup/bspstart.c.nocache
new file mode 100644
index 0000000000..055e84ad27
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/startup/bspstart.c.nocache
@@ -0,0 +1,202 @@
+/* bspstart.c
+ *
+ * This set of routines starts the application. It includes application,
+ * board, and monitor specific initialization and configuration.
+ * The generic CPU dependent initialization has been performed
+ * before this routine is invoked.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * Modifications for MBX860:
+ * Copyright (c) 1999, National Research Council of Canada
+ *
+ * $Id$
+ */
+
+#include <bsp.h>
+#include <rtems/libio.h>
+
+#include <libcsupport.h>
+
+#include <string.h>
+
+#ifdef STACK_CHECKER_ON
+#include <stackchk.h>
+#endif
+
+/*
+ * The original table from the application (in ROM) and our copy of it with
+ * some changes. Configuration is defined in <confdefs.h>. Make sure that
+ * our configuration tables are uninitialized so that they get allocated in
+ * the .bss section (RAM).
+ */
+extern rtems_configuration_table Configuration;
+rtems_configuration_table BSP_Configuration;
+
+rtems_cpu_table Cpu_table;
+
+char *rtems_progname;
+
+/*
+ * Use the shared implementations of the following routines.
+ * Look in rtems/c/src/lib/libbsp/shared/bsppost.c and
+ * rtems/c/src/lib/libbsp/shared/bsplibc.c.
+ */
+void bsp_postdriver_hook(void);
+void bsp_libc_init( void *, unsigned32, int );
+
+/*
+ * bsp_pretasking_hook
+ *
+ * Called when RTEMS initialization is complete but before interrupts and
+ * tasking are enabled. Used to setup libc and install any BSP extensions.
+ *
+ * Must not use libc (to do io) from here, since drivers are not yet
+ * initialized.
+ *
+ * Installed in the rtems_cpu_table defined in
+ * rtems/c/src/exec/score/cpu/m68k/cpu.h in main() below. Called from
+ * rtems_initialize_executive() defined in rtems/c/src/exec/sapi/src/init.c
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values: NONE
+ */
+void bsp_pretasking_hook(void)
+{
+ /*
+ * These are assigned addresses in the linkcmds file for the BSP. This
+ * approach is better than having these defined as manifest constants and
+ * compiled into the kernel, but it is still not ideal when dealing with
+ * multiprocessor configuration in which each board as a different memory
+ * map. A better place for defining these symbols might be the makefiles.
+ * Consideration should also be given to developing an approach in which
+ * the kernel and the application can be linked and burned into ROM
+ * independently of each other.
+ */
+ extern unsigned char _HeapStart;
+ extern unsigned char _HeapEnd;
+
+ bsp_libc_init( &_HeapStart, &_HeapEnd - &_HeapStart, 0 );
+
+#ifdef STACK_CHECKER_ON
+ /*
+ * Initialize the stack bounds checker
+ * We can either turn it on here or from the app.
+ */
+
+ Stack_check_Initialize();
+#endif /* STACK_CHECKER_ON */
+
+#ifdef RTEMS_DEBUG
+ rtems_debug_enable( RTEMS_DEBUG_ALL_MASK );
+#endif
+}
+
+
+/*
+ * bsp_start()
+ *
+ * Board-specific initialization code. Called from the generic boot_card()
+ * function defined in rtems/c/src/lib/libbsp/shared/main.c. That function
+ * does some of the board independent initialization. It is called from the
+ * MBX8xx entry point _start() defined in
+ * rtems/c/src/lib/libbsp/powerpc/mbx8xx/startup/start.S
+ *
+ * _start() has set up a stack, has zeroed the .bss section, has turned off
+ * interrupts, and placed the processor in the supervisor mode. boot_card()
+ * has left the processor in that state when bsp_start() was called.
+ *
+ * RUNS WITH ADDRESS TRANSLATION AND CACHING TURNED OFF!
+ * ASSUMES THAT THE VIRTUAL ADDRESSES WILL BE IDENTICAL TO THE PHYSICAL
+ * ADDRESSES. Software-controlled address translation would be required
+ * otherwise.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values: NONE
+ */
+void bsp_start(void)
+{
+ extern void *_WorkspaceBase;
+ unsigned32 r1;
+
+ mmu_init();
+
+ /*
+ * Enable instruction and data caches. Do not force writethrough mode.
+ */
+ #ifdef INSTRUCTION_CACHE_ENABLE
+ r1 = M8xx_CACHE_CMD_ENABLE;
+ _mtspr( M8xx_IC_CST, r1 );
+ _isync;
+ #endif
+
+ /*
+ * Warning: EPPCBug 1.1 chokes to death if the data cache is turned on.
+ * Set DATA_CACHE_ENABLE to zero in mbx8xx.cfg if EPPCBUG is used.
+ */
+ #ifdef DATA_CACHE_ENABLE
+ r1 = M8xx_CACHE_CMD_ENABLE;
+ _mtspr( M8xx_DC_CST, r1 );
+ _isync;
+ #endif
+
+ /*
+ * Allocate the memory for the RTEMS Work Space. This can come from
+ * a variety of places: hard coded address, malloc'ed from outside
+ * RTEMS world (e.g. simulator or primitive memory manager), or (as
+ * typically done by stock BSPs) by subtracting the required amount
+ * of work space from the last physical address on the CPU board.
+ *
+ * In this case, the memory is not malloc'ed. It is just
+ * "pulled from the air".
+ */
+ BSP_Configuration.work_space_start = (void *)&_WorkspaceBase;
+
+ /*
+ * initialize the CPU table for this BSP
+ */
+
+ Cpu_table.pretasking_hook = bsp_pretasking_hook; /* init libc, etc. */
+ Cpu_table.postdriver_hook = bsp_postdriver_hook;
+ if( Cpu_table.interrupt_stack_size < 4 * 1024 )
+ Cpu_table.interrupt_stack_size = 4 * 1024;
+
+ Cpu_table.clicks_per_usec = 1; /* for 4MHz extclk */
+ Cpu_table.serial_per_sec = 10000000;
+ Cpu_table.serial_external_clock = 1;
+ Cpu_table.serial_xon_xoff = 0;
+ Cpu_table.serial_cts_rts = 1;
+ Cpu_table.serial_rate = 9600;
+#if ( defined(mbx821_001) || defined(mbx821_001b) || defined(mbx860_001b) )
+ Cpu_table.clock_speed = 50000000;
+ Cpu_table.timer_average_overhead = 3;
+ Cpu_table.timer_least_valid = 3;
+#else
+ Cpu_table.clock_speed = 40000000;
+ Cpu_table.timer_average_overhead = 3;
+ Cpu_table.timer_least_valid = 3;
+#endif
+
+ /*
+ * Call this in case we use TERMIOS for console I/O
+ */
+ m8xx_uart_reserve_resources( &BSP_Configuration );
+
+ m8xx.scc2.sccm=0;
+ m8xx.scc2p.rbase=0;
+ m8xx.scc2p.tbase=0;
+ m8xx_cp_execute_cmd( M8xx_CR_OP_STOP_TX | M8xx_CR_CHAN_SCC2 );
+}
+
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/startup/imbx8xx.c b/c/src/lib/libbsp/powerpc/mbx8xx/startup/imbx8xx.c
new file mode 100644
index 0000000000..423f933079
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/startup/imbx8xx.c
@@ -0,0 +1,535 @@
+/*
+ * imbx8xx.c
+ *
+ * MBX860/MBX821 initialization routines.
+ *
+ * Copyright (c) 1999, National Research Council of Canada
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ */
+
+#include <bsp.h>
+
+/*
+ * EPPCBug rev 1.1 is stupid. It clears the interrupt mask register
+ * in the SIU when it takes control, but does not restore it before
+ * returning control to the program. We thus keep a copy of the
+ * register, and restore it from gdb using the hook facilities.
+ *
+ * We arrange for simask_copy to be initialized to zero so that
+ * it resides in the .data section. This avoids having gdb set
+ * the mask to crud before we get to initialize explicitly. Of
+ * course, the code will not be safely restartable, but then again,
+ * a lot of the library code isn't either, so there!
+ */
+unsigned32 simask_copy = 0;
+
+/*
+ * The memory controller's UPMA Ram array values.
+ * The values in table 2-6 and 2-7 in the "MBX Series Embedded
+ * Controller Programmer's Reference Guide", part number MBXA/PG2,
+ * differ from the ones in the older MBX Programmer's Guide, part
+ * number MBXA/PG1. We are assuming that the values in MBXA/PG1
+ * are for the older MBX boards whose part number does not have
+ * the "B" suffix, but we have discovered that the values from
+ * MBXA/PG2 work better, even for the older boards.
+ *
+ * THESE VALUES HAVE ONLY BEEN VERIFIED FOR THE MBX821-001 and
+ * MBX860-002. USE WITH CARE!
+ *
+ * NOTE: The MBXA/PG2 manual lists the clock speed of the MBX821_001B
+ * as being 50 MHz, while the MBXA/IH2.1 manual lists it as 40 MHz.
+ * We think the MBX821_001B is an entry level board and thus is 50 MHz,
+ */
+static unsigned32 upmaTable[64] = {
+
+#if ( defined(mbx860_001b) || \
+ defined(mbx821_001b) || \
+ defined(mbx821_001) )
+
+ /* 50 MHz MBX */
+ /*
+ * Note: For the mbx821_001, the following values (from the
+ * MBXA/PG2 manual) work better than, but are different
+ * from those published in the original MBXA/PG1 manual and
+ * initialized by EPPCBug 1.1. In particular, the original
+ * burst-write values do not work! Also, the following values
+ * facilitate higher performance.
+ */
+ /* DRAM 60ns - single read. (offset 0x00 in UPM RAM) */
+ 0xCFAFC004, 0x0FAFC404, 0x0CAF8C04, 0x10AF0C04,
+ 0xF0AF0C00, 0xF3BF4805, 0xFFFFC005, 0xFFFFC005,
+
+ /* DRAM 60ns - burst read. (offset 0x08 in UPM RAM) */
+ 0xCFAFC004, 0x0FAFC404, 0x0CAF8C04, 0x00AF0C04,
+ 0x07AF0C08, 0x0CAF0C04, 0x01AF0C04, 0x0FAF0C08,
+ 0x0CAF0C04, 0x01AF0C04, 0x0FAF0C08, 0x0CAF0C04,
+ 0x10AF0C04, 0xF0AFC000, 0xF3BF4805, 0xFFFFC005,
+
+ /* DRAM 60ns - single write. (offset 0x18 in UPM RAM) */
+ 0xCFFF0004, 0x0FFF0404, 0x0CFF0C00, 0x13FF4804,
+ 0xFFFFC004, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
+
+ /* DRAM 60ns - burst write. (offset 0x20 in UPM RAM) */
+ 0xCFFF0004, 0x0FFF0404, 0x0CFF0C00, 0x03FF0C0C,
+ 0x0CFF0C00, 0x03FF0C0C, 0x0CFF0C00, 0x03FF0C0C,
+ 0x0CFF0C00, 0x13FF4804, 0xFFFFC004, 0xFFFFC005,
+ 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
+
+ /* Refresh 60ns. (offset 0x30 in UPM RAM) */
+ 0xFCFFC004, 0xC0FFC004, 0x01FFC004, 0x0FFFC004,
+ 0x1FFFC004, 0xFFFFC004, 0xFFFFC005, 0xFFFFC005,
+ 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
+
+ /* Exception. (offset 0x3c in UPM RAM) */
+ 0xFFFFC007, 0xFFFFC007, 0xFFFFC007, 0xFFFFC007
+
+#elif ( defined(mbx860_002b) || \
+ defined(mbx860_003b) || \
+ defined(mbx860_004b) || \
+ defined(mbx860_005b) || \
+ defined(mbx860_006b) || \
+ defined(mbx821_002b) || \
+ defined(mbx821_003b) || \
+ defined(mbx821_004b) || \
+ defined(mbx821_005b) || \
+ defined(mbx821_006b) || \
+ defined(mbx860_001) || \
+ defined(mbx860_002) || \
+ defined(mbx860_003) || \
+ defined(mbx860_004) || \
+ defined(mbx860_005) || \
+ defined(mbx821_002) || \
+ defined(mbx821_003) || \
+ defined(mbx821_004) || \
+ defined(mbx821_005) )
+
+ /* 40 MHz MBX */
+ /*
+ * Note: For the older MBX models (i.e. without the "b"
+ * suffix, e.g. mbx860_001), the following values (from the
+ * MBXA/PG2 manual) work better than, but are different
+ * from those published in the original MBXA/PG1 manual and
+ * initialized by EPPCBug 1.1. In particular, the following
+ * burst-read and burst-write values facilitate higher
+ * performance.
+ */
+ /* DRAM 60ns - single read. (offset 0x00 in UPM RAM) */
+ 0xCFAFC004, 0x0FAFC404, 0x0CAF0C04, 0x30AF0C00,
+ 0xF1BF4805, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
+
+ /* DRAM 60ns - burst read. (offset 0x08 in UPM RAM) */
+ 0xCFAFC004, 0x0FAFC404, 0x0CAF0C04, 0x03AF0C08,
+ 0x0CAF0C04, 0x03AF0C08, 0x0CAF0C04, 0x03AF0C08,
+ 0x0CAF0C04, 0x30AF0C00, 0xF3BF4805, 0xFFFFC005,
+ 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
+
+ /* DRAM 60ns - single write. (offset 0x18 in UPM RAM) */
+ 0xCFFF0004, 0x0FFF4004, 0x0CFF0C00, 0x33FF4804,
+ 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
+
+ /* DRAM 60ns - burst write. (offset 0x20 in UPM RAM) */
+ 0xCFFF0004, 0x0FFF4004, 0x0CFF0C00, 0x03FF0C0C,
+ 0x0CFF0C00, 0x03FF0C0C, 0x0CFF0C00, 0x03FF0C0C,
+ 0x0CFF0C00, 0x33FF4804, 0xFFFFC005, 0xFFFFC005,
+ 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
+
+ /* Refresh 60ns. (offset 0x30 in UPM RAM) */
+ 0xFCFFC004, 0xC0FFC004, 0x01FFC004, 0x0FFFC004,
+ 0x3FFFC004, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
+ 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
+
+ /* Exception. (offset 0x3c in UPM RAM) */
+ 0xFFFFC007, 0xFFFFC007, 0xFFFFC007, 0xFFFFC007
+#else
+#error "MBX board model not specified."
+#endif
+};
+
+/*
+ * Initialize MBX8xx
+ */
+void _InitMBX8xx (void)
+{
+ register unsigned32 r1, i;
+ extern unsigned32 simask_copy;
+
+ /*
+ * Get the SIU interrupt mask.
+ */
+ simask_copy = m8xx.simask;
+
+ /*
+ * Initialize the Debug Enable Register (DER) to an appropriate
+ * value for EPPCBug debugging.
+ * (This value should also work for BDM debugging.)
+ */
+ r1 = 0x70C67C07; /* All except EXTIE, ALIE, DECIE */
+ _mtspr( M8xx_DER, r1 );
+
+ /*
+ * Initialize the Instruction Support Control Register (ICTRL) to a
+ * an appropriate value for normal operation. A different value,
+ * such as 0x0, may be more appropriate for debugging.
+ */
+ r1 = 0x00000007;
+ _mtspr( M8xx_ICTRL, r1 );
+
+ /*
+ * Disable and invalidate the instruction and data caches.
+ */
+ r1 = M8xx_CACHE_CMD_DISABLE;
+ _mtspr( M8xx_IC_CST, r1 );
+ _isync;
+ r1 = M8xx_CACHE_CMD_UNLOCKALL;
+ _mtspr( M8xx_IC_CST, r1 );
+ _isync;
+ r1 = M8xx_CACHE_CMD_INVALIDATE; /* invalidate all */
+ _mtspr( M8xx_IC_CST, r1 );
+ _isync;
+
+ r1 = M8xx_CACHE_CMD_DISABLE;
+ _mtspr( M8xx_DC_CST, r1 );
+ _isync;
+ r1 = M8xx_CACHE_CMD_UNLOCKALL;
+ _mtspr( M8xx_DC_CST, r1 );
+ _isync;
+ r1 = M8xx_CACHE_CMD_INVALIDATE; /* invalidate all */
+ _mtspr( M8xx_DC_CST, r1 );
+ _isync;
+
+ /*
+ * Initialize the Internal Memory Map Register (IMMR)
+ *
+ * Use the value in MBXA/PG2, which is also the value that EPPC-Bug
+ * programmed into our boards. The alternative is the value in
+ * MBXA/PG1: 0xFFA00000. This value might well depend on the revision
+ * of the firmware.
+ *
+ * THIS VALUE IS ALSO DECLARED IN THE linkcmds FILE and mmutlbtab.c!
+ */
+ r1 = 0xFA200000;
+ _mtspr( M8xx_IMMR, r1 );
+
+ /*
+ * Initialize the SIU Module Configuration Register (SIUMCR)
+ * m8xx.siumcr = 0x00602900, the default MBX and firmware value.
+ */
+ m8xx.siumcr = M8xx_SIUMCR_EARP0 | M8xx_SIUMCR_DBGC3 | M8xx_SIUMCR_DBPC0 |
+ M8xx_SIUMCR_DPC | M8xx_SIUMCR_MLRC2 | M8xx_SIUMCR_SEME;
+
+ /*
+ * Initialize the System Protection Control Register (SYPCR).
+ * The SYPCR can only be written once after Reset.
+ * - Enable bus monitor
+ * - Disable software watchdog timer
+ * m8xx.sypcr = 0xFFFFFF88, the default MBX and firmware value.
+ */
+ m8xx.sypcr = M8xx_SYPCR_SWTC(0xFFFF) | M8xx_SYPCR_BMT(0xFF) |
+ M8xx_SYPCR_BME | M8xx_SYPCR_SWF;
+
+ /* Initialize the SIU Interrupt Edge Level Mask Register (SIEL) */
+ m8xx.siel = 0xAAAA0000; /* Default MBX and firmware value. */
+
+ /* Initialize the Transfer Error Status Register (TESR) */
+ m8xx.tesr = 0xFFFFFFFF; /* Default firmware value. */
+
+ /* Initialize the SDMA Configuration Register (SDCR) */
+ m8xx.sdcr = 0x00000001; /* Default firmware value. */
+
+ /*
+ * Initialize the Timebase Status and Control Register (TBSCR)
+ * m8xx.tbscr = 0x00C3, default MBX and firmware value.
+ */
+ m8xx.tbscrk = M8xx_UNLOCK_KEY; /* unlock TBSCR */
+ m8xx.tbscr = M8xx_TBSCR_REFA | M8xx_TBSCR_REFB |
+ M8xx_TBSCR_TBF | M8xx_TBSCR_TBE;
+
+ /* Initialize the Real-Time Clock Status and Control Register (RTCSC) */
+ m8xx.rtcsk = M8xx_UNLOCK_KEY; /* unlock RTCSC */
+ m8xx.rtcsc = 0x00C3; /* Default MBX and firmware value. */
+
+ /* Unlock other Real-Time Clock registers */
+ m8xx.rtck = M8xx_UNLOCK_KEY; /* unlock RTC */
+ m8xx.rtseck = M8xx_UNLOCK_KEY; /* unlock RTSEC */
+ m8xx.rtcalk = M8xx_UNLOCK_KEY; /* unlock RTCAL */
+
+ /* Initialize the Periodic Interrupt Status and Control Register (PISCR) */
+ m8xx.piscrk = M8xx_UNLOCK_KEY; /* unlock PISCR */
+ m8xx.piscr = 0x0083; /* Default MBX and firmware value. */
+
+ /* Initialize the System Clock and Reset Control Register (SCCR)
+ * Set the clock sources and division factors:
+ * Timebase Source is GCLK2 / 16
+ * Real-Time Clock Select is EXTCLK (4.192MHz)
+ * Real-Time Clock Divide is /4
+ */
+ m8xx.sccrk = M8xx_UNLOCK_KEY; /* unlock SCCR */
+ m8xx.sccr = 0x02800000; /* for MBX860/MBX821 */
+
+ /* Initialize the PLL, Low-Power, and Reset Control Register (PLPRCR) */
+ /* - set the clock speed and set normal power mode */
+ m8xx.plprck = M8xx_UNLOCK_KEY; /* unlock PLPRCR */
+#if ( defined(mbx821_001) || defined(mbx821_001b) || defined(mbx860_001b) )
+ m8xx.plprcr = 0x5F500000;
+#else
+ m8xx.plprcr = 0x4C400000;
+#endif
+ /* Unlock the timebase and decrementer registers. */
+ m8xx.tbk = M8xx_UNLOCK_KEY;
+
+ /*
+ * Initialize decrementer register to a large value to
+ * guarantee that a decrementer interrupt will not be
+ * generated before the kernel is fully initialized.
+ */
+ r1 = 0x7FFFFFFF;
+ _mtspr( M8xx_DEC, r1 );
+
+ /* Initialize the timebase register (TB is 64 bits) */
+ r1 = 0x00000000;
+ _mtspr( M8xx_TBU_WR, r1 );
+ _mtspr( M8xx_TBL_WR, r1 );
+
+ /*
+ * Memory Controller Initialization
+ */
+
+ /*
+ * User Programmable Machine A (UPMA) Initialization
+ *
+ * If this initialization code is running from DRAM, it is very
+ * dangerous to change the value of any UPMA Ram array word from
+ * what the firmware (EPPCBug) initialized it to. Thus we don't
+ * initialize UPMA if EPPCBUG_VECTORS is defined; we assume EPPCBug
+ * has done the appropriate initialization.
+ *
+ * An exception to our rule, is that, for the older MBX boards
+ * (those without the "B" suffix, e.g. MBX821-001 and MBX860-002),
+ * we do re-initialize the burst-read and burst-write values with
+ * values that are more efficient. Also, in the MBX821 case,
+ * the burst-write original values set by EPPCBug do not work!
+ * This change can be done safely because the caches have not yet
+ * been activated.
+ *
+ * The RAM array of UPMA is initialized by writing to each of
+ * its 64 32-bit RAM locations.
+ * Note: UPM register initialization should occur before
+ * initialization of the corresponding BRx and ORx registers.
+ */
+#if ( !defined(EPPCBUG_VECTORS) )
+ for( i = 0; i < 64; ++i ) {
+ m8xx.mdr = upmaTable[i];
+ m8xx.mcr = M8xx_MEMC_MCR_WRITE | M8xx_MEMC_MCR_UPMA | M8xx_MEMC_MCR_MAD(i);
+ }
+#elif ( defined(mbx860_001) || \
+ defined(mbx860_002) || \
+ defined(mbx860_003) || \
+ defined(mbx860_004) || \
+ defined(mbx860_005) || \
+ defined(mbx821_001) || \
+ defined(mbx821_002) || \
+ defined(mbx821_003) || \
+ defined(mbx821_004) || \
+ defined(mbx821_005) )
+ /* Replace the burst-read and burst-write values with better ones. */
+ /* burst-read values */
+ for( i = 8; i < 24; ++i ) {
+ m8xx.mdr = upmaTable[i];
+ m8xx.mcr = M8xx_MEMC_MCR_WRITE | M8xx_MEMC_MCR_UPMA | M8xx_MEMC_MCR_MAD(i);
+ }
+ /* burst-write values */
+ for( i = 32; i < 48; ++i ) {
+ m8xx.mdr = upmaTable[i];
+ m8xx.mcr = M8xx_MEMC_MCR_WRITE | M8xx_MEMC_MCR_UPMA | M8xx_MEMC_MCR_MAD(i);
+ }
+#endif
+
+#if ( !defined(EPPCBUG_VECTORS) )
+ /*
+ * Initialize the memory periodic timer.
+ * Memory Periodic Timer Prescaler Register (MPTPR: 16-bit register)
+ * m8xx.mptpr = 0x0200;
+ */
+ m8xx.mptpr = M8xx_MPTPR_PTP(0x2);
+
+ /*
+ * Initialize the Machine A Mode Register (MAMR)
+ *
+ * ASSUMES THAT DIMMs ARE NOT INSTALLED!
+ *
+ * Without DIMMs:
+ * m8xx.mamr = 0x13821000 (40 MHz) or 0x18821000 (50 MHz).
+ *
+ * With DIMMs:
+ * m8xx.mamr = 0x06821000 (40 MHz) or 0x08821000 (50 MHz).
+ */
+#if ( defined(mbx821_001) || defined(mbx821_001b) || defined(mbx860_001b) )
+ m8xx.mamr = M8xx_MEMC_MMR_PTP(0x18) | M8xx_MEMC_MMR_PTE |
+ M8xx_MEMC_MMR_DSP(0x1) | M8xx_MEMC_MMR_G0CL(0) | M8xx_MEMC_MMR_UPWAIT;
+#else
+ m8xx.mamr = M8xx_MEMC_MMR_PTP(0x13) | M8xx_MEMC_MMR_PTE |
+ M8xx_MEMC_MMR_DSP(0x1) | M8xx_MEMC_MMR_G0CL(0) | M8xx_MEMC_MMR_UPWAIT;
+#endif
+#endif /* ! defined(EPPCBUG_VECTORS) */
+
+ /*
+ * Initialize the Base and Option Registers (BR0-BR7 and OR0-OR7)
+ * Note: For all chip selects, ORx should be programmed before BRx,
+ * except when programming the boot chip select (CS0) after hardware
+ * reset, in which case, BR0 should be programmed before OR0.
+ *
+ * MPC860/MPX821 Memory Map Summary:
+ * S-ADDR E-ADDR CS PS PE WP MS BI V DESCRIPTION
+ * FE000000 FE7FFFFF 0 32 N N GPCM Y Y Soldered FLASH Memory
+ * 00000000 00zFFFFF 1 32 N N UPMA N Y Local DRAM Memory
+ * 00X00000 0XXXXXXX 2 0 N N UPMA N N DIMM Memory - Bank #0
+ * 00X00000 0XXXXXXX 3 0 N N UPMA N N DIMM Memory - Bank #1
+ * FA000000 FA1FFFFF 4 8 N N GPCM Y Y NVRAM & BCSR
+ * 80000000 DFFFFFFF 5 32 N N GPCM Y Y PCI/ISA I/O & Memory
+ * FA210000 FA21FFFF 6 32 N N GPCM Y Y QSpan Registers
+ * FC000000 FC7FFFFF 7 8 N N GPCM Y Y Socketed FLASH Memory
+ *
+ * z = 3 for 4MB installed on the motherboard, z = F for 16M
+ *
+ * NOTE: The devices selected by CS0 and CS7 can be selected with jumper J4.
+ * This table assumes that the 32-bit soldered flash device is the boot ROM.
+ */
+
+ /*
+ * CS0 : Soldered (32-bit) Flash Memory at 0xFE000000
+ *
+ * CHANGE THIS CODE IF YOU CHANGE JUMPER J4 FROM ITS FACTORY DEFAULT SETTING!
+ * (or better yet, don't reprogram BR0 and OR0; just program BR7 and OR7 to
+ * access whatever flash device is not selected during hard reset.)
+ *
+ * MBXA/PG2 appears to lie in note 14 for table 2-4. The manual states that
+ * "EPPCBUG configures the reset flash device at the lower address, and the
+ * nonreset flash device at the higher address." If we take reset flash device
+ * to mean the boot flash memory, then the statement must mean that BR0 must
+ * point to the device at the lower address, i.e. 0xFC000000, while BR7 must
+ * point to the device at the highest address, i.e. 0xFE000000.
+ *
+ * THIS IS NOT THE CASE!
+ *
+ * The boot flash is always configured to start at 0xFE000000, and the other
+ * one to start at 0xFC000000. Changing jumper J4 only changes the width of
+ * the memory ports into these two region.
+ *
+ * BR0 = 0xFE000001
+ * Base addr [0-16] 0b11111110000000000 = 0xFE000000
+ * Address type [17-19] 0b000
+ * Port size [20-21] 0b00 = 32 bits
+ * Parity enable [22] 0b0 = disabled
+ * Write protect [23] 0b0 = r/w
+ * Machine select [24-25] 0b00 = GPCM
+ * Reserved [26-30] 0b00000
+ * Valid Bit [31] 0b1 = this bank is valid
+ * OR0 = 0xFF800930 @ 40 MHz, 0xFF800940 @ 50 MHz
+ * Address mask [0-16] 0b11111111100000000 = 0xFF800000
+ * Addr type mask [17-19] 0b000 = no address-type protection
+ * CS negation time [20] 0b1
+ * ACS [21-22] 0b00 = CS output at same time as address lines
+ * Burst inhibit [23] 0b1 = bank does not support burst accesses
+ * Cycle length [24-27] 0b0011/0b0100 = 3/4 clock cycle wait states
+ * SETA [28] 0b0 = TA generated internally
+ * Timing relaxed [29] 0b0 = not relaxed
+ * Extended hold time [30] 0b0 = not extended
+ * Reserved [31] 0b0
+ *
+ * m8xx.memc[0]._or = 0xFF800930 (40 MHz)
+ * m8xx.memc[0]._or = 0xFF800940 (50 MHz)
+ * m8xx.memc[0]._br = 0xFE000001
+ */
+#if ( defined(mbx821_001) || defined(mbx821_001b) || defined(mbx860_001b) )
+ m8xx.memc[0]._or = M8xx_MEMC_OR_8M | M8xx_MEMC_OR_ATM(0) | M8xx_MEMC_OR_CSNT |
+ M8xx_MEMC_OR_ACS_NORM | M8xx_MEMC_OR_BI | M8xx_MEMC_OR_SCY(4);
+#else
+ m8xx.memc[0]._or = M8xx_MEMC_OR_8M | M8xx_MEMC_OR_ATM(0) | M8xx_MEMC_OR_CSNT |
+ M8xx_MEMC_OR_ACS_NORM | M8xx_MEMC_OR_BI | M8xx_MEMC_OR_SCY(3);
+#endif
+ m8xx.memc[0]._br = M8xx_BR_BA(0xFE000000) | M8xx_BR_AT(0) | M8xx_BR_PS32 |
+ M8xx_BR_MS_GPCM | M8xx_MEMC_BR_V;
+
+ /*
+ * CS1 : Local DRAM Memory at 0x00000000
+ * m8xx.memc[1]._or = 0xFFC00400;
+ * m8xx.memc[1]._br = 0x00000081;
+ */
+ m8xx.memc[1]._or = M8xx_MEMC_OR_4M | M8xx_MEMC_OR_ATM(0) |
+ M8xx_MEMC_OR_ACS_QRTR | M8xx_MEMC_OR_SCY(0);
+ m8xx.memc[1]._br = M8xx_BR_BA(0x00000000) | M8xx_BR_AT(0) | M8xx_BR_PS32 |
+ M8xx_BR_MS_UPMA | M8xx_MEMC_BR_V;
+
+ /*
+ * CS2 : DIMM Memory - Bank #0, not present
+ * m8xx.memc[2]._or = 0x00000400;
+ * m8xx.memc[2]._br = 0x00000080;
+ */
+ m8xx.memc[2]._or = M8xx_MEMC_OR_ATM(0) |
+ M8xx_MEMC_OR_ACS_QRTR | M8xx_MEMC_OR_SCY(0);
+ m8xx.memc[2]._br = M8xx_BR_AT(0) | M8xx_BR_PS32 |
+ M8xx_BR_MS_UPMA; /* ! M8xx_MEMC_BR_V */
+
+ /*
+ * CS3 : DIMM Memory - Bank #1, not present
+ * m8xx.memc[3]._or = 0x00000400;
+ * m8xx.memc[3]._br = 0x00000080;
+ */
+ m8xx.memc[3]._or = M8xx_MEMC_OR_ATM(0) |
+ M8xx_MEMC_OR_ACS_QRTR | M8xx_MEMC_OR_SCY(0);
+ m8xx.memc[3]._br = M8xx_BR_AT(0) | M8xx_BR_PS32 |
+ M8xx_BR_MS_UPMA; /* ! M8xx_MEMC_BR_V */
+
+ /*
+ * CS4 : Battery-Backed SRAM at 0xFA000000
+ * m8xx.memc[4]._or = 0xFFE00920@ 40 MHz, 0xFFE00930 @ 50 MHz
+ * m8xx.memc[4]._br = 0xFA000401;
+ */
+#if ( defined(mbx821_001) || defined(mbx821_001b) || defined(mbx860_001b) )
+ m8xx.memc[4]._or = M8xx_MEMC_OR_2M | M8xx_MEMC_OR_ATM(0) | M8xx_MEMC_OR_CSNT |
+ M8xx_MEMC_OR_ACS_NORM | M8xx_MEMC_OR_BI | M8xx_MEMC_OR_SCY(3);
+#else
+ m8xx.memc[4]._or = M8xx_MEMC_OR_2M | M8xx_MEMC_OR_ATM(0) | M8xx_MEMC_OR_CSNT |
+ M8xx_MEMC_OR_ACS_NORM | M8xx_MEMC_OR_BI | M8xx_MEMC_OR_SCY(2);
+#endif
+ m8xx.memc[4]._br = M8xx_BR_BA(0xFA000000) | M8xx_BR_AT(0) | M8xx_BR_PS8 |
+ M8xx_BR_MS_GPCM | M8xx_MEMC_BR_V;
+
+ /*
+ * CS5 : PCI I/O and Memory at 0x80000000
+ * m8xx.memc[5]._or = 0xA0000108;
+ * m8xx.memc[5]._br = 0x80000001;
+ */
+ m8xx.memc[5]._or = 0xA0000000 | M8xx_MEMC_OR_ATM(0) | M8xx_MEMC_OR_ACS_NORM |
+ M8xx_MEMC_OR_BI | M8xx_MEMC_OR_SCY(0) | M8xx_MEMC_OR_SETA;
+ m8xx.memc[5]._br = M8xx_BR_BA(0x80000000) | M8xx_BR_AT(0) | M8xx_BR_PS32 |
+ M8xx_BR_MS_GPCM | M8xx_MEMC_BR_V;
+
+ /*
+ * CS6 : QSPAN Registers at 0xFA210000
+ * m8xx.memc[6]._or = 0xFFFF0108;
+ * m8xx.memc[6]._br = 0xFA210001;
+ */
+ m8xx.memc[6]._or = M8xx_MEMC_OR_64K | M8xx_MEMC_OR_ATM(0) | M8xx_MEMC_OR_ACS_NORM |
+ M8xx_MEMC_OR_BI | M8xx_MEMC_OR_SCY(0) | M8xx_MEMC_OR_SETA;
+ m8xx.memc[6]._br = M8xx_BR_BA(0xFA210000) | M8xx_BR_AT(0) | M8xx_BR_PS32 |
+ M8xx_BR_MS_GPCM | M8xx_MEMC_BR_V;
+
+ /*
+ * CS7 : Socketed (8-bit) Flash at 0xFC000000
+ * m8xx.memc[7]._or = 0xFF800930 @ 40 MHz, 0xFF800940 @ 50 MHz
+ * m8xx.memc[7]._br = 0xFC000401;
+ */
+#if ( defined(mbx821_001) || defined(mbx821_001b) || defined(mbx860_001b) )
+ m8xx.memc[7]._or = M8xx_MEMC_OR_8M | M8xx_MEMC_OR_ATM(0) | M8xx_MEMC_OR_CSNT |
+ M8xx_MEMC_OR_ACS_NORM | M8xx_MEMC_OR_BI | M8xx_MEMC_OR_SCY(4);
+#else
+ m8xx.memc[7]._or = M8xx_MEMC_OR_8M | M8xx_MEMC_OR_ATM(0) | M8xx_MEMC_OR_CSNT |
+ M8xx_MEMC_OR_ACS_NORM | M8xx_MEMC_OR_BI | M8xx_MEMC_OR_SCY(3);
+#endif
+ m8xx.memc[7]._br = M8xx_BR_BA(0xFC000000) | M8xx_BR_AT(0) | M8xx_BR_PS8 |
+ M8xx_BR_MS_GPCM | M8xx_MEMC_BR_V;
+}
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/startup/linkcmds b/c/src/lib/libbsp/powerpc/mbx8xx/startup/linkcmds
new file mode 100644
index 0000000000..565e7f175b
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/startup/linkcmds
@@ -0,0 +1,259 @@
+/*
+ * This file contains directives for the GNU linker that are specific
+ * to the MBX860-2 board.
+ *
+ * $Id$
+ */
+
+OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc")
+OUTPUT_ARCH(powerpc)
+ENTRY(start)
+
+/*
+ * Declare some sizes.
+ * XXX: The assignment of ". += XyzSize;" fails in older gld's if the
+ * number used there is not constant. If this happens to you, edit
+ * the lines marked XXX below to use a constant value.
+ */
+HeapSize = DEFINED(HeapSize) ? HeapSize : 0x100000; /* 1M Heap */
+StackSize = DEFINED(StackSize) ? StackSize : 0x1000;
+
+MEMORY
+ {
+ ram : org = 0x0, l = 4M
+ nvram : org = 0xfa000000, l = 32K
+ dpram : org = 0xfa200000, l = 16K
+ flash : org = 0xfc000000, l = 2M
+ immr : org = 0xfa200000, l = 16K
+ }
+
+
+SECTIONS
+{
+ /*
+ * If the vectors are specified statically rather than created at run time,
+ * accumulate them starting at VMA 0x0.
+ */
+ .vectors :
+ {
+ *(.vectors)
+ } >ram
+
+ /*
+ * The stack will live in this area - between the vectors and
+ * the text section.
+ */
+
+ .text 0x10000:
+ {
+ /* Read-only sections, merged into text segment: */
+
+ text.start = .;
+
+ /* Entry point is the .entry section */
+ *(.entry)
+ *(.entry2)
+
+ /* Actual code */
+ *(.text)
+ *(.text.*)
+
+ /* C++ constructors/destructors */
+ *(.gnu.linkonce.t*)
+
+ /* Initialization and finalization code.
+ *
+ * Various files can provide initialization and finalization functions.
+ * The bodies of these functions are in .init and .fini sections. We
+ * accumulate the bodies here, and prepend function prologues from
+ * ecrti.o and function epilogues from ecrtn.o. ecrti.o must be linked
+ * first; ecrtn.o must be linked last. Because these are wildcards, it
+ * doesn't matter if the user does not actually link against ecrti.o and
+ * ecrtn.o; the linker won't look for a file to match a wildcard. The
+ * wildcard also means that it doesn't matter which directory ecrti.o
+ * and ecrtn.o are in.
+ */
+ PROVIDE (_init = .);
+ *ecrti.o(.init)
+ *(.init)
+ *ecrtn.o(.init)
+
+ PROVIDE (_fini = .);
+ *ecrti.o(.fini)
+ *(.fini)
+ *ecrtn.o(.init)
+
+ /*
+ * C++ constructors and destructors for static objects.
+ * PowerPC EABI does not use crtstuff yet, so we build "old-style"
+ * constructor and destructor lists that begin with the list lenght
+ * end terminate with a NULL entry.
+ */
+
+ PROVIDE (__CTOR_LIST__ = .);
+ /* LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) */
+ *crtbegin.o(.ctors)
+ *(.ctors)
+ *crtend.o(.ctors)
+ LONG(0)
+ PROVIDE (__CTOR_END__ = .);
+
+ PROVIDE (__DTOR_LIST__ = .);
+ /* LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) */
+ *crtbegin.o(.dtors)
+ *(.dtors)
+ *crtend.o(.dtors)
+ LONG(0)
+ PROVIDE (__DTOR_END__ = .);
+
+ /* Exception frame info */
+ *(.eh_frame)
+
+ /* Miscellaneous read-only data */
+ _rodata_start = . ;
+ *(.gnu.linkonce.r*)
+ *(.lit)
+ *(.shdata)
+ *(.rodata)
+ *(.rodata1)
+ *(.descriptors)
+ *(rom_ver)
+ _erodata = .;
+
+
+ /* Various possible names for the end of the .text section */
+ etext = ALIGN(0x10);
+ _etext = .;
+ _endtext = .;
+ text.end = .;
+ PROVIDE (etext = .);
+ PROVIDE (__etext = .);
+ } > ram
+
+ /* R/W Data */
+ .data :
+ {
+ data_start = .;
+
+ *(.data)
+ *(.data.*)
+ *(.data1)
+
+ PROVIDE (__SDATA_START__ = .);
+ *(.sdata)
+ *(.gnu.linkonce.d*)
+ PROVIDE (__SDATA_END__ = .);
+
+ PROVIDE (__EXCEPT_START__ = .);
+ *(.gcc_except_table)
+ PROVIDE (__EXCEPT_END__ = .);
+
+ PROVIDE(__GOT_START__ = .);
+ *(.got.plt)
+ *(.got)
+ PROVIDE(__GOT_END__ = .);
+
+ *(.got1)
+
+ PROVIDE (__GOT2_START__ = .);
+ PROVIDE (_GOT2_START_ = .);
+ *(.got2)
+ PROVIDE (__GOT2_END__ = .);
+ PROVIDE (_GOT2_END_ = .);
+
+ PROVIDE (__FIXUP_START__ = .);
+ PROVIDE (_FIXUP_START_ = .);
+ *(.fixup)
+ PROVIDE (_FIXUP_END_ = .);
+ PROVIDE (__FIXUP_END__ = .);
+
+ /* We want the small data sections together, so single-instruction offsets
+ * can access them all.
+ */
+ PROVIDE (__SDATA2_START__ = .);
+ *(.sdata2)
+ PROVIDE (__SDATA2_END__ = .);
+ } > ram
+
+
+ .bss :
+ {
+ PROVIDE (__SBSS_START__ = .);
+
+ PROVIDE (__SBSS2_START__ = .);
+ *(.sbss2)
+ PROVIDE (__SBSS2_END__ = .);
+
+ bss.start = .;
+ *(.bss)
+ *(.sbss)
+ *(COMMON)
+ . = ALIGN(4);
+ bss.end = .;
+
+ PROVIDE (__SBSS_END__ = .);
+
+ } > ram
+
+ bss.size = bss.end - bss.start;
+ text.size = text.end - text.start;
+ PROVIDE(_end = bss.end);
+
+ _HeapStart = .;
+ __HeapStart = .;
+ . += HeapSize; /* XXX -- Old gld can't handle this */
+ /* . += 0x80000; */ /* HeapSize for old gld */
+ _HeapEnd = .;
+ __HeapEnd = .;
+ clear_end = .;
+
+ _WorkspaceBase = .;
+ __WorkspaceBase = .;
+
+ dpram :
+ {
+ m8xx = .;
+ _m8xx = .;
+ . += (16 * 1024);
+ } >immr
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /* These must appear regardless of . */
+}
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/startup/mmutlbtab.c b/c/src/lib/libbsp/powerpc/mbx8xx/startup/mmutlbtab.c
new file mode 100644
index 0000000000..45c22d8951
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/startup/mmutlbtab.c
@@ -0,0 +1,132 @@
+/*
+ * mmutlbtab.c
+ *
+ * This file defines the MMU_TLB_table for the MBX8xx.
+ *
+ * Copyright (c) 1999, National Research Council of Canada
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ */
+
+#include <bsp.h>
+#include <mpc8xx/mmu.h>
+
+/*
+ * This MMU_TLB_table is used to statically initialize the Table Lookaside
+ * Buffers in the MMU of the MBX8xx board.
+ *
+ * We initialize the entries in both the instruction and data TLBs
+ * with the same values - a few bits relevant to the data TLB are unused
+ * in the instruction TLB.
+ *
+ * An Effective Page Number (EPN), Tablewalk Control Register (TWC) and
+ * Real Page Number (RPN) value are supplied in the table for each TLB entry.
+ *
+ * The instruction and data TLBs each can hold 32 entries, so _TLB_Table must
+ * not have more than 32 lines in it!
+ *
+ * We set up the virtual memory map so that virtual address of a
+ * location is equal to its real address.
+ */
+MMU_TLB_table_t MMU_TLB_table[] = {
+ /*
+ * DRAM: CS1, Start address 0x00000000, 4M,
+ * ASID=0x0, APG=0x0, not guarded memory, copyback data cache policy,
+ * R/W,X for all, no ASID comparison, not cache-inhibited.
+ * Last 512K block is cache-inhibited, but not guarded for use by EPPCBug.
+ * EPN TWC RPN
+ */
+ { 0x00000200, 0x05, 0x000009FD }, /* DRAM - PS=512K */
+ { 0x00080200, 0x05, 0x000809FD }, /* DRAM - PS=512K */
+ { 0x00100200, 0x05, 0x001009FD }, /* DRAM - PS=512K */
+ { 0x00180200, 0x05, 0x001809FD }, /* DRAM - PS=512K */
+ { 0x00200200, 0x05, 0x002009FD }, /* DRAM - PS=512K */
+ { 0x00280200, 0x05, 0x002809FD }, /* DRAM - PS=512K */
+ { 0x00300200, 0x05, 0x003009FD }, /* DRAM - PS=512K */
+ { 0x00380200, 0x05, 0x003809FF }, /* DRAM - PS=512K, cache-inhibited */
+ /*
+ *
+ * NVRAM: CS4, Start address 0xFA000000, 32K,
+ * ASID=0x0, APG=0x0, not guarded memory, copyback data cache policy,
+ * R/W,X for all, no ASID comparison, cache-inhibited.
+ *
+ * EPN TWC RPN
+ */
+ { 0xFA000200, 0x01, 0xFA0009FF }, /* NVRAM - PS=16K */
+ { 0xFA004200, 0x01, 0xFA0049FF }, /* NVRAM - PS=16K */
+ /*
+ *
+ * Board Control/Status Register #1/#2: CS4, Start address 0xFA100000, (4 x 8 bits?)
+ * ASID=0x0, APG=0x0, guarded memory, copyback data cache policy,
+ * R/W,X for all, no ASID comparison, cache-inhibited.
+ * EPN TWC RPN
+ */
+ { 0xFA100200, 0x11, 0xFA1009F7 }, /* BCSR - PS=4K */
+ /*
+ *
+ * (IMMR-SPRs) Dual Port RAM: Start address 0xFA200000, 16K,
+ * ASID=0x0, APG=0x0, guarded memory, copyback data cache policy,
+ * R/W,X for all, no ASID comparison, cache-inhibited.
+ *
+ * Note: We use the value in MBXA/PG2, which is also the value that
+ * EPPC-Bug programmed into our boards. The alternative is the value
+ * in MBXA/PG1: 0xFFA00000. This value might well depend on the revision
+ * of the firmware.
+ * EPN TWC RPN
+ */
+ { 0xFA200200, 0x11, 0xFA2009FF }, /* IMMR - PS=16K */
+ /*
+ *
+ * Flash: CS0, Start address 0xFE000000, 4M, (BootROM-EPPCBug)
+ * ASID=0x0, APG=0x0, not guarded memory,
+ * R/O,X for all, no ASID comparison, not cache-inhibited.
+ * EPN TWC RPN
+ */
+ { 0xFE000200, 0x05, 0xFE000CFD }, /* Flash - PS=512K */
+ { 0xFE080200, 0x05, 0xFE080CFD }, /* Flash - PS=512K */
+ { 0xFE100200, 0x05, 0xFE100CFD }, /* Flash - PS=512K */
+ { 0xFE180200, 0x05, 0xFE180CFD }, /* Flash - PS=512K */
+ { 0xFE200200, 0x05, 0xFE200CFD }, /* Flash - PS=512K */
+ { 0xFE280200, 0x05, 0xFE280CFD }, /* Flash - PS=512K */
+ { 0xFE300200, 0x05, 0xFE300CFD }, /* Flash - PS=512K */
+ { 0xFE380200, 0x05, 0xFE380CFD }, /* Flash - PS=512K */
+ /*
+ * BootROM: CS7, Start address 0xFC000000, 4M?, (socketed FLASH)
+ * ASID=0x0, APG=0x0, not guarded memory,
+ * R/O,X for all, no ASID comparison, not cache-inhibited.
+ * EPN TWC RPN
+ */
+ { 0xFC000200, 0x05, 0xFC000CFD }, /* BootROM - PS=512K */
+ /*
+ *
+ * PCI/ISA I/O Space: CS5, Start address 0x80000000, 512M?
+ * ASID=0x0, APG=0x0, guarded memory,
+ * R/W,X for all, no ASID comparison, cache-inhibited.
+ * EPN TWC RPN
+ */
+ { 0x80000200, 0x1D, 0x800009FF }, /* PCI I/O - PS=8M */
+ /*
+ *
+ * PCI/ISA Memory Space: CS5, Start address 0xC0000000, 512M?
+ * ASID=0x0, APG=0x0, guarded memory,
+ * R/W,X for all, no ASID comparison, cache-inhibited.
+ * EPN TWC RPN
+ */
+ { 0xC0000200, 0x1D, 0xC00009FF }, /* PCI Memory - PS=8M */
+ /*
+ *
+ * PCI Bridge/QSPAN Registers: CS6, Start address 0xFA210000, 4K
+ * ASID=0x0, APG=0x0, guarded memory,
+ * R/W,X for all, no ASID comparison, cache-inhibited.
+ * EPN TWC RPN
+ */
+ { 0xFA210200, 0x11, 0xFA2109F7 } /* QSPAN - PS=4K */
+};
+
+/*
+ * MMU_N_TLB_Table_Entries is defined here because the size of the
+ * MMU_TLB_table is only known in this file.
+ */
+int MMU_N_TLB_Table_Entries = ( sizeof(MMU_TLB_table) / sizeof(MMU_TLB_table[0]) );
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/startup/setvec.c b/c/src/lib/libbsp/powerpc/mbx8xx/startup/setvec.c
new file mode 100644
index 0000000000..b32dc8aaec
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/startup/setvec.c
@@ -0,0 +1,44 @@
+/* set_vector
+ *
+ * This routine installs an interrupt vector on the target Board/CPU.
+ * This routine is allowed to be as board dependent as necessary.
+ *
+ * INPUT:
+ * handler - interrupt handler entry point
+ * vector - vector number
+ * type - 0 indicates raw hardware connect
+ * 1 indicates RTEMS interrupt connect
+ *
+ * RETURNS:
+ * address of previous interrupt handler
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <bsp.h>
+
+rtems_isr_entry set_vector( /* returns old vector */
+ rtems_isr_entry handler, /* isr routine */
+ rtems_vector_number vector, /* vector number */
+ int type /* RTEMS or RAW intr */
+)
+{
+ rtems_isr_entry previous_isr;
+
+ if (type) {
+ rtems_interrupt_catch(handler, vector, (rtems_isr_entry *) &previous_isr );
+ } else {
+ /* XXX: install non-RTEMS ISR as "raw" interupt */
+ }
+ return previous_isr;
+}
+
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/startup/start.S b/c/src/lib/libbsp/powerpc/mbx8xx/startup/start.S
new file mode 100644
index 0000000000..c487a58a33
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/startup/start.S
@@ -0,0 +1,383 @@
+/* start.S
+ *
+ * This file contains the entry veneer for RTEMS programs
+ * on the MBX8xx board.
+ * It jumps to the BSP which is responsible for performing
+ * all remaining initialization.
+ *
+ * This file is based on several others:
+ *
+ * (1) start360.s from the gen68360 BSP by
+ * W. Eric Norum (eric@skatter.usask.ca)
+ * with the following copyright and license:
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may in
+ * the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * (2) start.s for the eth_comm port by
+ * Jay Monkman (jmonkman@fracsa.com),
+ * which itself is based on the
+ *
+ * (3) dlentry.s for the Papyrus BSP, written by:
+ * Andrew Bray <andy@i-cubed.co.uk>
+ * with the following copyright and license:
+ *
+ * COPYRIGHT (c) 1995 by i-cubed ltd.
+ *
+ * (4) start860.S for the MBX821/MBX860, written by:
+ * Darlene A. Stewart <darlene.stewart@iit.nrc.ca>
+ * Copyright (c) 1999, National Research Council of Canada
+ *
+ * To anyone who acknowledges that this file is provided "AS IS"
+ * without any express or implied warranty:
+ * permission to use, copy, modify, and distribute this file
+ * for any purpose is hereby granted without fee, provided that
+ * the above copyright notice and this notice appears in all
+ * copies, and that the name of i-cubed limited not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * i-cubed limited makes no representations about the suitability
+ * of this software for any purpose.
+ *
+ * Modifications (for MBX8xx) of respective RTEMS files:
+ * Copyright (c) 1999, National Research Council of Canada
+ */
+
+#include "asm.h"
+
+/*
+ * The initial stack is set to run BELOW the code base address.
+ * (between the vectors and text sections)
+ *
+ * All the entry veneer has to do is to clear the BSS.
+ */
+
+/*
+ * GDB likes to have debugging information for the entry veneer.
+ * Play compiler and provide some DWARF information.
+ *
+ * CHANGE TO SUIT YOUR SETUP!
+ */
+
+ .section .entry,"ax",@progbits
+.L_text_b:
+.L_LC1:
+ .previous
+
+.section .debug_sfnames
+.L_sfnames_b:
+ .byte "rtems/c/src/lib/libbsp/powerpc/mbx8xx/startup/"
+ .byte 0
+.L_F0:
+ .byte "start.S"
+ .byte 0
+ .previous
+
+.section .line
+.L_line_b:
+ .4byte .L_line_e-.L_line_b
+ .4byte .L_text_b
+.L_LE1:
+.L_line_last:
+ .4byte 0x0
+ .2byte 0xffff
+ .4byte .L_text_e-.L_text_b
+.L_line_e:
+ .previous
+
+.section .debug_srcinfo
+.L_srcinfo_b:
+ .4byte .L_line_b
+ .4byte .L_sfnames_b
+ .4byte .L_text_b
+ .4byte .L_text_e
+ .4byte 0xffffffff
+ .4byte .L_LE1-.L_line_b
+ .4byte .L_F0-.L_sfnames_b
+ .4byte .L_line_last-.L_line_b
+ .4byte 0xffffffff
+ .previous
+
+.section .debug_pubnames
+ .4byte .L_debug_b
+ .4byte .L_P0
+ .byte "start"
+ .byte 0
+ .4byte 0x0
+ .byte 0
+ .previous
+
+.section .debug_aranges
+ .4byte .L_debug_b
+ .4byte .L_text_b
+ .4byte .L_text_e-.L_text_b
+ .4byte 0
+ .4byte 0
+ .4byte 0
+ .4byte 0
+ .4byte 0
+ .4byte 0
+ .4byte 0x0
+ .4byte 0x0
+ .previous
+
+.section .debug
+.L_debug_b:
+.L_D1:
+ .4byte .L_D1_e-.L_D1
+ .2byte 0x11 /* TAG_compile_unit */
+ .2byte 0x12 /* AT_sibling */
+ .4byte .L_D2
+ .2byte 0x38 /* AT_name */
+ .byte "start.S"
+ .byte 0
+ .2byte 0x258 /* AT_producer */
+ .byte "GAS 2.5.2"
+ .byte 0
+ .2byte 0x111 /* AT_low_pc */
+ .4byte .L_text_b
+ .2byte 0x121 /* AT_high_pc */
+ .4byte .L_text_e
+ .2byte 0x106 /* AT_stmt_list */
+ .4byte .L_line_b
+ .2byte 0x1b8 /* AT_comp_dir */
+ .byte "rtems/c/src/lib/libbsp/powerpc/mbx8xx/startup/"
+ .byte 0
+ .2byte 0x8006 /* AT_sf_names */
+ .4byte .L_sfnames_b
+ .2byte 0x8016 /* AT_src_info */
+ .4byte .L_srcinfo_b
+.L_D1_e:
+.L_P0:
+.L_D3:
+ .4byte .L_D3_e-.L_D3
+ .2byte 0x6 /* TAG_global_subroutine */
+ .2byte 0x12 /* AT_sibling */
+ .4byte .L_D4
+ .2byte 0x38 /* AT_name */
+ .byte "start"
+ .byte 0
+ .2byte 0x278 /* AT_prototyped */
+ .byte 0
+ .2byte 0x111 /* AT_low_pc */
+ .4byte .L_text_b
+ .2byte 0x121 /* AT_high_pc */
+ .4byte .L_text_e
+ .2byte 0x8041 /* AT_body_begin */
+ .4byte .L_text_b
+ .2byte 0x8051 /* AT_body_end */
+ .4byte .L_text_e
+.L_D3_e:
+
+.L_D4:
+ .4byte .L_D4_e-.L_D4
+ .align 2
+.L_D4_e:
+.L_D2:
+ .previous
+
+/*
+ * Tell C's eabi-ctor's that we have an atexit function,
+ * and that it is to register __do_global_dtors.
+ */
+ EXTERN_PROC(atexit)
+ PUBLIC_VAR(__atexit)
+ .section ".sdata","aw"
+ .align 2
+SYM(__atexit):
+ EXT_PROC_REF(atexit)@fixup
+ .previous
+
+ .section ".fixup","aw"
+ .align 2
+ EXT_SYM_REF(__atexit)
+ .previous
+
+/* That should do it */
+
+/*
+ * Put the entry point in its own section. That way, we can guarantee
+ * to put it first in the .text section in the linker script.
+ */
+ .section .entry
+
+ PUBLIC_VAR (start)
+SYM(start):
+ bl .startup /* or bl .spin */
+base_addr:
+
+/*
+ * Parameters from linker
+ */
+toc_pointer:
+ .long __GOT_START__
+bss_length:
+ .long bss.size
+bss_addr:
+ .long bss.start
+
+PUBLIC_VAR (text_addr)
+text_addr:
+ .long text.start
+
+PUBLIC_VAR (text_length)
+text_length:
+ .long text.size
+
+/*
+ * Spin, if necessary, to acquire control from debugger (CodeWarrior).
+ */
+spin:
+ .long 0x0001
+.spin:
+ lis r3, spin@ha
+ lwz r3, spin@l(r3)
+ cmpwi r3, 0x1
+ beq .spin
+
+/*
+ * Initialization code
+ */
+.startup:
+ /* Get the start address. */
+ mflr r1
+
+ /* Initialize essential registers. */
+ bl initregs
+ nop
+
+ /*
+ * C_setup.
+ */
+
+ /* set toc */
+ lwz r2, toc_pointer-base_addr(r1)
+
+ /* Set up stack pointer = beginning of text section - 56 */
+ addi r1, r1, -56-4
+
+ /* Initialize the memory mapped MPC821 registers (done in C). */
+ EXTERN_PROC (_InitMBX8xx)
+ bl PROC (_InitMBX8xx)
+ nop
+
+ /* Clear the bss section. */
+ bl bssclr
+ nop
+
+ /* clear argc and argv */
+ xor r3, r3, r3
+ xor r4, r4, r4
+
+ EXTERN_PROC (boot_card)
+ bl PROC (boot_card) /* call the first C routine */
+ nop
+
+ /* we should never return from boot_card, but in case we do ... */
+ /* The next instructions are dependent on your runtime environment */
+
+ /* Return to EPPCBug */
+ lis r10, 0x0400 /* Data cache disable */
+ mtspr 568, r10
+ isync
+
+ mtspr 560, r10 /* Instruction cache disable */
+ isync
+
+stop_here:
+ li r10, 0x0F00 /* .RETURN */
+ sc
+
+ b stop_here
+ nop
+
+/*
+ * bssclr - zero out bss
+ */
+bssclr:
+ lis r3, base_addr@ha
+ addi r3, r3, base_addr@l
+ lwz r4, bss_addr-base_addr(r3) /* Start of bss */
+ lwz r5, bss_length-base_addr(r3) /* Length of bss */
+
+ rlwinm. r5,r5,30,0x3FFFFFFF /* form length/4 */
+ beqlr /* no bss - return */
+ mtctr r5 /* set ctr reg */
+
+ li r5,0x0000 /* r5 = 0 */
+clear_bss:
+ stw r5,0(r4) /* store r6 */
+ addi r4,r4,0x4 /* update r4 */
+ bdnz clear_bss /* dec counter and loop */
+
+ blr /* return */
+
+/*
+ * initregs
+ * Initialize the MSR and basic core PowerPC registers
+ *
+ * Register usage:
+ * r0 - scratch
+ */
+initregs:
+ /*
+ * Disable address translation. We should already be running in real space,
+ * so this should be a no-op, i.e. no need to switch instruction stream
+ * addresses from virtual space to real space. Other bits set the processor
+ * for big-endian mode, exceptions vectored to 0x000n_nnnn (vectors are
+ * already in low memory!), no execution tracing, machine check exceptions
+ * enabled, floating-point not available (MPC8xx has none), supervisor
+ * priviledge level, external interrupts disabled, power management
+ * disabled (normal operation mode).
+ */
+ li r0, 0x1000 /* MSR_ME */
+ mtmsr r0 /* Context-synchronizing */
+ isync
+
+ /*
+ * Clear the exception handling registers.
+ * Note SPRG3 is reserved for use by EPPCBug on the MBX8xx.
+ */
+ li r0, 0x0000
+ mtdar r0
+ mtspr sprg0, r0
+ mtspr sprg1, r0
+ mtspr sprg2, r0
+ mtspr srr0, r0
+ mtspr srr1, r0
+
+ mr r6, r0
+ mr r7, r0
+ mr r8, r0
+ mr r9, r0
+ mr r10, r0
+ mr r11, r0
+ mr r12, r0
+ mr r13, r0
+ mr r14, r0
+ mr r15, r0
+ mr r16, r0
+ mr r17, r0
+ mr r18, r0
+ mr r19, r0
+ mr r20, r0
+ mr r21, r0
+ mr r22, r0
+ mr r23, r0
+ mr r24, r0
+ mr r25, r0
+ mr r26, r0
+ mr r27, r0
+ mr r28, r0
+ mr r29, r0
+ mr r30, r0
+ mr r31, r0
+
+ blr /* return */
+
+.L_text_e:
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/times-mbx821 b/c/src/lib/libbsp/powerpc/mbx8xx/times-mbx821
new file mode 100644
index 0000000000..53e6b133a9
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/times-mbx821
@@ -0,0 +1,191 @@
+#
+# Timing Test Suite Results for the MBX821-001
+#
+# $Id$
+#
+
+Board: MBX821
+CPU: MPC821
+Clock Speed: 50 MHz
+Memory Configuration: 4Mb EDO, 60ns DRAM
+Wait States:
+
+Times Reported in: clock ticks
+Timer Source: Timebase register (TMBCLK = (cpu clock speed / 16) = 3.125MHz)
+
+Column A: Data & instruction caches disabled (2000-05-04)
+Column B: Data & instruction caches enabled (UPM/A: new burst r/w values) (2000-05-04)
+
+# DESCRIPTION A B
+== ================================================================= ==== ====
+ 1 rtems_semaphore_create 181 79
+ rtems_semaphore_delete 196 55
+ rtems_semaphore_obtain: available 128 12
+ rtems_semaphore_obtain: not available -- NO_WAIT 128 12
+ rtems_semaphore_release: no waiting tasks 162 16
+
+ 2 rtems_semaphore_obtain: not available -- caller blocks 405 113
+
+ 3 rtems_semaphore_release: task readied -- preempts caller 317 72
+
+ 4 rtems_task_restart: blocked task -- preempts caller 549 156
+ rtems_task_restart: ready task -- preempts caller 539 150
+ rtems_semaphore_release: task readied -- returns to caller 201 25
+ rtems_task_create 585 153
+ rtems_task_start 257 67
+ rtems_task_restart: suspended task -- returns to caller 309 83
+ rtems_task_delete: suspended task 555 118
+ rtems_task_restart: ready task -- returns to caller 317 85
+ rtems_task_restart: blocked task -- returns to caller 374 113
+ rtems_task_delete: blocked task 571 130
+
+ 5 rtems_task_suspend: calling task 314 63
+ rtems_task_resume: task readied -- preempts caller 263 49
+
+ 6 rtems_task_restart: calling task 385 53
+ rtems_task_suspend: returns to caller 132 18
+ rtems_task_resume: task readied -- returns to caller 145 20
+ rtems_task_delete: ready task 574 135
+
+ 7 rtems_task_restart: suspended task -- preempts caller 505 111
+
+ 8 rtems_task_set_priority: obtain current priority 111 11
+ rtems_task_set_priority: returns to caller 207 20
+ rtems_task_mode: obtain current mode 56 6
+ rtems_task_mode: no reschedule 70 8
+ rtems_task_mode: reschedule -- returns to caller 75 32
+ rtems_task_mode: reschedule -- preempts caller 292 97
+ rtems_task_set_note 112 11
+ rtems_task_get_note 113 11
+ rtems_clock_set 250 25
+ rtems_clock_get 6 1
+
+ 9 rtems_message_queue_create 751 320
+ rtems_message_queue_send: no waiting tasks 241 33
+ rtems_message_queue_urgent: no waiting tasks 238 39
+ rtems_message_queue_receive: available 229 29
+ rtems_message_queue_flush: no messages flushed 104 12
+ rtems_message_queue_flush: messages flushed 127 12
+ rtems_message_queue_delete 242 83
+
+10 rtems_message_queue_receive: not available -- NO_WAIT 147 16
+ rtems_message_queue_receive: not available -- caller blocks 416 94
+
+11 rtems_message_queue_send: task readied -- preempts caller 377 82
+
+12 rtems_message_queue_send: task readied -- returns to caller 262 50
+
+13 rtems_message_queue_urgent: task readied -- preempts caller 377 85
+
+14 rtems_message_queue_urgent: task readied -- returns to caller 262 43
+
+15 rtems_event_receive: obtain current events 10 1
+ rtems_event_receive: not available -- NO_WAIT 102 9
+ rtems_event_receive: not available -- caller blocks 346 76
+ rtems_event_send: no task readied 104 10
+ rtems_event_receive: available 105 24
+ rtems_event_send: task readied -- returns to caller 181 26
+
+16 rtems_event_send: task readied -- preempts caller 308 78
+
+17 rtems_task_set_priority: preempts caller 408 76
+
+18 rtems_task_delete: calling task 749 174
+
+19 rtems_signal_catch 75 9
+ rtems_signal_send: returns to caller 120 35
+ rtems_signal_send: signal to self 198 74
+ exit ASR overhead: returns to calling task 158 63
+ exit ASR overhead: returns to preempting task 249 65
+
+20 rtems_partition_create 247 102
+ rtems_region_create 196 78
+ rtems_partition_get_buffer: available 117 26
+ rtems_partition_get_buffer: not available 110 10
+ rtems_partition_return_buffer 127 30
+ rtems_partition_delete 145 31
+ rtems_region_get_segment: available 156 19
+ rtems_region_get_segment: not available -- NO_WAIT 143 36
+ rtems_region_return_segment: no waiting tasks 167 15
+ rtems_region_get_segment: not available -- caller blocks 429 167
+ rtems_region_return_segment: task readied -- preempts caller 418 142
+ rtems_region_return_segment: task readied -- returns to caller 298 71
+ rtems_region_delete 146 25
+ rtems_io_initialize 13 2
+ rtems_io_open 9 1
+ rtems_io_close 9 1
+ rtems_io_read 9 1
+ rtems_io_write 9 1
+ rtems_io_control 9 1
+
+21 rtems_task_ident 1143 139
+ rtems_message_queue_ident 1115 141
+ rtems_semaphore_ident 1285 158
+ rtems_partition_ident 1115 132
+ rtems_region_ident 1137 144
+ rtems_port_ident 1115 133
+ rtems_timer_ident 1117 140
+ rtems_rate_monotonic_ident 1116 136
+
+22 rtems_message_queue_broadcast: task readied -- returns to caller 281 84
+ rtems_message_queue_broadcast: no waiting tasks 177 17
+ rtems_message_queue_broadcast: task readied -- preempts caller 398 114
+
+23 rtems_timer_create 127 15
+ rtems_timer_fire_after: inactive 191 23
+ rtems_timer_fire_after: active 204 24
+ rtems_timer_cancel: active 118 15
+ rtems_timer_cancel: inactive 104 13
+ rtems_timer_reset: inactive 176 21
+ rtems_timer_reset: active 189 22
+ rtems_timer_fire_when: inactive 237 28
+ rtems_timer_fire_when: active 237 28
+ rtems_timer_delete: active 167 25
+ rtems_timer_delete: inactive 153 23
+ rtems_task_wake_when 408 83
+
+24 rtems_task_wake_after: yield -- returns to caller 85 8
+ rtems_task_wake_after: yields -- preempts caller 287 56
+
+25 rtems_clock_tick 59 25
+
+26 _ISR_Disable 3 1
+ _ISR_Flash 3 0
+ _ISR_Enable 1 0
+ _Thread_Disable_dispatch 4 0
+ _Thread_Enable_dispatch 59 6
+ _Thread_Set_state 59 16
+ _Thread_Disptach (NO FP) 242 52
+ context switch: no floating point contexts 183 44
+ context switch: self 62 2
+ context switch: to another task 64 3
+ context switch: restore 1st FP task 189 40
+ fp context switch: save idle, restore idle 186 39
+ fp context switch: save idle, restore initialized 67 4
+ fp context switch: save initialized, restore initialized 67 5
+ _Thread_Resume 51 24
+ _Thread_Unblock 47 12
+ _Thread_Ready 54 9
+ _Thread_Get 33 3
+ _Semaphore_Get 26 2
+ _Thread_Get: invalid id 5 0
+
+27 interrupt entry overhead: returns to interrupted task 0 0
+ interrupt exit overhead: returns to interrupted task 1 1
+ interrupt entry overhead: returns to nested interrupt 0 0
+ interrupt exit overhead: returns to nested interrupt 0 0
+ interrupt entry overhead: returns to preempting task
+ interrupt exit overhead: returns to preempting task
+
+28 rtems_port_create 145 55
+ rtems_port_external_to_internal 101 9
+ rtems_port_internal_to_external 101 9
+ rtems_port_delete 144 40
+
+29 rtems_rate_monotonic_create 135 57
+ rtems_rate_monotonic_period: initiate period -- returns to caller 176 77
+ rtems_rate_monotonic_period: obtain status 110 35
+ rtems_rate_monotonic_cancel 131 50
+ rtems_rate_monotonic_delete: inactive 160 61
+ rtems_rate_monotonic_delete: active 178 41
+ rtems_rate_monotonic_period: conclude periods -- caller blocks 284 67
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/times-mbx860 b/c/src/lib/libbsp/powerpc/mbx8xx/times-mbx860
new file mode 100644
index 0000000000..d99737f9a1
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/times-mbx860
@@ -0,0 +1,191 @@
+#
+# Timing Test Suite Results for the MBX860-002
+#
+# $Id$
+#
+
+Board: MBX860
+CPU: MPC860
+Clock Speed: 40 MHz
+Memory Configuration: 4Mb EDO, 60ns DRAM
+Wait States:
+
+Times Reported in: clock ticks
+Timer Source: Timebase register (TMBCLK = (cpu clock speed / 16) = 2.5Mhz)
+
+Column A: Data & instruction caches disabled (2000-05-03)
+Column B: Data & instruction caches enabled (UPM/A: new burst r/w values) (2000-05-04)
+
+# DESCRIPTION A B
+== ================================================================= ==== ====
+ 1 rtems_semaphore_create 159 67
+ rtems_semaphore_delete 173 52
+ rtems_semaphore_obtain: available 113 26
+ rtems_semaphore_obtain: not available -- NO_WAIT 113 28
+ rtems_semaphore_release: no waiting tasks 144 22
+
+ 2 rtems_semaphore_obtain: not available -- caller blocks 346 121
+
+ 3 rtems_semaphore_release: task readied -- preempts caller 268 89
+
+ 4 rtems_task_restart: blocked task -- preempts caller 475 130
+ rtems_task_restart: ready task -- preempts caller 465 132
+ rtems_semaphore_release: task readied -- returns to caller 179 48
+ rtems_task_create 521 154
+ rtems_task_start 228 57
+ rtems_task_restart: suspended task -- returns to caller 275 74
+ rtems_task_delete: suspended task 494 139
+ rtems_task_restart: ready task -- returns to caller 283 78
+ rtems_task_restart: blocked task -- returns to caller 333 98
+ rtems_task_delete: blocked task 507 144
+
+ 5 rtems_task_suspend: calling task 266 88
+ rtems_task_resume: task readied -- preempts caller 220 61
+
+ 6 rtems_task_restart: calling task 334 75
+ rtems_task_suspend: returns to caller 117 24
+ rtems_task_resume: task readied -- returns to caller 129 29
+ rtems_task_delete: ready task 510 138
+
+ 7 rtems_task_restart: suspended task -- preempts caller 436 135
+
+ 8 rtems_task_set_priority: obtain current priority 98 11
+ rtems_task_set_priority: returns to caller 183 32
+ rtems_task_mode: obtain current mode 51 8
+ rtems_task_mode: no reschedule 62 9
+ rtems_task_mode: reschedule -- returns to caller 66 25
+ rtems_task_mode: reschedule -- preempts caller 246 69
+ rtems_task_set_note 99 11
+ rtems_task_get_note 100 23
+ rtems_clock_set 222 35
+ rtems_clock_get 6 1
+
+ 9 rtems_message_queue_create 667 262
+ rtems_message_queue_send: no waiting tasks 215 58
+ rtems_message_queue_urgent: no waiting tasks 212 53
+ rtems_message_queue_receive: available 204 43
+ rtems_message_queue_flush: no messages flushed 93 17
+ rtems_message_queue_flush: messages flushed 113 22
+ rtems_message_queue_delete 214 76
+
+10 rtems_message_queue_receive: not available -- NO_WAIT 131 20
+ rtems_message_queue_receive: not available -- caller blocks 357 118
+
+11 rtems_message_queue_send: task readied -- preempts caller 322 109
+
+12 rtems_message_queue_send: task readied -- returns to caller 234 67
+
+13 rtems_message_queue_urgent: task readied -- preempts caller 322 94
+
+14 rtems_message_queue_urgent: task readied -- returns to caller 234 62
+
+15 rtems_event_receive: obtain current events 8 1
+ rtems_event_receive: not available -- NO_WAIT 90 9
+ rtems_event_receive: not available -- caller blocks 294 88
+ rtems_event_send: no task readied 91 10
+ rtems_event_receive: available 93 22
+ rtems_event_send: task readied -- returns to caller 161 41
+
+16 rtems_event_send: task readied -- preempts caller 260 84
+
+17 rtems_task_set_priority: preempts caller 349 108
+
+18 rtems_task_delete: calling task 652 203
+
+19 rtems_signal_catch 66 9
+ rtems_signal_send: returns to caller 107 41
+ rtems_signal_send: signal to self 176 62
+ exit ASR overhead: returns to calling task 140 56
+ exit ASR overhead: returns to preempting task 207 54
+
+20 rtems_partition_create 220 78
+ rtems_region_create 175 71
+ rtems_partition_get_buffer: available 103 21
+ rtems_partition_get_buffer: not available 97 10
+ rtems_partition_return_buffer 113 24
+ rtems_partition_delete 128 26
+ rtems_region_get_segment: available 137 27
+ rtems_region_get_segment: not available -- NO_WAIT 126 36
+ rtems_region_return_segment: no waiting tasks 148 31
+ rtems_region_get_segment: not available -- caller blocks 366 119
+ rtems_region_return_segment: task readied -- preempts caller 359 114
+ rtems_region_return_segment: task readied -- returns to caller 265 72
+ rtems_region_delete 129 33
+ rtems_io_initialize 12 2
+ rtems_io_open 9 1
+ rtems_io_close 9 1
+ rtems_io_read 9 1
+ rtems_io_write 9 1
+ rtems_io_control 9 1
+
+21 rtems_task_ident 1019 137
+ rtems_message_queue_ident 993 139
+ rtems_semaphore_ident 1144 162
+ rtems_partition_ident 993 132
+ rtems_region_ident 1012 143
+ rtems_port_ident 993 132
+ rtems_timer_ident 994 138
+ rtems_rate_monotonic_ident 993 135
+
+22 rtems_message_queue_broadcast: task readied -- returns to caller 249 80
+ rtems_message_queue_broadcast: no waiting tasks 157 27
+ rtems_message_queue_broadcast: task readied -- preempts caller 340 94
+
+23 rtems_timer_create 114 15
+ rtems_timer_fire_after: inactive 170 36
+ rtems_timer_fire_after: active 182 36
+ rtems_timer_cancel: active 104 14
+ rtems_timer_cancel: inactive 92 12
+ rtems_timer_reset: inactive 156 29
+ rtems_timer_reset: active 168 31
+ rtems_timer_fire_when: inactive 210 43
+ rtems_timer_fire_when: active 210 42
+ rtems_timer_delete: active 148 24
+ rtems_timer_delete: inactive 136 20
+ rtems_task_wake_when 350 99
+
+24 rtems_task_wake_after: yield -- returns to caller 76 10
+ rtems_task_wake_after: yields -- preempts caller 242 63
+
+25 rtems_clock_tick 51 19
+
+26 _ISR_Disable 3 0
+ _ISR_Flash 2 0
+ _ISR_Enable 0 0
+ _Thread_Disable_dispatch 3 0
+ _Thread_Enable_dispatch 52 8
+ _Thread_Set_state 51 15
+ _Thread_Disptach (NO FP) 201 53
+ context switch: no floating point contexts 148 44
+ context switch: self 41 4
+ context switch: to another task 44 5
+ context switch: restore 1st FP task 154 41
+ fp context switch: save idle, restore idle 152 42
+ fp context switch: save idle, restore initialized 46 5
+ fp context switch: save initialized, restore initialized 47 4
+ _Thread_Resume 45 19
+ _Thread_Unblock 42 10
+ _Thread_Ready 47 8
+ _Thread_Get 29 3
+ _Semaphore_Get 23 2
+ _Thread_Get: invalid id 5 0
+
+27 interrupt entry overhead: returns to interrupted task 0 0
+ interrupt exit overhead: returns to interrupted task 0 0
+ interrupt entry overhead: returns to nested interrupt 0 0
+ interrupt exit overhead: returns to nested interrupt 0 0
+ interrupt entry overhead: returns to preempting task
+ interrupt exit overhead: returns to preempting task
+
+28 rtems_port_create 128 48
+ rtems_port_external_to_internal 90 9
+ rtems_port_internal_to_external 90 13
+ rtems_port_delete 128 30
+
+29 rtems_rate_monotonic_create 120 48
+ rtems_rate_monotonic_period: initiate period -- returns to caller 156 55
+ rtems_rate_monotonic_period: obtain status 98 27
+ rtems_rate_monotonic_cancel 115 39
+ rtems_rate_monotonic_delete: inactive 141 51
+ rtems_rate_monotonic_delete: active 158 46
+ rtems_rate_monotonic_period: conclude periods -- caller blocks 240 76
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/wrapup/Makefile.am b/c/src/lib/libbsp/powerpc/mbx8xx/wrapup/Makefile.am
new file mode 100644
index 0000000000..11de3f33b0
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/wrapup/Makefile.am
@@ -0,0 +1,40 @@
+##
+## $Id$
+##
+
+AUTOMAKE_OPTIONS = foreign 1.4
+
+# We only build the networking device driver if HAS_NETWORKING was defined
+if HAS_NETWORKING
+NETWORKING = network
+endif
+
+BSP_PIECES = startup console $(NETWORKING)
+# pieces to pick up out of libcpu/ppc
+# CPU_PIECES = mpc8xx/clock mpc8xx/console-generic mpc8xx/cpm \
+ mpc8xx/mmu mpc8xx/timer mpc8xx/vectors
+
+# bummer; have to use $foreach since % pattern subst rules only replace 1x
+OBJS = $(foreach piece, $(BSP_PIECES), $(wildcard ../$(piece)/$(ARCH)/*.o))
+LIB = $(ARCH)/libbsp.a
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../../../../../../automake/lib.am
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+$(LIB): $(OBJS)
+ $(make-library)
+
+$(PROJECT_RELEASE)/lib/libbsp$(LIB_VARIANT).a: $(LIB)
+ $(INSTALL_DATA) $< $@
+
+TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/libbsp$(LIB_VARIANT).a
+
+all-local: $(ARCH) $(OBJS) $(LIB) $(TMPINSTALL_FILES)
+
+.PRECIOUS: $(LIB)
+
+include $(top_srcdir)/../../../../../../automake/local.am