summaryrefslogtreecommitdiffstats
path: root/c
diff options
context:
space:
mode:
authorThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2008-09-08 09:55:39 +0000
committerThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2008-09-08 09:55:39 +0000
commit63de714ce7c0869715687c728f84efd048cba550 (patch)
tree65af9691a920ba4300d1e1fe5209fb6696cd815f /c
parentadded support for flexible PLL in MPC866 and friends (diff)
downloadrtems-63de714ce7c0869715687c728f84efd048cba550.tar.bz2
added new BSP for TQM8xx boards
Diffstat (limited to 'c')
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am93
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/README141
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/bsp_specs14
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/configure.ac113
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/console/console.c1112
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/include/8xx_immap.h477
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/include/bsp.h172
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/include/coverhd.h362
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/include/irq-config.h101
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/include/irq.h154
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/include/tm27.h32
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/include/tqm.h51
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/irq/irq.c240
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/irq/irq.h204
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/irq/irq_asm.S433
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/irq/irq_init.c185
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/network/network_fec.c926
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/network/network_scc.c1047
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/preinstall.am104
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/startup/bspstart.c234
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/startup/cpuinit.c134
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/startup/linkcmds.base316
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/startup/linkcmds.tqm8xx15
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/startup/mmutlbtab.c103
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/startup/start.S287
-rw-r--r--c/src/lib/libbsp/powerpc/tqm8xx/timer/timer.c110
26 files changed, 7160 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am b/c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am
new file mode 100644
index 0000000000..08489adc8d
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am
@@ -0,0 +1,93 @@
+##
+## $Id$
+##
+
+ACLOCAL_AMFLAGS = -I ../../../../aclocal
+
+include $(top_srcdir)/../../../../automake/compile.am
+include $(top_srcdir)/../../bsp.am
+
+dist_project_lib_DATA = bsp_specs
+
+include_HEADERS = include/bsp.h
+include_HEADERS += include/tm27.h
+
+libcpudir = ../../../libcpu/@RTEMS_CPU@
+
+nodist_include_HEADERS = include/bspopts.h
+DISTCLEANFILES = include/bspopts.h
+
+noinst_PROGRAMS =
+
+include_bspdir = $(includedir)/bsp
+
+include_HEADERS += include/coverhd.h
+include_bsp_HEADERS = include/tqm.h include/8xx_immap.h \
+ include/irq.h include/irq-config.h \
+ ../../shared/include/irq-generic.h\
+ $(libcpudir)/@exceptions@/bspsupport/vectors.h \
+ $(libcpudir)/@exceptions@/bspsupport/ppc_exc_bspsupp.h
+
+
+EXTRA_DIST = times-tqm866
+
+EXTRA_DIST += startup/start.S
+start.$(OBJEXT): startup/start.S
+ $(CPPASCOMPILE) -o $@ -c $<
+project_lib_DATA = start.$(OBJEXT)
+
+EXTRA_DIST += ../../powerpc/shared/start/rtems_crti.S
+rtems_crti.$(OBJEXT): ../../powerpc/shared/start/rtems_crti.S
+ $(CPPASCOMPILE) -o $@ -c $<
+project_lib_DATA += rtems_crti.$(OBJEXT)
+
+dist_project_lib_DATA += startup/linkcmds.base\
+ startup/linkcmds.tqm8xx
+
+irq_SOURCES = include/irq-config.h \
+ irq/irq.c \
+ ../../shared/src/irq-generic.c \
+ ../../shared/src/irq-legacy.c
+
+# clock_SOURCES = ../shared/clock/clock.c
+p_clock_SOURCES = clock/p_clock.c
+
+console_SOURCES = console/console.c
+timer_SOURCES = timer/timer.c
+startup_SOURCES = ../../shared/bspclean.c ../../shared/bsplibc.c \
+ ../../shared/bsppost.c ../../shared/bsppredriverhook.c \
+ startup/bspstart.c ../../shared/bootcard.c \
+ startup/mmutlbtab.c startup/cpuinit.c \
+ ../../shared/sbrk.c ../../shared/gnatinstallhandler.c
+
+if HAS_NETWORKING
+network_CPPFLAGS = -D__INSIDE_RTEMS_BSD_TCPIP_STACK__
+noinst_PROGRAMS += network.rel
+network_rel_SOURCES = network/network_scc.c network/network_fec.c
+network_rel_CPPFLAGS = $(AM_CPPFLAGS) $(network_CPPFLAGS)
+network_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
+endif
+
+noinst_LIBRARIES = libbsp.a
+libbsp_a_SOURCES = $(irq_SOURCES) \
+ $(startup_SOURCES) $(console_SOURCES) \
+ $(p_clock_SOURCES) $(timer_SOURCES)
+
+libbsp_a_LIBADD = \
+ $(libcpudir)/shared/cpuIdent.rel \
+ $(libcpudir)/shared/cache.rel \
+ $(libcpudir)/@exceptions@/rtems-cpu.rel \
+ $(libcpudir)/@exceptions@/raw_exception.rel \
+ $(libcpudir)/@exceptions@/exc_bspsupport.rel \
+ $(libcpudir)/mpc8xx/console-generic.rel \
+ $(libcpudir)/mpc8xx/cpm.rel \
+ $(libcpudir)/mpc8xx/clock.rel \
+ $(libcpudir)/mpc8xx/mmu.rel \
+ $(libcpudir)/mpc8xx/timer.rel
+
+if HAS_NETWORKING
+libbsp_a_LIBADD += network.rel
+endif
+
+include $(srcdir)/preinstall.am
+include $(top_srcdir)/../../../../automake/local.am
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/README b/c/src/lib/libbsp/powerpc/tqm8xx/README
new file mode 100644
index 0000000000..261932c3c5
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/README
@@ -0,0 +1,141 @@
+#
+# $Id$
+#
+
+This is a README file for the tqm8xx BSP
+
+
+Summary
+-------
+
+BSP NAME: tqm8xx
+BOARD: various boards based on TQ Components TQM8xx modules
+BUS: No backplane.
+CPU FAMILY: PowerPC
+CPU: PowerPC MPC860 or MPC866
+COPROCESSORS: Built-in Motorola QUICC
+MODE: 32 bit mode
+
+BOOT MONITOR: TQMon
+
+PERIPHERALS
+===========
+TIMERS: PIT / Timebase
+ RESOLUTION: 1 microsecond / frequency = clock-speed / 16
+SERIAL PORTS: 1-4 SCCs, 1-2 SMC
+REAL-TIME CLOCK: <none>
+DMA: Each SCC and SMC.
+VIDEO: <none>
+SCSI: <none>
+NETWORKING: Ethernet 10 Mbps on SCC1 and/or
+ 10/100Mbps on FEC (for MPC866T)
+
+
+DRIVER INFORMATION
+==================
+CLOCK DRIVER: yes
+CONSOLE DRIVER: yes
+SHMSUPP: N/A
+TIMER DRIVER: yes
+NETWORK DRIVER: yes
+
+NOTES
+=====
+On-chip resources:
+ SCC1 network or serial port
+ SCC2 serial port
+ SCC3 serial port
+ SCC4 serial port
+ SMC1 serial port
+ SMC2 serial port
+ CLK1 network
+ CLK2 network
+ CLK3
+ CLK4
+ CLK5
+ CLK6
+ CLK7
+ CLK8
+ BRG1 console
+ BRG2 console
+ BRG3 console
+ BRG4 console
+ RTC
+ PIT clock
+ TB
+ DEC
+ SWT
+ 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 - 133MHz.
+Bus width: 32 bit Flash, 32 bit DRAM
+FLASH: 2-8MB
+RAM: 32-256MB SDRAM
+
+
+Installation
+------------
+<tbd>
+
+
+Port Description
+Console driver
+---------------
+
+This BSP contains a console driver for polled and interrupt-driven
+operation. It supports SCCs and SMCs.
+During BSP configuration, various variables can be set to activate a
+certain channels and to specify the console channel:
+
+CONS_SMC1_MODE, CONS_SMC2_MODE, CONS_SCC[1-4]_MODE can be set to
+CONS_MODE_UNUSED, CONS_MODE_POLLED or CONS_MODE_IRQ
+
+The driver always uses termios.
+
+printk() and debug output
+-----------------------
+<tbd>
+
+Floating-point
+--------------
+
+The MPC8xx 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 mbx8xx and gen68360 port.
+
+Test Configuration
+------------------
+
+Board: pghplus (
+CPU: Motorola MPC866T
+Clock Speed: 133MHz
+RAM: 64MByte
+Cache Configuration: Instruction cache on; data cache on, copyback mode.
+
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/bsp_specs b/c/src/lib/libbsp/powerpc/tqm8xx/bsp_specs
new file mode 100644
index 0000000000..e5456faee5
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/bsp_specs
@@ -0,0 +1,14 @@
+%rename endfile old_endfile
+%rename startfile old_startfile
+%rename link old_link
+
+*startfile:
+%{!qrtems: %(old_startfile)} %{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s \
+%{!qrtems_debug: start.o%s} \
+%{qrtems_debug: start_g.o%s}}}
+
+*endfile:
+%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s 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/tqm8xx/configure.ac b/c/src/lib/libbsp/powerpc/tqm8xx/configure.ac
new file mode 100644
index 0000000000..712ba650b6
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/configure.ac
@@ -0,0 +1,113 @@
+## Process this file with autoconf to produce a configure script.
+##
+## $Id$
+
+AC_PREREQ(2.60)
+AC_INIT([rtems-c-src-lib-libbsp-powerpc-tqm8xx],[_RTEMS_VERSION],[http://www.rtems.org/bugzilla])
+AC_CONFIG_SRCDIR([bsp_specs])
+RTEMS_TOP(../../../../../..)
+
+RTEMS_CANONICAL_TARGET_CPU
+AM_INIT_AUTOMAKE([no-define nostdinc foreign 1.10])
+RTEMS_BSP_CONFIGURE
+
+RTEMS_PROG_CC_FOR_TARGET([-ansi -fasm])
+RTEMS_CANONICALIZE_TOOLS
+RTEMS_PROG_CCAS
+
+RTEMS_CHECK_NETWORKING
+AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes")
+
+RTEMS_BSPOPTS_SET([PPC_USE_DATA_CACHE],[*],[1])
+RTEMS_BSPOPTS_HELP([PPC_USE_DATA_CACHE],
+[If defined, then the PowerPC specific code in RTEMS will use
+ data cache instructions to optimize the context switch code.
+ This code can conflict with debuggers or emulators.])
+
+RTEMS_BSPOPTS_SET([DATA_CACHE_ENABLE],[*],[1])
+RTEMS_BSPOPTS_HELP([DATA_CACHE_ENABLE],
+[If defined, the data cache will be enabled after address translation
+ is turned on.])
+
+RTEMS_BSPOPTS_SET([INSTRUCTION_CACHE_ENABLE],[*],[1])
+RTEMS_BSPOPTS_HELP([INSTRUCTION_CACHE_ENABLE],
+[If defined, the instruction cache will be enabled after address translation
+ is turned on.])
+
+RTEMS_BSPOPTS_SET([CONSOLE_CHN],[*],[CONS_CHN_SMC1])
+RTEMS_BSPOPTS_HELP([CONSOLE_CHN],
+[(BSP--console driver) Must be defined to be one of CONS_CHN_SMC1,
+ CONS_CHN_SMC2, CONS_CHN_SCC1, CONS_CHN_SCC2, CONS_CHN_SCC3, or CONS_CHN_SCC4.
+ Determines which device will be registered as /dev/console.])
+
+RTEMS_BSPOPTS_SET([PRINTK_CHN],[*],[CONS_CHN_SMC1])
+RTEMS_BSPOPTS_HELP([PRINTK_CHN],
+[(BSP--console driver)
+ Must be defined to be one of CONS_CHN_SMC1, CONS_CHN_SMC2, CONS_CHN_SCC2,
+ CONS_CHN_SCC3, or CONS_CHN_SCC4. Determines which device is used for output
+ by printk(). If the port that printk() uses is also used for other
+ I/O (e.g. if PRINTK_CHN == CONSOLE_CHN), then both ports should
+ use the same type of I/O, otherwise the drivers will likely conflict with
+ each other.])
+
+RTEMS_BSPOPTS_SET([CONS_SMC1_MODE],[tqm8xx_stk8xx],[CONS_MODE_POLLED])
+RTEMS_BSPOPTS_SET([CONS_SMC1_MODE],[pghplus],[CONS_MODE_POLLED])
+RTEMS_BSPOPTS_SET([CONS_SMC1_MODE],[*],[CONS_MODE_UNUSED])
+RTEMS_BSPOPTS_HELP([CONS_SMC1_MODE],
+[(BSP--SMC1 UART IF mode) Must be defined if SMC1 is used as a tty (UART)
+ channel. Set it to CONS_MODE_POLLED for polled operation, CONS_MODE_IRQ for
+ interrupt driven (spooled) operation. Set it to CONS_MODE_UNUSED, if not used])
+
+RTEMS_BSPOPTS_SET([CONS_SMC2_MODE],[tqm8xx_stk8xx],[CONS_MODE_POLLED])
+RTEMS_BSPOPTS_SET([CONS_SMC2_MODE],[*],[CONS_MODE_UNUSED])
+RTEMS_BSPOPTS_HELP([CONS_SMC2_MODE],
+[(BSP--SMC2 UART IF mode) Must be defined if SMC2 is used as a tty (UART)
+ channel. Set it to CONS_MODE_POLLED for polled operation, CONS_MODE_IRQ for
+ interrupt driven (spooled) operation. Set it to CONS_MODE_UNUSED, if not used])
+
+RTEMS_BSPOPTS_SET([CONS_SCC1_MODE],[*],[CONS_MODE_UNUSED])
+RTEMS_BSPOPTS_HELP([CONS_SCC1_MODE],
+[(BSP--SCC1 UART IF mode) Must be defined if SCC1 is used as a tty (UART)
+ channel. Set it to CONS_MODE_POLLED for polled operation, CONS_MODE_IRQ for
+ interrupt driven (spooled) operation. Set it to CONS_MODE_UNUSED, if not used])
+
+RTEMS_BSPOPTS_SET([CONS_SCC2_MODE],[*],[CONS_MODE_UNUSED])
+RTEMS_BSPOPTS_HELP([CONS_SCC2_MODE],
+[(BSP--SCC2 UART IF mode) Must be defined if SCC2 is used as a tty (UART)
+ channel. Set it to CONS_MODE_POLLED for polled operation, CONS_MODE_IRQ for
+ interrupt driven (spooled) operation. Set it to CONS_MODE_UNUSED, if not used])
+
+RTEMS_BSPOPTS_SET([CONS_SCC3_MODE],[*],[CONS_MODE_UNUSED])
+RTEMS_BSPOPTS_HELP([CONS_SCC3_MODE],
+[(BSP--SCC3 UART IF mode) Must be defined if SCC3 is used as a tty (UART)
+ channel. Set it to CONS_MODE_POLLED for polled operation, CONS_MODE_IRQ for
+ interrupt driven (spooled) operation. Set it to CONS_MODE_UNUSED, if not used])
+
+RTEMS_BSPOPTS_SET([CONS_SCC4_MODE],[*],[CONS_MODE_UNUSED])
+RTEMS_BSPOPTS_HELP([CONS_SCC4_MODE],
+[(BSP--SCC4 UART IF mode) Must be defined if SCC4 is used as a tty (UART)
+ channel. Set it to CONS_MODE_POLLED for polled operation, CONS_MODE_IRQ for
+ interrupt driven (spooled) operation. Set it to CONS_MODE_UNUSED, if not used])
+
+# add selection of primary network interface
+RTEMS_BSPOPTS_SET([BSP_USE_NETWORK_FEC],[pghplus],[1])
+RTEMS_BSPOPTS_SET([BSP_USE_NETWORK_FEC],[*],[0])
+RTEMS_BSPOPTS_HELP([BSP_USE_NETWORK_FEC],
+[If defined, then the BSP will use the Fast Ethernet Controller
+ for 10/100MBit networking and used as primary networking interface.])
+
+RTEMS_BSPOPTS_SET([BSP_USE_NETWORK_SCC],[pghplus],[0])
+RTEMS_BSPOPTS_SET([BSP_USE_NETWORK_SCC],[*],[1])
+RTEMS_BSPOPTS_HELP([BSP_USE_NETWORK_SCC],
+[If defined, then the BSP will use the Serial Communications Controller (SCC1)
+ for 10MBit networking.])
+
+
+# Explicitly list a Makefile here
+AC_CONFIG_FILES([Makefile])
+
+RTEMS_BSP_BOOTCARD_HANDLES_RAM_ALLOCATION
+
+RTEMS_PPC_EXCEPTIONS
+
+AC_OUTPUT
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/console/console.c b/c/src/lib/libbsp/powerpc/tqm8xx/console/console.c
new file mode 100644
index 0000000000..00e08e79b3
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/console/console.c
@@ -0,0 +1,1112 @@
+/*===============================================================*\
+| Project: RTEMS TQM8xx BSP |
++-----------------------------------------------------------------+
+| This file has been adapted to MPC8xx by |
+| Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> |
+| Copyright (c) 2008 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
+| |
+| See the other copyright notice below for the original parts. |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the console driver |
+\*===============================================================*/
+/* derived from: */
+/*
+ * SMC1/2 SCC1..4 raw console serial I/O.
+ * adapted to work with up to 4 SCC and 2 SMC
+ *
+ * This driver is an example of `TASK DRIVEN' `POLLING' or `INTERRUPT' I/O.
+ *
+ * To run with interrupt-driven I/O, ensure m8xx_smc1_interrupt
+ * is set before calling the initialization routine.
+ *
+ * Author:
+ * W. Eric Norum
+ * Saskatchewan Accelerator Laboratory
+ * University of Saskatchewan
+ * Saskatoon, Saskatchewan, CANADA
+ * eric@skatter.usask.ca
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <bsp.h>
+#include <mpc8xx.h>
+#include <rtems/libio.h>
+#include <termios.h>
+#include <unistd.h>
+#include <rtems/termiostypes.h>
+#include <rtems/bspIo.h>
+
+/*
+ * Declare clock speed -- may be overwritten by downloader or debugger
+ */
+int m8xx_clock_rate = 0;
+
+/*
+ * Interrupt-driven input buffer
+ */
+#define RXBUFSIZE 256
+
+#define M8xx_IVEC_SRC_MASK (0x1f)
+#define M8xx_IVEC_SRC_SCC1 (0x1E)
+#define M8xx_IVEC_SRC_SCC2 (0x1D)
+#define M8xx_IVEC_SRC_SCC3 (0x1C)
+#define M8xx_IVEC_SRC_SCC4 (0x1B)
+#define M8xx_IVEC_SRC_SMC1 (0x04)
+#define M8xx_IVEC_SRC_SMC2 (0x03)
+
+#define M8xx_IREG_MASK(src) (1UL << src)
+#define M8xx_SICR_BRG1 (0)
+#define M8xx_SICR_BRG2 (1)
+#define M8xx_SICR_BRG3 (2)
+#define M8xx_SICR_BRG4 (3)
+
+#define M8xx_SICR_SCCRX_MSK(scc) (( 7) << (((scc))*8+3))
+#define M8xx_SICR_SCCRX(scc,clk) ((clk) << (((scc))*8+3))
+
+#define M8xx_SICR_SCCTX_MSK(scc) (( 7) << (((scc))*8+0))
+#define M8xx_SICR_SCCTX(scc,clk) ((clk) << (((scc))*8+0))
+
+#define M8xx_SIMODE_SMCCS(smc,clk) ((clk) << ((smc)*16+12))
+#define M8xx_SIMODE_SMCCS_MSK(smc) M8xx_SIMODE_SMCCS(smc,7)
+
+#define CONS_CHN_CNT 6
+#define CONS_CHN_SCC1 0
+#define CONS_CHN_SCC2 1
+#define CONS_CHN_SCC3 2
+#define CONS_CHN_SCC4 3
+#define CONS_CHN_SMC1 4
+#define CONS_CHN_SMC2 5
+
+/*
+ * possible identifiers for bspopts.h: CONS_SxCy_MODE
+ */
+#define CONS_MODE_UNUSED -1
+#define CONS_MODE_POLLED TERMIOS_POLLED
+#define CONS_MODE_IRQ TERMIOS_IRQ_DRIVEN
+
+#define CHN_IS_SCC(chan) ((chan) < CONS_CHN_SMC1)
+
+#define BRG_CNT 4
+
+#define MAX_IDL_DEFAULT 10
+#define DEVICEPREFIX "tty"
+
+/*
+ * printk basic support
+ */
+static void _BSP_null_char( char c ) {return;}
+BSP_output_char_function_type BSP_output_char = _BSP_null_char;
+
+/*
+ * Interrupt-driven callback
+ */
+static int m8xx_scc_mode[CONS_CHN_CNT];
+static void *sccttyp[CONS_CHN_CNT];
+typedef struct m8xx_console_chan_desc_s {
+ bool is_scc; /* true for SCC */
+ struct {
+ volatile m8xxSCCparms_t *sccp;
+ volatile m8xxSMCparms_t *smcp;
+ } parms;
+ struct {
+ volatile m8xxSCCRegisters_t *sccr;
+ volatile m8xxSMCRegisters_t *smcr;
+ } regs;
+ int ivec_src;
+ uint32_t ireg_mask;
+ int cr_chan_code;
+ int brg_used;
+} m8xx_console_chan_desc_t;
+
+m8xx_console_chan_desc_t m8xx_console_chan_desc[CONS_CHN_CNT] = {
+ /* SCC1 */
+ {TRUE,
+ {(m8xxSCCparms_t *)&(m8xx.scc1p),NULL},
+ {&(m8xx.scc1),NULL},
+ M8xx_IVEC_SRC_SCC1,
+ M8xx_IREG_MASK(M8xx_IVEC_SRC_SCC1),
+ M8xx_CR_CHAN_SCC1,
+ -1},
+ /* SCC2 */
+ {TRUE,
+ {&(m8xx.scc2p),NULL},
+ {&(m8xx.scc2),NULL},
+ M8xx_IVEC_SRC_SCC2,
+ M8xx_IREG_MASK(M8xx_IVEC_SRC_SCC2),
+ M8xx_CR_CHAN_SCC2,
+ -1},
+ /* SCC3 */
+ {TRUE,
+ {&(m8xx.scc3p),NULL},
+ {&(m8xx.scc3),NULL},
+ M8xx_IVEC_SRC_SCC3,
+ M8xx_IREG_MASK(M8xx_IVEC_SRC_SCC3),
+ M8xx_CR_CHAN_SCC3,
+ -1},
+ /* SCC4 */
+ {TRUE,
+ {&(m8xx.scc4p),NULL},
+ {&(m8xx.scc4),NULL},
+ M8xx_IVEC_SRC_SCC4,
+ M8xx_IREG_MASK(M8xx_IVEC_SRC_SCC4),
+ M8xx_CR_CHAN_SCC4,
+ -1},
+ /* SMC1 */
+ {FALSE,
+ {NULL,&(m8xx.smc1p)},
+ {NULL,&(m8xx.smc1)},
+ M8xx_IVEC_SRC_SMC1,
+ M8xx_IREG_MASK(M8xx_IVEC_SRC_SMC1),
+ M8xx_CR_CHAN_SMC1,
+ -1},
+ /* SMC2 */
+ {FALSE,
+ {NULL,&(m8xx.smc2p)},
+ {NULL,&(m8xx.smc2)},
+ M8xx_IVEC_SRC_SMC2,
+ M8xx_IREG_MASK(M8xx_IVEC_SRC_SMC2),
+ M8xx_CR_CHAN_SMC2,
+ -1}};
+
+#define CHN_PARAM_GET(chan,param) \
+ (m8xx_console_chan_desc[chan].is_scc \
+ ? m8xx_console_chan_desc[chan].parms.sccp->param \
+ : m8xx_console_chan_desc[chan].parms.smcp->param)
+
+#define CHN_PARAM_SET(chan,param,value) \
+ do {if (m8xx_console_chan_desc[chan].is_scc) \
+ m8xx_console_chan_desc[chan].parms.sccp->param = value; \
+ else \
+ m8xx_console_chan_desc[chan].parms.smcp->param = value; \
+ } while (0)
+
+#define CHN_EVENT_GET(chan) \
+ (m8xx_console_chan_desc[chan].is_scc \
+ ? m8xx_console_chan_desc[chan].regs.sccr->scce \
+ : m8xx_console_chan_desc[chan].regs.smcr->smce)
+
+#define CHN_EVENT_CLR(chan,mask) \
+ do { \
+ if (m8xx_console_chan_desc[chan].is_scc) \
+ m8xx_console_chan_desc[chan].regs.sccr->scce = (mask); \
+ else \
+ m8xx_console_chan_desc[chan].regs.smcr->smce = (mask); \
+ }while (0)
+
+#define CHN_MASK_GET(chan) \
+ (m8xx_console_chan_desc[chan].is_scc \
+ ? m8xx_console_chan_desc[chan].regs.sccr->sccm \
+ : m8xx_console_chan_desc[chan].regs.smcr->smcm)
+
+#define CHN_MASK_SET(chan,mask) \
+ do { \
+ if (m8xx_console_chan_desc[chan].is_scc) \
+ m8xx_console_chan_desc[chan].regs.sccr->sccm = (mask); \
+ else \
+ m8xx_console_chan_desc[chan].regs.smcr->smcm = (mask); \
+ }while (0)
+
+
+/*
+ * I/O buffers and pointers to buffer descriptors
+ */
+#define SCC_RXBD_CNT 4
+#define SCC_TXBD_CNT 4
+typedef volatile char sccRxBuf_t[SCC_RXBD_CNT][RXBUFSIZE];
+static sccRxBuf_t *rxBuf[CONS_CHN_CNT];
+
+static volatile m8xxBufferDescriptor_t *sccFrstRxBd[CONS_CHN_CNT];
+static volatile m8xxBufferDescriptor_t *sccCurrRxBd[CONS_CHN_CNT];
+static volatile m8xxBufferDescriptor_t *sccFrstTxBd[CONS_CHN_CNT];
+static volatile m8xxBufferDescriptor_t *sccPrepTxBd[CONS_CHN_CNT];
+static volatile m8xxBufferDescriptor_t *sccDequTxBd[CONS_CHN_CNT];
+
+/*
+ * Compute baud-rate-generator configuration register value
+ */
+static uint32_t
+sccBRGval (int baud)
+{
+ int divisor;
+ int div16 = 0;
+
+ divisor = ((m8xx_clock_rate / 16) + (baud / 2)) / baud;
+ if (divisor > 4096) {
+ div16 = 1;
+ divisor = (divisor + 8) / 16;
+ }
+ return M8xx_BRG_EN | M8xx_BRG_EXTC_BRGCLK | ((divisor - 1) << 1) | div16;
+}
+
+typedef struct {
+ uint32_t reg_content;
+ int link_cnt;
+}brg_state_t;
+brg_state_t scc_brg_state[BRG_CNT];
+
+/*
+ * initialize brg_state
+ */
+static void sccBRGinit(void)
+{
+ int brg_idx;
+
+ for (brg_idx = 0;brg_idx < BRG_CNT;brg_idx++) {
+ scc_brg_state[brg_idx].reg_content = 0;
+ scc_brg_state[brg_idx].link_cnt = 0;
+ }
+#ifndef MDE360
+ /*
+ * on ZEM40, init CLK4/5 inputs
+ */
+ m8xx.papar |= ((1 << 11) | (1 << 12));
+ m8xx.padir &= ~((1 << 11) | (1 << 12));
+#endif
+}
+
+/*
+ * input clock frq for CPM clock inputs
+ */
+static uint32_t clkin_frq[2][4] = {
+#ifdef MDE360
+ {0,0,0,0},
+ {0,0,0,0}
+#else
+ {0,0,0,1843000},
+ {1843000,0,0,0}
+#endif
+};
+
+/*
+ * allocate, set and connect baud rate generators
+ * FIXME: or clock input
+ * FIXME: set pin to be clock input
+ */
+
+static int sccBRGalloc(int chan,int baud)
+{
+ rtems_interrupt_level level;
+ m8xx_console_chan_desc_t *chan_desc = &(m8xx_console_chan_desc[chan]);
+ uint32_t reg_val;
+ int old_brg;
+ int new_brg = -1;
+ int brg_idx;
+#if 0 /* we do not support external clocked console */
+ int clk_group;
+ int clk_sel;
+#endif
+
+ old_brg = chan_desc->brg_used;
+ /* compute brg register contents needed */
+ reg_val = sccBRGval(baud);
+
+#if 0 /* we do not support external clocked console */
+ /* search for clock input with this frq */
+ clk_group = ((chan == CONS_CHN_SCC3) ||
+ (chan == CONS_CHN_SCC4) ||
+ (chan == CONS_CHN_SMC2)) ? 1 : 0;
+
+ for (clk_sel = 0, new_brg = -1;
+ (clk_sel < 4) && (new_brg < 0);
+ clk_sel++) {
+ if (baud == (clkin_frq[clk_group][clk_sel] / 16)) {
+ new_brg = clk_sel + 4;
+ }
+ }
+#endif
+
+ rtems_interrupt_disable(level);
+
+ if (new_brg < 0) {
+ /* search for brg with this settings */
+ for (brg_idx = 0;
+ (new_brg < 0) && (brg_idx < BRG_CNT);
+ brg_idx++) {
+ if (scc_brg_state[brg_idx].reg_content == reg_val) {
+ new_brg = brg_idx;
+ }
+ }
+ /*
+ * if not found: check, whether brg currently in use
+ * is linked only from our channel
+ */
+ if ((new_brg < 0) &&
+ (old_brg >= 0) &&
+ (scc_brg_state[old_brg].link_cnt == 1)) {
+ new_brg = old_brg;
+ }
+ /* if not found: search for unused brg, set it */
+ for (brg_idx = 0;
+ (new_brg < 0) && (brg_idx < BRG_CNT);
+ brg_idx++) {
+ if (scc_brg_state[brg_idx].link_cnt == 0) {
+ new_brg = brg_idx;
+ }
+ }
+ }
+
+ /* decrease old link count */
+ if ((old_brg >= 0) &&
+ (old_brg < 4)) {
+ scc_brg_state[old_brg].link_cnt--;
+ }
+ /* increase new brg link count, set brg */
+ if ((new_brg >= 0) &&
+ (new_brg < 4)) {
+ scc_brg_state[new_brg].link_cnt++;
+ scc_brg_state[new_brg].reg_content = reg_val;
+ (&m8xx.brgc1)[new_brg] = reg_val;
+ }
+ rtems_interrupt_enable(level);
+
+ /* connect to scc/smc */
+ if (new_brg >= 0) {
+ m8xx_console_chan_desc[chan].brg_used = new_brg;
+ /*
+ * Put SCC in NMSI mode, connect SCC to BRG or CLKx
+ */
+ if (m8xx_console_chan_desc[chan].is_scc) {
+ m8xx.sicr = ((m8xx.sicr & ~(M8xx_SICR_SCCRX_MSK(chan) |
+ M8xx_SICR_SCCTX_MSK(chan))) |
+ M8xx_SICR_SCCRX(chan,new_brg)|
+ M8xx_SICR_SCCTX(chan,new_brg));
+ }
+ else {
+ /* connect SMC to BRGx or CLKx... */
+ m8xx.simode = ((m8xx.simode & ~(M8xx_SIMODE_SMCCS_MSK(chan - CONS_CHN_SMC1)))|
+ M8xx_SIMODE_SMCCS(chan - CONS_CHN_SMC1,new_brg));
+ }
+ }
+ return (new_brg < 0);
+}
+
+
+/*
+ * Hardware-dependent portion of tcsetattr().
+ */
+static int
+sccSetAttributes (int minor, const struct termios *t)
+{
+ int baud;
+
+ switch (t->c_cflag & CBAUD) {
+ default: baud = -1; break;
+ case B50: baud = 50; break;
+ case B75: baud = 75; break;
+ case B110: baud = 110; break;
+ case B134: baud = 134; break;
+ case B150: baud = 150; break;
+ case B200: baud = 200; break;
+ case B300: baud = 300; break;
+ case B600: baud = 600; break;
+ case B1200: baud = 1200; break;
+ case B1800: baud = 1800; break;
+ case B2400: baud = 2400; break;
+ case B4800: baud = 4800; break;
+ case B9600: baud = 9600; break;
+ case B19200: baud = 19200; break;
+ case B38400: baud = 38400; break;
+ case B57600: baud = 57600; break;
+ case B115200: baud = 115200; break;
+ case B230400: baud = 230400; break;
+ case B460800: baud = 460800; break;
+ }
+ return sccBRGalloc(minor,baud);
+ return 0;
+}
+
+/*
+ * Interrupt handler
+ */
+static rtems_isr
+sccInterruptHandler (rtems_vector_number v)
+{
+ int chan = 0;
+ /*
+ * calculate channel from vector
+ */
+ switch(v & M8xx_IVEC_SRC_MASK) {
+ case M8xx_IVEC_SRC_SCC1:
+ chan = CONS_CHN_SCC1;
+ break;
+ case M8xx_IVEC_SRC_SCC2:
+ chan = CONS_CHN_SCC2;
+ break;
+ case M8xx_IVEC_SRC_SCC3:
+ chan = CONS_CHN_SCC3;
+ break;
+ case M8xx_IVEC_SRC_SCC4:
+ chan = CONS_CHN_SCC4;
+ break;
+ case M8xx_IVEC_SRC_SMC1:
+ chan = CONS_CHN_SMC1;
+ break;
+ case M8xx_IVEC_SRC_SMC2:
+ chan = CONS_CHN_SMC2;
+ break;
+ }
+
+ /*
+ * Buffer received?
+ */
+ if (CHN_EVENT_GET(chan) & 0x1) {
+ /*
+ * clear SCC event flag
+ */
+ CHN_EVENT_CLR(chan,0x01);
+ /*
+ * process event
+ */
+ while ((sccCurrRxBd[chan]->status & M8xx_BD_EMPTY) == 0) {
+ if (sccttyp[chan] != NULL) {
+ rtems_cache_invalidate_multiple_data_lines((void *)sccCurrRxBd[chan]->buffer,
+ sccCurrRxBd[chan]->length);
+ rtems_termios_enqueue_raw_characters (sccttyp[chan],
+ (char *)sccCurrRxBd[chan]->buffer,
+ sccCurrRxBd[chan]->length);
+ }
+ /*
+ * clear status
+ */
+ sccCurrRxBd[chan]->status =
+ (sccCurrRxBd[chan]->status
+ & (M8xx_BD_WRAP | M8xx_BD_INTERRUPT))
+ | M8xx_BD_EMPTY;
+ /*
+ * advance to next BD
+ */
+ if ((sccCurrRxBd[chan]->status & M8xx_BD_WRAP) != 0) {
+ sccCurrRxBd[chan] = sccFrstRxBd[chan];
+ }
+ else {
+ sccCurrRxBd[chan]++;
+ }
+ }
+ }
+ /*
+ * Buffer transmitted?
+ */
+ if (CHN_EVENT_GET(chan) & 0x2) {
+ /*
+ * then clear interrupt event bit
+ */
+ CHN_EVENT_CLR(chan,0x2);
+ /*
+ * and signal successful transmit to termios
+ */
+ /*
+ * FIXME: multiple dequeue calls for multiple buffers
+ */
+ while((sccDequTxBd[chan] != sccPrepTxBd[chan]) &&
+ ((sccDequTxBd[chan]->status & M8xx_BD_READY) == 0)) {
+ if (sccttyp[chan] != NULL) {
+ rtems_termios_dequeue_characters (sccttyp[chan],
+ sccDequTxBd[chan]->length);
+ }
+ /*
+ * advance to next BD
+ */
+ if ((sccDequTxBd[chan]->status & M8xx_BD_WRAP) != 0) {
+ sccDequTxBd[chan] = sccFrstTxBd[chan];
+ }
+ else {
+ sccDequTxBd[chan]++;
+ }
+ }
+ }
+
+ m8xx.cisr = m8xx_console_chan_desc[chan].ireg_mask;/* Clear interrupt-in-service bit */
+}
+
+static void
+sccInitialize (int chan)
+{
+ int i;
+ /*
+ * allocate buffers
+ * FIXME: use a cache-line size boundary alloc here
+ */
+ rxBuf[chan] = malloc(sizeof(*rxBuf[chan]) + 2*PPC_CACHE_ALIGNMENT);
+ if (rxBuf[chan] == NULL) {
+ BSP_panic("Cannot allocate console rx buffer\n");
+ }
+ else {
+ /*
+ * round up rxBuf[chan] to start at a cache line size
+ */
+ rxBuf[chan] = (sccRxBuf_t *)
+ (((uint32_t)rxBuf[chan]) +
+ (PPC_CACHE_ALIGNMENT
+ - ((uint32_t)rxBuf[chan]) % PPC_CACHE_ALIGNMENT));
+ }
+ /*
+ * Allocate buffer descriptors
+ */
+ sccCurrRxBd[chan] =
+ sccFrstRxBd[chan] = m8xx_bd_allocate(SCC_RXBD_CNT);
+ sccPrepTxBd[chan] =
+ sccDequTxBd[chan] =
+ sccFrstTxBd[chan] = m8xx_bd_allocate(SCC_TXBD_CNT);
+ switch(chan) {
+ case CONS_CHN_SCC1:
+ /*
+ * Configure port A pins to enable TXD1 and RXD1 pins
+ * FIXME: add setup for modem control lines....
+ */
+ m8xx.papar |= 0x03;
+ m8xx.padir &= ~0x03;
+
+ /*
+ * Configure port C pins to enable RTS1 pins (static active low)
+ */
+ m8xx.pcpar &= ~0x01;
+ m8xx.pcso &= ~0x01;
+ m8xx.pcdir |= 0x01;
+ m8xx.pcdat &= ~0x01;
+ break;
+ case CONS_CHN_SCC2:
+ /*
+ * Configure port A pins to enable TXD2 and RXD2 pins
+ * FIXME: add setup for modem control lines....
+ */
+ m8xx.papar |= 0x0C;
+ m8xx.padir &= ~0x0C;
+
+ /*
+ * Configure port C pins to enable RTS2 pins (static active low)
+ */
+ m8xx.pcpar &= ~0x02;
+ m8xx.pcso &= ~0x02;
+ m8xx.pcdir |= 0x02;
+ m8xx.pcdat &= ~0x02;
+ break;
+ case CONS_CHN_SCC3:
+ /*
+ * Configure port A pins to enable TXD3 and RXD3 pins
+ * FIXME: add setup for modem control lines....
+ */
+ m8xx.papar |= 0x30;
+ m8xx.padir &= ~0x30;
+
+ /*
+ * Configure port C pins to enable RTS3 (static active low)
+ */
+ m8xx.pcpar &= ~0x04;
+ m8xx.pcso &= ~0x04;
+ m8xx.pcdir |= 0x04;
+ m8xx.pcdat &= ~0x04;
+ break;
+ case CONS_CHN_SCC4:
+ /*
+ * Configure port A pins to enable TXD4 and RXD4 pins
+ * FIXME: add setup for modem control lines....
+ */
+ m8xx.papar |= 0xC0;
+ m8xx.padir &= ~0xC0;
+
+ /*
+ * Configure port C pins to enable RTS4 pins (static active low)
+ */
+ m8xx.pcpar &= ~0x08;
+ m8xx.pcso &= ~0x08;
+ m8xx.pcdir |= 0x08;
+ m8xx.pcdat &= ~0x08;
+ break;
+ case CONS_CHN_SMC1:
+ /*
+ * Configure port B pins to enable SMTXD1 and SMRXD1 pins
+ */
+ m8xx.pbpar |= 0xC0;
+ m8xx.pbdir &= ~0xC0;
+ break;
+ case CONS_CHN_SMC2:
+ /*
+ * Configure port B pins to enable SMTXD2 and SMRXD2 pins
+ */
+ m8xx.pbpar |= 0xC00;
+ m8xx.pbdir &= ~0xC00;
+ break;
+ }
+ /*
+ * allocate and connect BRG
+ */
+ sccBRGalloc(chan,9600);
+
+
+ /*
+ * Set up SCCx parameter RAM common to all protocols
+ */
+ CHN_PARAM_SET(chan,rbase,(char *)sccFrstRxBd[chan] - (char *)&m8xx);
+ CHN_PARAM_SET(chan,tbase,(char *)sccFrstTxBd[chan] - (char *)&m8xx);
+ CHN_PARAM_SET(chan,rfcr ,M8xx_RFCR_MOT | M8xx_RFCR_DMA_SPACE(0));
+ CHN_PARAM_SET(chan,tfcr ,M8xx_TFCR_MOT | M8xx_TFCR_DMA_SPACE(0));
+ if (m8xx_scc_mode[chan] != TERMIOS_POLLED)
+ CHN_PARAM_SET(chan,mrblr,RXBUFSIZE);
+ else
+ CHN_PARAM_SET(chan,mrblr,1);
+
+ /*
+ * Set up SCCx parameter RAM UART-specific parameters
+ */
+ CHN_PARAM_SET(chan,un.uart.max_idl ,MAX_IDL_DEFAULT);
+ CHN_PARAM_SET(chan,un.uart.brkln ,0);
+ CHN_PARAM_SET(chan,un.uart.brkec ,0);
+ CHN_PARAM_SET(chan,un.uart.brkcr ,0);
+ if (m8xx_console_chan_desc[chan].is_scc) {
+ m8xx_console_chan_desc[chan].parms.sccp->un.uart.character[0]=0x8000; /* no char filter */
+ m8xx_console_chan_desc[chan].parms.sccp->un.uart.rccm=0x80FF; /* control character mask */
+ }
+
+ /*
+ * Set up the Receive Buffer Descriptors
+ */
+ for (i = 0;i < SCC_RXBD_CNT;i++) {
+ sccFrstRxBd[chan][i].status = M8xx_BD_EMPTY | M8xx_BD_INTERRUPT;
+ if (i == SCC_RXBD_CNT-1) {
+ sccFrstRxBd[chan][i].status |= M8xx_BD_WRAP;
+ }
+ sccFrstRxBd[chan][i].length = 0;
+ sccFrstRxBd[chan][i].buffer = rxBuf[chan][i];
+ }
+ /*
+ * Setup the Transmit Buffer Descriptor
+ */
+ for (i = 0;i < SCC_TXBD_CNT;i++) {
+ sccFrstTxBd[chan][i].status = M8xx_BD_INTERRUPT;
+ if (i == SCC_TXBD_CNT-1) {
+ sccFrstTxBd[chan][i].status |= M8xx_BD_WRAP;
+ }
+ sccFrstTxBd[chan][i].length = 0;
+ sccFrstTxBd[chan][i].buffer = NULL;
+ }
+
+ /*
+ * Set up SCC general and protocol-specific mode registers
+ */
+ CHN_EVENT_CLR(chan,~0); /* Clear any pending events */
+ CHN_MASK_SET(chan,0); /* Mask all interrupt/event sources */
+
+ if (m8xx_console_chan_desc[chan].is_scc) {
+ m8xx_console_chan_desc[chan].regs.sccr->psmr = 0xb000; /* 8N1, CTS flow control */
+ m8xx_console_chan_desc[chan].regs.sccr->gsmr_h = 0x00000000;
+ m8xx_console_chan_desc[chan].regs.sccr->gsmr_l = 0x00028004; /* UART mode */
+ }
+ else {
+ m8xx_console_chan_desc[chan].regs.smcr->smcmr = 0x4820;
+ }
+ /*
+ * Send "Init parameters" command
+ */
+ m8xx_cp_execute_cmd(M8xx_CR_OP_INIT_RX_TX
+ | m8xx_console_chan_desc[chan].cr_chan_code);
+
+ /*
+ * Enable receiver and transmitter
+ */
+ if (m8xx_console_chan_desc[chan].is_scc) {
+ m8xx_console_chan_desc[chan].regs.sccr->gsmr_l |= 0x00000030;
+ }
+ else {
+ m8xx_console_chan_desc[chan].regs.smcr->smcmr |= 0x0003;
+ }
+
+ if (m8xx_scc_mode[chan] != TERMIOS_POLLED) {
+ rtems_isr_entry old_handler;
+ rtems_status_code sc;
+
+ sc = rtems_interrupt_catch (sccInterruptHandler,
+ m8xx_console_chan_desc[chan].ivec_src
+ | (m8xx.cicr & 0xE0),
+ &old_handler);
+ CHN_MASK_SET(chan,3); /* Enable TX and RX interrupts */
+ m8xx.cimr |= m8xx_console_chan_desc[chan].ireg_mask; /* Enable interrupts */
+ }
+}
+
+/*
+ * polled scc read function
+ */
+static int
+sccPollRead (int minor)
+{
+ unsigned char c;
+ int chan = minor;
+
+ if ((sccCurrRxBd[chan]->status & M8xx_BD_EMPTY) != 0) {
+ return -1;
+ }
+ rtems_cache_invalidate_multiple_data_lines((void *)sccCurrRxBd[chan]->buffer,
+ sccCurrRxBd[chan]->length);
+ c = *((char *)sccCurrRxBd[chan]->buffer);
+ /*
+ * clear status
+ */
+ sccCurrRxBd[chan]->status =
+ (sccCurrRxBd[chan]->status
+ & (M8xx_BD_WRAP | M8xx_BD_INTERRUPT))
+ | M8xx_BD_EMPTY;
+ /*
+ * advance to next BD
+ */
+ if ((sccCurrRxBd[chan]->status & M8xx_BD_WRAP) != 0) {
+ sccCurrRxBd[chan] = sccFrstRxBd[chan];
+ }
+ else {
+ sccCurrRxBd[chan]++;
+ }
+ return c;
+}
+
+
+/*
+ * Device-dependent write routine
+ * Interrupt-driven devices:
+ * Begin transmission of as many characters as possible (minimum is 1).
+ * Polling devices:
+ * Transmit all characters.
+ */
+static int
+sccInterruptWrite (int minor, const char *buf, int len)
+{
+ int chan = minor;
+
+ if ((sccPrepTxBd[chan]->status & M8xx_BD_READY) == 0) {
+ sccPrepTxBd[chan]->buffer = (char *)buf;
+ sccPrepTxBd[chan]->length = len;
+ rtems_cache_flush_multiple_data_lines((const void *)buf,len);
+ /*
+ * clear status, set ready bit
+ */
+ sccPrepTxBd[chan]->status =
+ (sccPrepTxBd[chan]->status
+ & M8xx_BD_WRAP)
+ | M8xx_BD_READY | M8xx_BD_INTERRUPT;
+ if ((sccPrepTxBd[chan]->status & M8xx_BD_WRAP) != 0) {
+ sccPrepTxBd[chan] = sccFrstTxBd[chan];
+ }
+ else {
+ sccPrepTxBd[chan]++;
+ }
+ }
+ return 0;
+}
+
+static int
+sccPollWrite (int minor, const char *buf, int len)
+{
+ int chan = minor;
+ int bd_used;
+
+ while (len--) {
+ static char txBuf[CONS_CHN_CNT][SCC_TXBD_CNT];
+ while (sccPrepTxBd[chan]->status & M8xx_BD_READY)
+ continue;
+ bd_used = sccPrepTxBd[chan]-sccFrstTxBd[chan];
+ txBuf[chan][bd_used] = *buf++;
+ rtems_cache_flush_multiple_data_lines((const void *)&txBuf[chan][bd_used],
+ sizeof(txBuf[chan][bd_used]));
+ sccPrepTxBd[chan]->buffer = &(txBuf[chan][bd_used]);
+ sccPrepTxBd[chan]->length = 1;
+ sccPrepTxBd[chan]->status =
+ (sccPrepTxBd[chan]->status
+ & M8xx_BD_WRAP)
+ | M8xx_BD_READY;
+ if ((sccPrepTxBd[chan]->status & M8xx_BD_WRAP) != 0) {
+ sccPrepTxBd[chan] = sccFrstTxBd[chan];
+ }
+ else {
+ sccPrepTxBd[chan]++;
+ }
+ }
+ return 0;
+}
+
+/*
+***************
+* BOILERPLATE *
+***************
+*/
+
+struct {
+ rtems_device_minor_number minor;
+ int driver_mode;
+} channel_list[] = {
+ {CONS_CHN_SMC1,CONS_SMC1_MODE},
+ {CONS_CHN_SMC2,CONS_SMC2_MODE},
+ {CONS_CHN_SCC1,CONS_SCC1_MODE},
+ {CONS_CHN_SCC2,CONS_SCC2_MODE},
+ {CONS_CHN_SCC3,CONS_SCC3_MODE},
+ {CONS_CHN_SCC4,CONS_SCC4_MODE}
+};
+
+
+/*
+ * Initialize and register the device
+ */
+rtems_device_driver console_initialize(rtems_device_major_number major,
+ rtems_device_minor_number minor,/* ignored */
+ void *arg
+ )
+{
+ rtems_status_code status = RTEMS_SUCCESSFUL;
+ int chan,entry,ttynum;
+ char tty_name[] = "/dev/tty00";
+
+ /*
+ * init base clock for BRGs
+ * (if not already set by debugger etc)
+ */
+ if (m8xx_clock_rate == 0) {
+ m8xx_clock_rate = BSP_bus_frequency;
+ }
+ /*
+ * Set up TERMIOS
+ */
+ rtems_termios_initialize ();
+ /*
+ * init BRG allocataion
+ */
+ sccBRGinit();
+ ttynum = 0;
+ for (entry = 0;
+ (entry < sizeof(channel_list)/sizeof(channel_list[0]))
+ && (status == RTEMS_SUCCESSFUL);
+ entry++) {
+ if (channel_list[entry].driver_mode != CONS_MODE_UNUSED) {
+ /*
+ * Do device-specific initialization
+ */
+ chan = channel_list[entry].minor;
+ m8xx_scc_mode[chan] = channel_list[entry].driver_mode;
+ sccInitialize (chan);
+
+ /*
+ * build device name
+ */
+ tty_name[sizeof(tty_name)-2] = '0'+ttynum;
+ ttynum++;
+ /*
+ * Register the device
+ */
+ status = rtems_io_register_name (tty_name,
+ major,
+ channel_list[entry].minor);
+ if (status != RTEMS_SUCCESSFUL) {
+ rtems_fatal_error_occurred (status);
+ }
+ }
+ }
+ /*
+ * register /dev/console
+ */
+ status = rtems_io_register_name ("/dev/console",
+ major,
+ CONSOLE_CHN);
+ if (status != RTEMS_SUCCESSFUL) {
+ rtems_fatal_error_occurred (status);
+ }
+ /*
+ * FIXME: enable printk support
+ */
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Open the device
+ */
+rtems_device_driver console_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+ )
+{
+ rtems_status_code status;
+ int chan = minor;
+ rtems_libio_open_close_args_t *args = (rtems_libio_open_close_args_t *)arg;
+ static const rtems_termios_callbacks interruptCallbacks = {
+ NULL, /* firstOpen */
+ NULL, /* lastClose */
+ NULL, /* pollRead */
+ sccInterruptWrite, /* write */
+ sccSetAttributes, /* setAttributes */
+ NULL, /* stopRemoteTx */
+ NULL, /* startRemoteTx */
+ TERMIOS_IRQ_DRIVEN /* outputUsesInterrupts */
+ };
+ static const rtems_termios_callbacks pollCallbacks = {
+ NULL, /* firstOpen */
+ NULL, /* lastClose */
+ sccPollRead, /* pollRead */
+ sccPollWrite, /* write */
+ sccSetAttributes, /* setAttributes */
+ NULL, /* stopRemoteTx */
+ NULL, /* startRemoteTx */
+ 0 /* outputUsesInterrupts */
+ };
+
+ if (m8xx_scc_mode[chan] == TERMIOS_IRQ_DRIVEN) {
+ status = rtems_termios_open (major, minor, arg, &interruptCallbacks);
+ sccttyp[chan] = args->iop->data1;
+ }
+ else {
+ status = rtems_termios_open (major, minor, arg, &pollCallbacks);
+ sccttyp[chan] = args->iop->data1;
+ }
+ return status;
+}
+
+/*
+ * Close the device
+ */
+rtems_device_driver console_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+ )
+{
+ rtems_status_code rc;
+
+ rc = rtems_termios_close (arg);
+ sccttyp[minor] = NULL;
+
+ return rc;
+
+}
+
+/*
+ * 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);
+}
+
+#if 0
+static int scc_io_set_trm_char(rtems_device_minor_number minor,
+ rtems_libio_ioctl_args_t *ioa)
+{
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+ con360_io_trm_char_t *trm_char_info = ioa->buffer;
+
+ printf("ioctl called: maxidl=%d\n",trm_char_info->max_idl);
+ printf("ioctl called: char_cnt=%d\n",trm_char_info->char_cnt);
+ /*
+ * check, that parameter is non-NULL
+ */
+ if ((rc == RTEMS_SUCCESSFUL) &&
+ (trm_char_info == NULL)) {
+ rc = RTEMS_INVALID_ADDRESS;
+ }
+ /*
+ * transfer max_idl
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ if (trm_char_info->max_idl >= 0x10000) {
+ printf("ioctl called: invalid number for maxidl\n");
+ rc = RTEMS_INVALID_NUMBER;
+ }
+ else if (trm_char_info->max_idl > 0) {
+ CHN_PARAM_SET(minor,un.uart.max_idl ,trm_char_info->max_idl);
+ }
+ else if (trm_char_info->max_idl == 0) {
+ CHN_PARAM_SET(minor,un.uart.max_idl ,MAX_IDL_DEFAULT);
+ }
+ }
+ /*
+ * transfer characters
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ if (trm_char_info->char_cnt > CON8XX_TRM_CHAR_CNT) {
+ printf("ioctl called: invalid number for char_cnt\n");
+ rc = RTEMS_TOO_MANY;
+ }
+ else if (trm_char_info->char_cnt >= 0) {
+ /*
+ * check, whether device is a SCC
+ */
+ if ((rc == RTEMS_SUCCESSFUL) &&
+ !m8xx_console_chan_desc[minor].is_scc) {
+ printf("ioctl called: not an scc:%d\n",minor);
+ rc = RTEMS_UNSATISFIED;
+ }
+ else {
+ int idx = 0;
+ for(idx = 0;idx < trm_char_info->char_cnt;idx++) {
+ m8xx_console_chan_desc[minor].parms.sccp->un.uart.character[idx] =
+ trm_char_info->character[idx] & 0x00ff;
+ }
+ if (trm_char_info->char_cnt < CON8XX_TRM_CHAR_CNT) {
+ m8xx_console_chan_desc[minor].parms.sccp
+ ->un.uart.character[trm_char_info->char_cnt] = 0x8000;
+ }
+ }
+ }
+ }
+
+ printf("ioctl called: return code: %d\n",rc);
+ return rc;
+}
+#endif
+
+/*
+ * Handle ioctl request.
+ */
+rtems_device_driver console_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+ )
+{
+ rtems_libio_ioctl_args_t *ioa=arg;
+
+ switch (ioa->command) {
+#if 0
+ case CON8XX_IO_SET_TRM_CHAR:
+ return scc_io_set_trm_char(minor, ioa);
+#endif
+ default:
+ return rtems_termios_ioctl (arg);
+ break;
+ }
+}
+
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/include/8xx_immap.h b/c/src/lib/libbsp/powerpc/tqm8xx/include/8xx_immap.h
new file mode 100644
index 0000000000..de4be69690
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/include/8xx_immap.h
@@ -0,0 +1,477 @@
+/*===============================================================*\
+| Project: RTEMS BSP support for TQ modules |
++-----------------------------------------------------------------+
+| Partially based on the code references which are named below. |
+| Adaptions, modifications, enhancements and any recent parts of |
+| the code are: |
+| Copyright (c) 2007 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains definitions to interact with TQC's |
+| processor modules |
+\*===============================================================*/
+/* derived from mbx8xx BSP */
+/*
+ * MPC8xx Internal Memory Map
+ * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
+ *
+ * The I/O on the MPC860 is comprised of blocks of special registers
+ * and the dual port ram for the Communication Processor Module.
+ * Within this space are functional units such as the SIU, memory
+ * controller, system timers, and other control functions. It is
+ * a combination that I found difficult to separate into logical
+ * functional files.....but anyone else is welcome to try. -- Dan
+ */
+#ifndef __IMMAP_8XX__
+#define __IMMAP_8XX__
+
+/* System configuration registers.
+*/
+typedef struct sys_conf {
+ unsigned int sc_siumcr;
+ unsigned int sc_sypcr;
+ unsigned int sc_swt;
+ char res1[2];
+ unsigned short sc_swsr;
+ unsigned int sc_sipend;
+ unsigned int sc_simask;
+ unsigned int sc_siel;
+ unsigned int sc_sivec;
+ unsigned int sc_tesr;
+ char res2[0xc];
+ unsigned int sc_sdcr;
+ char res3[0x4c];
+} sysconf8xx_t;
+
+/* PCMCIA configuration registers.
+*/
+typedef struct pcmcia_conf {
+ unsigned int pcmc_pbr0;
+ unsigned int pcmc_por0;
+ unsigned int pcmc_pbr1;
+ unsigned int pcmc_por1;
+ unsigned int pcmc_pbr2;
+ unsigned int pcmc_por2;
+ unsigned int pcmc_pbr3;
+ unsigned int pcmc_por3;
+ unsigned int pcmc_pbr4;
+ unsigned int pcmc_por4;
+ unsigned int pcmc_pbr5;
+ unsigned int pcmc_por5;
+ unsigned int pcmc_pbr6;
+ unsigned int pcmc_por6;
+ unsigned int pcmc_pbr7;
+ unsigned int pcmc_por7;
+ char res1[0x20];
+ unsigned int pcmc_pgcra;
+ unsigned int pcmc_pgcrb;
+ unsigned int pcmc_pscr;
+ char res2[4];
+ unsigned int pcmc_pipr;
+ char res3[4];
+ unsigned int pcmc_per;
+ char res4[4];
+} pcmconf8xx_t;
+
+/* Memory controller registers.
+*/
+typedef struct mem_ctlr {
+ unsigned int memc_br0;
+ unsigned int memc_or0;
+ unsigned int memc_br1;
+ unsigned int memc_or1;
+ unsigned int memc_br2;
+ unsigned int memc_or2;
+ unsigned int memc_br3;
+ unsigned int memc_or3;
+ unsigned int memc_br4;
+ unsigned int memc_or4;
+ unsigned int memc_br5;
+ unsigned int memc_or5;
+ unsigned int memc_br6;
+ unsigned int memc_or6;
+ unsigned int memc_br7;
+ unsigned int memc_or7;
+ char res1[0x24];
+ unsigned int memc_mar;
+ unsigned int memc_mcr;
+ char res2[4];
+ unsigned int memc_mamr;
+ unsigned int memc_mbmr;
+ unsigned short memc_mstat;
+ unsigned short memc_mptpr;
+ unsigned int memc_mdr;
+ char res3[0x80];
+} memctl8xx_t;
+
+/* System Integration Timers.
+*/
+typedef struct sys_int_timers {
+ unsigned short sit_tbscr;
+ unsigned int sit_tbreff0;
+ unsigned int sit_tbreff1;
+ char res1[0x14];
+ unsigned short sit_rtcsc;
+ unsigned int sit_rtc;
+ unsigned int sit_rtsec;
+ unsigned int sit_rtcal;
+ char res2[0x10];
+ unsigned short sit_piscr;
+ char res3[2];
+ unsigned int sit_pitc;
+ unsigned int sit_pitr;
+ char res4[0x34];
+} sit8xx_t;
+
+#define TBSCR_TBIRQ_MASK ((unsigned short)0xff00)
+#define TBSCR_REFA ((unsigned short)0x0080)
+#define TBSCR_REFB ((unsigned short)0x0040)
+#define TBSCR_REFAE ((unsigned short)0x0008)
+#define TBSCR_REFBE ((unsigned short)0x0004)
+#define TBSCR_TBF ((unsigned short)0x0002)
+#define TBSCR_TBE ((unsigned short)0x0001)
+
+#define RTCSC_RTCIRQ_MASK ((unsigned short)0xff00)
+#define RTCSC_SEC ((unsigned short)0x0080)
+#define RTCSC_ALR ((unsigned short)0x0040)
+#define RTCSC_38K ((unsigned short)0x0010)
+#define RTCSC_SIE ((unsigned short)0x0008)
+#define RTCSC_ALE ((unsigned short)0x0004)
+#define RTCSC_RTF ((unsigned short)0x0002)
+#define RTCSC_RTE ((unsigned short)0x0001)
+
+#define PISCR_PIRQ_MASK ((unsigned short)0xff00)
+#define PISCR_PS ((unsigned short)0x0080)
+#define PISCR_PIE ((unsigned short)0x0004)
+#define PISCR_PTF ((unsigned short)0x0002)
+#define PISCR_PTE ((unsigned short)0x0001)
+
+/* Clocks and Reset.
+*/
+typedef struct clk_and_reset {
+ unsigned int car_sccr;
+ unsigned int car_plprcr;
+ unsigned int car_rsr;
+ char res[0x74]; /* Reserved area */
+} car8xx_t;
+
+/* System Integration Timers keys.
+*/
+typedef struct sitk {
+ unsigned int sitk_tbscrk;
+ unsigned int sitk_tbreff0k;
+ unsigned int sitk_tbreff1k;
+ unsigned int sitk_tbk;
+ char res1[0x10];
+ unsigned int sitk_rtcsck;
+ unsigned int sitk_rtck;
+ unsigned int sitk_rtseck;
+ unsigned int sitk_rtcalk;
+ char res2[0x10];
+ unsigned int sitk_piscrk;
+ unsigned int sitk_pitck;
+ char res3[0x38];
+} sitk8xx_t;
+
+/* Clocks and reset keys.
+*/
+typedef struct cark {
+ unsigned int cark_sccrk;
+ unsigned int cark_plprcrk;
+ unsigned int cark_rsrk;
+ char res[0x474];
+} cark8xx_t;
+
+/* The key to unlock registers maintained by keep-alive power.
+*/
+#define KAPWR_KEY ((unsigned int)0x55ccaa33)
+
+/* LCD interface. MPC821 Only.
+*/
+typedef struct lcd {
+ unsigned short lcd_lcolr[16];
+ char res[0x20];
+ unsigned int lcd_lccr;
+ unsigned int lcd_lchcr;
+ unsigned int lcd_lcvcr;
+ char res2[4];
+ unsigned int lcd_lcfaa;
+ unsigned int lcd_lcfba;
+ char lcd_lcsr;
+ char res3[0x7];
+} lcd8xx_t;
+
+/* I2C
+*/
+typedef struct i2c {
+ unsigned char i2c_i2mod;
+ char res1[3];
+ unsigned char i2c_i2add;
+ char res2[3];
+ unsigned char i2c_i2brg;
+ char res3[3];
+ unsigned char i2c_i2com;
+ char res4[3];
+ unsigned char i2c_i2cer;
+ char res5[3];
+ unsigned char i2c_i2cmr;
+ char res6[0x8b];
+} i2c8xx_t;
+
+/* DMA control/status registers.
+*/
+typedef struct sdma_csr {
+ char res1[4];
+ unsigned int sdma_sdar;
+ unsigned char sdma_sdsr;
+ char res3[3];
+ unsigned char sdma_sdmr;
+ char res4[3];
+ unsigned char sdma_idsr1;
+ char res5[3];
+ unsigned char sdma_idmr1;
+ char res6[3];
+ unsigned char sdma_idsr2;
+ char res7[3];
+ unsigned char sdma_idmr2;
+ char res8[0x13];
+} sdma8xx_t;
+
+/* Communication Processor Module Interrupt Controller.
+*/
+typedef struct cpm_ic {
+ unsigned short cpic_civr;
+ char res[0xe];
+ unsigned int cpic_cicr;
+ unsigned int cpic_cipr;
+ unsigned int cpic_cimr;
+ unsigned int cpic_cisr;
+} cpic8xx_t;
+
+/* Input/Output Port control/status registers.
+*/
+typedef struct io_port {
+ unsigned short iop_padir;
+ unsigned short iop_papar;
+ unsigned short iop_paodr;
+ unsigned short iop_padat;
+ char res1[8];
+ unsigned short iop_pcdir;
+ unsigned short iop_pcpar;
+ unsigned short iop_pcso;
+ unsigned short iop_pcdat;
+ unsigned short iop_pcint;
+ char res2[6];
+ unsigned short iop_pddir;
+ unsigned short iop_pdpar;
+ char res3[2];
+ unsigned short iop_pddat;
+ char res4[8];
+} iop8xx_t;
+
+/* Communication Processor Module Timers
+*/
+typedef struct cpm_timers {
+ unsigned short cpmt_tgcr;
+ char res1[0xe];
+ unsigned short cpmt_tmr1;
+ unsigned short cpmt_tmr2;
+ unsigned short cpmt_trr1;
+ unsigned short cpmt_trr2;
+ unsigned short cpmt_tcr1;
+ unsigned short cpmt_tcr2;
+ unsigned short cpmt_tcn1;
+ unsigned short cpmt_tcn2;
+ unsigned short cpmt_tmr3;
+ unsigned short cpmt_tmr4;
+ unsigned short cpmt_trr3;
+ unsigned short cpmt_trr4;
+ unsigned short cpmt_tcr3;
+ unsigned short cpmt_tcr4;
+ unsigned short cpmt_tcn3;
+ unsigned short cpmt_tcn4;
+ unsigned short cpmt_ter1;
+ unsigned short cpmt_ter2;
+ unsigned short cpmt_ter3;
+ unsigned short cpmt_ter4;
+ char res2[8];
+} cpmtimer8xx_t;
+
+/* Finally, the Communication Processor stuff.....
+*/
+typedef struct scc { /* Serial communication channels */
+ unsigned int scc_gsmrl;
+ unsigned int scc_gsmrh;
+ unsigned short scc_pmsr;
+ char res1[2];
+ unsigned short scc_todr;
+ unsigned short scc_dsr;
+ unsigned short scc_scce;
+ char res2[2];
+ unsigned short scc_sccm;
+ char res3;
+ unsigned char scc_sccs;
+ char res4[8];
+} scc_t;
+
+typedef struct smc { /* Serial management channels */
+ char res1[2];
+ unsigned short smc_smcmr;
+ char res2[2];
+ unsigned char smc_smce;
+ char res3[3];
+ unsigned char smc_smcm;
+ char res4[5];
+} smc_t;
+
+/* MPC860T Fast Ethernet Controller. It isn't part of the CPM, but
+ * it fits within the address space.
+ */
+typedef struct fec {
+ unsigned int fec_addr_low; /* LS 32 bits of station address */
+ unsigned short fec_addr_high; /* MS 16 bits of address */
+ unsigned short res1;
+ unsigned int fec_hash_table_high;
+ unsigned int fec_hash_table_low;
+ unsigned int fec_r_des_start;
+ unsigned int fec_x_des_start;
+ unsigned int fec_r_buff_size;
+ unsigned int res2[9];
+ unsigned int fec_ecntrl;
+ unsigned int fec_ievent;
+ unsigned int fec_imask;
+ unsigned int fec_ivec;
+ unsigned int fec_r_des_active;
+ unsigned int fec_x_des_active;
+ unsigned int res3[10];
+ unsigned int fec_mii_data;
+ unsigned int fec_mii_speed;
+ unsigned int res4[17];
+ unsigned int fec_r_bound;
+ unsigned int fec_r_fstart;
+ unsigned int res5[6];
+ unsigned int fec_x_fstart;
+ unsigned int res6[17];
+ unsigned int fec_fun_code;
+ unsigned int res7[3];
+ unsigned int fec_r_cntrl;
+ unsigned int fec_r_hash;
+ unsigned int res8[14];
+ unsigned int fec_x_cntrl;
+ unsigned int res9[0x1e];
+} fec_t;
+
+typedef struct comm_proc {
+ /* General control and status registers.
+ */
+ unsigned short cp_cpcr;
+ char res1[2];
+ unsigned short cp_rccr;
+ char res2[6];
+ unsigned short cp_cpmcr1;
+ unsigned short cp_cpmcr2;
+ unsigned short cp_cpmcr3;
+ unsigned short cp_cpmcr4;
+ char res3[2];
+ unsigned short cp_rter;
+ char res4[2];
+ unsigned short cp_rtmr;
+ char res5[0x14];
+
+ /* Baud rate generators.
+ */
+ unsigned int cp_brgc1;
+ unsigned int cp_brgc2;
+ unsigned int cp_brgc3;
+ unsigned int cp_brgc4;
+
+ /* Serial Communication Channels.
+ */
+ scc_t cp_scc[4];
+
+ /* Serial Management Channels.
+ */
+ smc_t cp_smc[2];
+
+ /* Serial Peripheral Interface.
+ */
+ unsigned short cp_spmode;
+ char res6[4];
+ unsigned char cp_spie;
+ char res7[3];
+ unsigned char cp_spim;
+ char res8[2];
+ unsigned char cp_spcom;
+ char res9[2];
+
+ /* Parallel Interface Port.
+ */
+ char res10[2];
+ unsigned short cp_pipc;
+ char res11[2];
+ unsigned short cp_ptpr;
+ unsigned int cp_pbdir;
+ unsigned int cp_pbpar;
+ char res12[2];
+ unsigned short cp_pbodr;
+ unsigned int cp_pbdat;
+ char res13[0x18];
+
+ /* Serial Interface and Time Slot Assignment.
+ */
+ unsigned int cp_simode;
+ unsigned char cp_sigmr;
+ char res14;
+ unsigned char cp_sistr;
+ unsigned char cp_sicmr;
+ char res15[4];
+ unsigned int cp_sicr;
+ unsigned int cp_sirp;
+ char res16[0x10c];
+ unsigned char cp_siram[0x200];
+
+ /* The fast ethernet controller is not really part of the CPM,
+ * but it resides in the address space.
+ */
+ fec_t cp_fec;
+ char res18[0x1000];
+
+ /* Dual Ported RAM follows.
+ * There are many different formats for this memory area
+ * depending upon the devices used and options chosen.
+ */
+ unsigned char cp_dpmem[0x1000]; /* BD / Data / ucode */
+ unsigned char res19[0xc00];
+ unsigned char cp_dparam[0x400]; /* Parameter RAM */
+} cpm8xx_t;
+
+/* Internal memory map.
+*/
+typedef struct immap {
+ sysconf8xx_t im_siu_conf; /* SIU Configuration */
+ pcmconf8xx_t im_pcmcia; /* PCMCIA Configuration */
+ memctl8xx_t im_memctl; /* Memory Controller */
+ sit8xx_t im_sit; /* System integration timers */
+ car8xx_t im_clkrst; /* Clocks and reset */
+ sitk8xx_t im_sitk; /* Sys int timer keys */
+ cark8xx_t im_clkrstk; /* Clocks and reset keys */
+ lcd8xx_t im_lcd; /* LCD (821 only) */
+ i2c8xx_t im_i2c; /* I2C control/status */
+ sdma8xx_t im_sdma; /* SDMA control/status */
+ cpic8xx_t im_cpic; /* CPM Interrupt Controller */
+ iop8xx_t im_ioport; /* IO Port control/status */
+ cpmtimer8xx_t im_cpmtimer; /* CPM timers */
+ cpm8xx_t im_cpm; /* Communication processor */
+} immap_t;
+
+#endif /* __IMMAP_8XX__ */
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/include/bsp.h b/c/src/lib/libbsp/powerpc/tqm8xx/include/bsp.h
new file mode 100644
index 0000000000..115ed6392c
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/include/bsp.h
@@ -0,0 +1,172 @@
+/*===============================================================*\
+| Project: RTEMS TQM8xx BSP |
++-----------------------------------------------------------------+
+| This file has been adapted to MPC8xx by |
+| Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> |
+| Copyright (c) 2008 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
+| |
+| See the other copyright notice below for the original parts. |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the console driver |
+\*===============================================================*/
+/* derived from MBX8xx BSP: */
+/* 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).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _BSP_H
+#define _BSP_H
+
+/*
+ * indicate, that BSP is booted via TQMMon
+ */
+#define BSP_HAS_TQMMON
+
+LINKER_SYMBOL(TopRamReserved);
+
+LINKER_SYMBOL( bsp_ram_start);
+LINKER_SYMBOL( bsp_ram_end);
+LINKER_SYMBOL( bsp_ram_size);
+
+LINKER_SYMBOL( bsp_rom_start);
+LINKER_SYMBOL( bsp_rom_end);
+LINKER_SYMBOL( bsp_rom_size);
+
+LINKER_SYMBOL( bsp_section_text_start);
+LINKER_SYMBOL( bsp_section_text_end);
+LINKER_SYMBOL( bsp_section_text_size);
+
+LINKER_SYMBOL( bsp_section_data_start);
+LINKER_SYMBOL( bsp_section_data_end);
+LINKER_SYMBOL( bsp_section_data_size);
+
+LINKER_SYMBOL( bsp_section_bss_start);
+LINKER_SYMBOL( bsp_section_bss_end);
+LINKER_SYMBOL( bsp_section_bss_size);
+
+LINKER_SYMBOL( bsp_interrupt_stack_start);
+LINKER_SYMBOL( bsp_interrupt_stack_end);
+LINKER_SYMBOL( bsp_interrupt_stack_size);
+
+LINKER_SYMBOL( bsp_work_area_start);
+
+#ifndef ASM
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <bspopts.h>
+
+#include <rtems.h>
+#include <rtems/console.h>
+#include <rtems/clockdrv.h>
+#include <mpc8xx.h>
+#include <mpc8xx/cpm.h>
+#include <mpc8xx/mmu.h>
+#include <mpc8xx/console.h>
+#include <bsp/vectors.h>
+#include <bsp/tqm.h>
+#include <libcpu/powerpc-utility.h>
+
+/*
+ * Network driver configuration
+ */
+struct rtems_bsdnet_ifconfig;
+
+#if BSP_USE_NETWORK_FEC
+extern int rtems_fec_enet_driver_attach (struct rtems_bsdnet_ifconfig *config,
+ int attaching);
+#define RTEMS_BSP_FEC_NETWORK_DRIVER_NAME "fec1"
+#define RTEMS_BSP_FEC_NETWORK_DRIVER_ATTACH rtems_fec_enet_driver_attach
+#endif
+
+#if BSP_USE_NETWORK_SCC
+extern int rtems_scc_enet_driver_attach (struct rtems_bsdnet_ifconfig *config,
+ int attaching);
+#define RTEMS_BSP_SCC_NETWORK_DRIVER_NAME "scc1"
+#define RTEMS_BSP_SCC_NETWORK_DRIVER_ATTACH rtems_scc_enet_driver_attach
+#endif
+
+#if BSP_USE_NETWORK_FEC
+#define RTEMS_BSP_NETWORK_DRIVER_NAME RTEMS_BSP_FEC_NETWORK_DRIVER_NAME
+#define RTEMS_BSP_NETWORK_DRIVER_ATTACH RTEMS_BSP_FEC_NETWORK_DRIVER_ATTACH
+#elif BSP_USE_NETWORK_SCC
+#define RTEMS_BSP_NETWORK_DRIVER_NAME RTEMS_BSP_SCC_NETWORK_DRIVER_NAME
+#define RTEMS_BSP_NETWORK_DRIVER_ATTACH RTEMS_BSP_SCC_NETWORK_DRIVER_ATTACH
+#endif
+/*
+ * 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
+
+/* miscellaneous stuff assumed to exist */
+
+/*
+ * Device Driver Table Entries
+ */
+
+/*
+ * NOTE: Use the standard Console driver entry
+ */
+
+/*
+ * NOTE: Use the standard Clock driver entry
+ */
+
+/*
+ * indicate, that BSP has IDE driver
+ */
+#undef RTEMS_BSP_HAS_IDE_DRIVER
+
+/*
+ * How many libio files we want
+ */
+
+#define BSP_LIBIO_MAX_FDS 20
+
+/*
+ * our bus frequency
+ */
+extern unsigned int BSP_bus_frequency;
+
+/* 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 */
+);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/include/coverhd.h b/c/src/lib/libbsp/powerpc/tqm8xx/include/coverhd.h
new file mode 100644
index 0000000000..543accb2e5
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/include/coverhd.h
@@ -0,0 +1,362 @@
+/* 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).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __COVERHD_h
+#define __COVERHD_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#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
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/include/irq-config.h b/c/src/lib/libbsp/powerpc/tqm8xx/include/irq-config.h
new file mode 100644
index 0000000000..cdfdfa9dc0
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/include/irq-config.h
@@ -0,0 +1,101 @@
+/*===============================================================*\
+| Project: RTEMS TQM8xx BSP |
++-----------------------------------------------------------------+
+| This file has been adapted to MPC8xx by |
+| Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> |
+| Copyright (c) 2008 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
+| |
+| See the other copyright notice below for the original parts. |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the console driver |
+\*===============================================================*/
+/* derived from: generic MPC83xx BSP */
+/**
+ * @file
+ *
+ * @ingroup bsp_interrupt
+ *
+ * @brief BSP interrupt support configuration.
+ */
+
+/*
+ * Copyright (c) 2008
+ * Embedded Brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * rtems@embedded-brains.de
+ *
+ * The license and distribution terms for this file may be found in the file
+ * LICENSE in this distribution or at http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_POWERPC_TQM8XX_IRQ_CONFIG_H
+#define LIBBSP_POWERPC_TQM8XX_IRQ_CONFIG_H
+
+#include <stdint.h>
+
+#include <bsp/irq.h>
+
+/**
+ * @addtogroup bsp_interrupt
+ *
+ * @{
+ */
+
+/**
+ * @brief Minimum vector number.
+ */
+#define BSP_INTERRUPT_VECTOR_MIN BSP_LOWEST_OFFSET
+
+/**
+ * @brief Maximum vector number.
+ */
+#define BSP_INTERRUPT_VECTOR_MAX BSP_MAX_OFFSET
+
+/**
+ * @brief Enables the index table.
+ *
+ * If you enable the index table, you have to define a size for the handler
+ * table (@ref BSP_INTERRUPT_HANDLER_TABLE_SIZE) and must provide an integer
+ * type capable to index the complete handler table (@ref
+ * bsp_interrupt_handler_index_type).
+ */
+#undef BSP_INTERRUPT_USE_INDEX_TABLE
+
+/**
+ * @brief Disables usage of the heap.
+ *
+ * If you define this, you have to define @ref BSP_INTERRUPT_USE_INDEX_TABLE as
+ * well.
+ */
+#undef BSP_INTERRUPT_NO_HEAP_USAGE
+
+#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
+
+/**
+ * @brief Size of the handler table.
+ */
+#define BSP_INTERRUPT_HANDLER_TABLE_SIZE 63
+
+/**
+ * @brief Integer type capable to index the complete handler table.
+ */
+typedef uint8_t bsp_interrupt_handler_index_type;
+
+#endif /* BSP_INTERRUPT_USE_INDEX_TABLE */
+
+/** @} */
+
+#endif /* LIBBSP_POWERPC_TQM8XX_IRQ_CONFIG_H */
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/include/irq.h b/c/src/lib/libbsp/powerpc/tqm8xx/include/irq.h
new file mode 100644
index 0000000000..2ada75bd43
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/include/irq.h
@@ -0,0 +1,154 @@
+/*===============================================================*\
+| Project: RTEMS TQM8xx BSP |
++-----------------------------------------------------------------+
+| This file has been adapted to MPC8xx by |
+| Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> |
+| Copyright (c) 2008 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
+| |
+| See the other copyright notice below for the original parts. |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the console driver |
+\*===============================================================*/
+/* derived from: generic MPC83xx BSP */
+#ifndef TQM8xx_IRQ_IRQ_H
+#define TQM8xx_IRQ_IRQ_H
+
+#include <stdbool.h>
+
+#include <rtems.h>
+#include <rtems/irq.h>
+#include <rtems/irq-extension.h>
+
+/*
+ * the following definitions specify the indices used
+ * to interface the interrupt handler API
+ */
+
+/*
+ * Peripheral IRQ handlers related definitions
+ */
+#define BSP_SIU_PER_IRQ_NUMBER 16
+#define BSP_SIU_IRQ_LOWEST_OFFSET 0
+#define BSP_SIU_IRQ_MAX_OFFSET (BSP_SIU_IRQ_LOWEST_OFFSET\
+ +BSP_SIU_PER_IRQ_NUMBER-1)
+
+#define BSP_IS_SIU_IRQ(irqnum) \
+ (((irqnum) >= BSP_SIU_IRQ_LOWEST_OFFSET) && \
+ ((irqnum) <= BSP_SIU_IRQ_MAX_OFFSET))
+
+#define BSP_CPM_PER_IRQ_NUMBER 32
+#define BSP_CPM_IRQ_LOWEST_OFFSET (BSP_SIU_IRQ_MAX_OFFSET+1)
+#define BSP_CPM_IRQ_MAX_OFFSET (BSP_CPM_IRQ_LOWEST_OFFSET\
+ +BSP_CPM_PER_IRQ_NUMBER-1)
+
+#define BSP_IS_CPM_IRQ(irqnum) \
+ (((irqnum) >= BSP_CPM_IRQ_LOWEST_OFFSET) && \
+ ((irqnum) <= BSP_CPM_IRQ_MAX_OFFSET))
+/*
+ * Processor IRQ handlers related definitions
+ */
+#define BSP_PROCESSOR_IRQ_NUMBER 1
+#define BSP_PROCESSOR_IRQ_LOWEST_OFFSET (BSP_CPM_IRQ_MAX_OFFSET+1)
+#define BSP_PROCESSOR_IRQ_MAX_OFFSET (BSP_PROCESSOR_IRQ_LOWEST_OFFSET\
+ +BSP_PROCESSOR_IRQ_NUMBER-1)
+
+#define BSP_IS_PROCESSOR_IRQ(irqnum) \
+ (((irqnum) >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET) && \
+ ((irqnum) <= BSP_PROCESSOR_IRQ_MAX_OFFSET))
+/*
+ * Summary
+ */
+#define BSP_IRQ_NUMBER (BSP_PROCESSOR_IRQ_MAX_OFFSET+1)
+#define BSP_LOWEST_OFFSET BSP_SIU_IRQ_LOWEST_OFFSET
+#define BSP_MAX_OFFSET BSP_PROCESSOR_IRQ_MAX_OFFSET
+
+#define BSP_IS_VALID_IRQ(irqnum) \
+ (BSP_IS_PROCESSOR_IRQ(irqnum) \
+ || BSP_IS_SIU_IRQ(irqnum) \
+ || BSP_IS_CPM_IRQ(irqnum))
+
+#ifndef ASM
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * index table for the module specific handlers, a few entries are only placeholders
+ */
+ typedef enum {
+ BSP_SIU_EXT_IRQ_0 = BSP_SIU_IRQ_LOWEST_OFFSET + 0,
+ BSP_SIU_INT_IRQ_0 = BSP_SIU_IRQ_LOWEST_OFFSET + 1,
+ BSP_SIU_EXT_IRQ_1 = BSP_SIU_IRQ_LOWEST_OFFSET + 2,
+ BSP_SIU_INT_IRQ_1 = BSP_SIU_IRQ_LOWEST_OFFSET + 3,
+ BSP_SIU_EXT_IRQ_2 = BSP_SIU_IRQ_LOWEST_OFFSET + 4,
+ BSP_SIU_INT_IRQ_2 = BSP_SIU_IRQ_LOWEST_OFFSET + 5,
+ BSP_SIU_EXT_IRQ_3 = BSP_SIU_IRQ_LOWEST_OFFSET + 6,
+ BSP_SIU_INT_IRQ_3 = BSP_SIU_IRQ_LOWEST_OFFSET + 7,
+ BSP_SIU_EXT_IRQ_4 = BSP_SIU_IRQ_LOWEST_OFFSET + 8,
+ BSP_SIU_INT_IRQ_4 = BSP_SIU_IRQ_LOWEST_OFFSET + 9,
+ BSP_SIU_EXT_IRQ_5 = BSP_SIU_IRQ_LOWEST_OFFSET + 10,
+ BSP_SIU_INT_IRQ_5 = BSP_SIU_IRQ_LOWEST_OFFSET + 11,
+ BSP_SIU_EXT_IRQ_6 = BSP_SIU_IRQ_LOWEST_OFFSET + 12,
+ BSP_SIU_INT_IRQ_6 = BSP_SIU_IRQ_LOWEST_OFFSET + 13,
+ BSP_SIU_EXT_IRQ_7 = BSP_SIU_IRQ_LOWEST_OFFSET + 14,
+ BSP_SIU_INT_IRQ_7 = BSP_SIU_IRQ_LOWEST_OFFSET + 15,
+ BSP_SIU_IRQ_LAST = BSP_SIU_IRQ_MAX_OFFSET,
+ /*
+ * Some CPM IRQ symbolic name definition
+ */
+ BSP_CPM_IRQ_ERROR = (BSP_CPM_IRQ_LOWEST_OFFSET),
+ BSP_CPM_IRQ_PARALLEL_IO_PC4 = (BSP_CPM_IRQ_LOWEST_OFFSET + 1),
+ BSP_CPM_IRQ_PARALLEL_IO_PC5 = (BSP_CPM_IRQ_LOWEST_OFFSET + 2),
+ BSP_CPM_IRQ_SMC2_OR_PIP = (BSP_CPM_IRQ_LOWEST_OFFSET + 3),
+ BSP_CPM_IRQ_SMC1 = (BSP_CPM_IRQ_LOWEST_OFFSET + 4),
+ BSP_CPM_IRQ_SPI = (BSP_CPM_IRQ_LOWEST_OFFSET + 5),
+ BSP_CPM_IRQ_PARALLEL_IO_PC6 = (BSP_CPM_IRQ_LOWEST_OFFSET + 6),
+ BSP_CPM_IRQ_TIMER_4 = (BSP_CPM_IRQ_LOWEST_OFFSET + 7),
+ BSP_CPM_IRQ_PARALLEL_IO_PC7 = (BSP_CPM_IRQ_LOWEST_OFFSET + 9),
+ BSP_CPM_IRQ_PARALLEL_IO_PC8 = (BSP_CPM_IRQ_LOWEST_OFFSET + 10),
+ BSP_CPM_IRQ_PARALLEL_IO_PC9 = (BSP_CPM_IRQ_LOWEST_OFFSET + 11),
+ BSP_CPM_IRQ_TIMER_3 = (BSP_CPM_IRQ_LOWEST_OFFSET + 12),
+ BSP_CPM_IRQ_PARALLEL_IO_PC10= (BSP_CPM_IRQ_LOWEST_OFFSET + 14),
+ BSP_CPM_IRQ_PARALLEL_IO_PC11= (BSP_CPM_IRQ_LOWEST_OFFSET + 15),
+ BSP_CPM_I2C = (BSP_CPM_IRQ_LOWEST_OFFSET + 16),
+ BSP_CPM_RISC_TIMER_TABLE = (BSP_CPM_IRQ_LOWEST_OFFSET + 17),
+ BSP_CPM_IRQ_TIMER_2 = (BSP_CPM_IRQ_LOWEST_OFFSET + 18),
+ BSP_CPM_IDMA2 = (BSP_CPM_IRQ_LOWEST_OFFSET + 20),
+ BSP_CPM_IDMA1 = (BSP_CPM_IRQ_LOWEST_OFFSET + 21),
+ BSP_CPM_SDMA_CHANNEL_BUS_ERR= (BSP_CPM_IRQ_LOWEST_OFFSET + 22),
+ BSP_CPM_IRQ_PARALLEL_IO_PC12= (BSP_CPM_IRQ_LOWEST_OFFSET + 23),
+ BSP_CPM_IRQ_PARALLEL_IO_PC13= (BSP_CPM_IRQ_LOWEST_OFFSET + 24),
+ BSP_CPM_IRQ_TIMER_1 = (BSP_CPM_IRQ_LOWEST_OFFSET + 25),
+ BSP_CPM_IRQ_PARALLEL_IO_PC14= (BSP_CPM_IRQ_LOWEST_OFFSET + 26),
+ BSP_CPM_IRQ_SCC4 = (BSP_CPM_IRQ_LOWEST_OFFSET + 27),
+ BSP_CPM_IRQ_SCC3 = (BSP_CPM_IRQ_LOWEST_OFFSET + 28),
+ BSP_CPM_IRQ_SCC2 = (BSP_CPM_IRQ_LOWEST_OFFSET + 29),
+ BSP_CPM_IRQ_SCC1 = (BSP_CPM_IRQ_LOWEST_OFFSET + 30),
+ BSP_CPM_IRQ_PARALLEL_IO_PC15= (BSP_CPM_IRQ_LOWEST_OFFSET + 31),
+ BSP_CPM_IRQ_LAST = BSP_CPM_IRQ_MAX_OFFSET,
+ } rtems_irq_symbolic_name;
+
+ /*
+ * Symbolic name for CPM interrupt on SIU Internal level 2
+ */
+#define BSP_CPM_INTERRUPT BSP_SIU_INT_IRQ_2
+#define BSP_PERIODIC_TIMER BSP_SIU_INT_IRQ_6
+#define BSP_FAST_ETHERNET_CTRL BSP_SIU_INT_IRQ_3
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* ASM */
+
+#endif /* TQM8XX_IRQ_IRQ_H */
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/include/tm27.h b/c/src/lib/libbsp/powerpc/tqm8xx/include/tm27.h
new file mode 100644
index 0000000000..ee820ef1ff
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/include/tm27.h
@@ -0,0 +1,32 @@
+/*
+ * tm27.h
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _RTEMS_TMTEST27
+#error "This is an RTEMS internal file you must not include directly."
+#endif
+
+#ifndef __tm27_h
+#define __tm27_h
+
+/*
+ * 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() /* empty */
+
+#define Clear_tm27_intr() /* empty */
+
+#define Lower_tm27_intr() /* empty */
+
+#endif
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/include/tqm.h b/c/src/lib/libbsp/powerpc/tqm8xx/include/tqm.h
new file mode 100644
index 0000000000..31500e25f2
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/include/tqm.h
@@ -0,0 +1,51 @@
+/*===============================================================*\
+| Project: RTEMS BSP support for TQ modules |
++-----------------------------------------------------------------+
+| Partially based on the code references which are named below. |
+| Adaptions, modifications, enhancements and any recent parts of |
+| the code are: |
+| Copyright (c) 2007 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains definitions to interact with TQC's |
+| processor modules |
+\*===============================================================*/
+
+#ifndef __TQM_H__
+#define __TQM_H__
+#include <rtems.h>
+
+typedef struct {
+ uint32_t sdram_size; /* existing SDRAM size */
+ uint32_t flash_base; /* start address flash */
+ uint32_t flash_size; /* existing Flash size */
+ uint32_t flash_offset;
+ uint32_t sram_base; /* start address sram */
+ uint32_t sram_size; /* existing sram size */
+ uint32_t immr_base; /* start address internal memory map */
+ uint32_t reboot; /* reboot flag */
+ uint8_t ip_addr[4]; /* IP address */
+ uint8_t eth_addr[6]; /* ethernet (MAC) address */
+ uint8_t gap_42[2]; /* gap for alignment */
+ void (*put_char)(int c); /* function to output characters */
+} tqm_bd_info_t;
+
+#define TQM_BD_INFO_ADDR 0x3400
+#define TQM_BD_INFO (*(tqm_bd_info_t *)TQM_BD_INFO_ADDR)
+
+#define TQM_CONF_INFO_BLOCK_ADDR 0x4001fe00
+
+#define IMAP_ADDR ((unsigned int)0xfa200000)
+#define IMAP_SIZE ((unsigned int)(64 * 1024))
+
+#endif /* __TQM_H__ */
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/irq/irq.c b/c/src/lib/libbsp/powerpc/tqm8xx/irq/irq.c
new file mode 100644
index 0000000000..4dac7fb38b
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/irq/irq.c
@@ -0,0 +1,240 @@
+/*===============================================================*\
+| Project: RTEMS TQM8xx BSP |
++-----------------------------------------------------------------+
+| This file has been adapted to MPC8xx by |
+| Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> |
+| Copyright (c) 2008 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
+| |
+| See the other copyright notice below for the original parts. |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the console driver |
+\*===============================================================*/
+/* derived from: generic MPC83xx BSP */
+
+#include <rtems.h>
+#include <mpc8xx.h>
+
+#include <libcpu/powerpc-utility.h>
+#include <libcpu/raw_exception.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/vectors.h>
+#include <bsp/ppc_exc_bspsupp.h>
+#include <bsp/irq-generic.h>
+/*
+ * functions to enable/disable a source at the SIU/CPM irq controller
+ */
+
+rtems_status_code bsp_irq_disable_at_SIU(rtems_vector_number irqnum)
+{
+ rtems_vector_number vecnum = irqnum - BSP_SIU_IRQ_LOWEST_OFFSET;
+ m8xx.simask &= ~(1 << (31 - vecnum));
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code bsp_irq_enable_at_SIU(rtems_vector_number irqnum)
+{
+ rtems_vector_number vecnum = irqnum - BSP_SIU_IRQ_LOWEST_OFFSET;
+ m8xx.simask |= (1 << (31 - vecnum));
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code bsp_irq_disable_at_CPM(rtems_vector_number irqnum)
+{
+ rtems_vector_number vecnum = irqnum - BSP_CPM_IRQ_LOWEST_OFFSET;
+ m8xx.cimr &= ~(1 << (31 - vecnum));
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code bsp_irq_enable_at_CPM(rtems_vector_number irqnum)
+{
+ rtems_vector_number vecnum = irqnum - BSP_CPM_IRQ_LOWEST_OFFSET;
+ m8xx.cimr |= (1 << (31 - vecnum));
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code bsp_interrupt_vector_enable( rtems_vector_number irqnum)
+{
+ if (BSP_IS_CPM_IRQ(irqnum)) {
+ bsp_irq_enable_at_CPM(irqnum);
+ return RTEMS_SUCCESSFUL;
+ }
+ else if (BSP_IS_SIU_IRQ(irqnum)) {
+ bsp_irq_enable_at_SIU(irqnum);
+ return RTEMS_SUCCESSFUL;
+ }
+ return RTEMS_INVALID_ID;
+}
+
+rtems_status_code bsp_interrupt_vector_disable( rtems_vector_number irqnum)
+{
+ if (BSP_IS_CPM_IRQ(irqnum)) {
+ bsp_irq_disable_at_CPM(irqnum);
+ return RTEMS_SUCCESSFUL;
+ }
+ else if (BSP_IS_SIU_IRQ(irqnum)) {
+ bsp_irq_disable_at_SIU(irqnum);
+ return RTEMS_SUCCESSFUL;
+ }
+ return RTEMS_INVALID_ID;
+}
+
+/*
+ * IRQ Handler: this is called from the primary exception dispatcher
+ */
+static int BSP_irq_handle_at_cpm(void)
+{
+ int32_t cpvecnum;
+ uint32_t msr;
+ rtems_interrupt_level level;
+
+ /* Get vector number: write IACK=1, then read vectir */
+ m8xx.civr = 1;
+ cpvecnum = (m8xx.civr >> 11) + BSP_CPM_IRQ_LOWEST_OFFSET;
+
+ /*
+ * Check the vector number, mask lower priority interrupts, enable
+ * exceptions and dispatch the handler.
+ */
+ if (BSP_IS_CPM_IRQ(cpvecnum)) {
+ /* Enable all interrupts */
+ msr = ppc_external_exceptions_enable();
+ /* Dispatch interrupt handlers */
+ bsp_interrupt_handler_dispatch(cpvecnum);
+ /* Restore machine state */
+ ppc_external_exceptions_disable(msr);
+ /*
+ * clear "in-service" bit
+ */
+ m8xx.cisr = 1 << (cpvecnum - BSP_CPM_IRQ_LOWEST_OFFSET);
+ }
+ else {
+ /* not valid vector */
+ bsp_interrupt_handler_default(cpvecnum);
+ }
+ return 0;
+}
+
+static int BSP_irq_handle_at_siu( unsigned excNum)
+{
+ int32_t sivecnum;
+ uint32_t msr;
+ rtems_interrupt_level level;
+ bool is_cpm_irq;
+ uint32_t simask_save;
+ /*
+ * check, if interrupt is pending
+ * and repeat as long as valid interrupts are pending
+ */
+ while (0 != (m8xx.simask & m8xx.sipend)) {
+ /* Get vector number */
+ sivecnum = (m8xx.sivec >> 26);
+ is_cpm_irq = (sivecnum == BSP_CPM_INTERRUPT);
+ /*
+ * Check the vector number, mask lower priority interrupts, enable
+ * exceptions and dispatch the handler.
+ */
+ if (BSP_IS_SIU_IRQ(sivecnum)) {
+ simask_save = m8xx.simask;
+ /*
+ * if this is the CPM interrupt, mask lower prio interrupts at SIU
+ * else mask lower and same priority interrupts
+ */
+ m8xx.simask &= ~0 << (32
+ - sivecnum
+ - ((is_cpm_irq) ? 1 : 0));
+
+ if (is_cpm_irq) {
+ BSP_irq_handle_at_cpm();
+ }
+ else {
+ /* Enable all interrupts */
+ msr = ppc_external_exceptions_enable();
+ /* Dispatch interrupt handlers */
+ bsp_interrupt_handler_dispatch(sivecnum + BSP_SIU_IRQ_LOWEST_OFFSET);
+ /* Restore machine state */
+ ppc_external_exceptions_disable(msr);
+ /*
+ * clear pending bit, if edge triggered interrupt input
+ */
+ m8xx.sipend = 1 << (31 - sivecnum);
+ }
+
+
+ /* Restore initial masks */
+ m8xx.simask = simask_save;
+ } else {
+ /* not valid vector */
+ bsp_interrupt_handler_default(sivecnum);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Activate the CPIC
+ */
+rtems_status_code mpc8xx_cpic_initialize( void)
+{
+ /*
+ * mask off all interrupts
+ */
+ m8xx.cimr = 0;
+ /*
+ * make sure CPIC request proper level at SIU interrupt controller
+ */
+ m8xx.cicr = (0x00e41f00 |
+ ((BSP_CPM_INTERRUPT/2) << 13));
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Activate the SIU interrupt controller
+ */
+rtems_status_code mpc8xx_siu_int_initialize( void)
+{
+ /*
+ * mask off all interrupts
+ */
+ m8xx.simask = 0;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+int mpc8xx_exception_handler(BSP_Exception_frame *frame,
+ unsigned exception_number)
+{
+ return BSP_irq_handle_at_siu(exception_number);
+}
+
+rtems_status_code bsp_interrupt_facility_initialize()
+{
+ /* Install exception handler */
+ if (ppc_exc_set_handler(ASM_EXT_VECTOR, mpc8xx_exception_handler)) {
+ return RTEMS_IO_ERROR;
+ }
+ /* Initialize the SIU interrupt controller */
+ if (mpc8xx_siu_int_initialize()) {
+ return RTEMS_IO_ERROR;
+ }
+ /* Initialize the CPIC interrupt controller */
+ return mpc8xx_cpic_initialize();
+}
+
+void bsp_interrupt_handler_default( rtems_vector_number vector)
+{
+ printk( "Spurious interrupt: 0x%08x\n", vector);
+}
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/irq/irq.h b/c/src/lib/libbsp/powerpc/tqm8xx/irq/irq.h
new file mode 100644
index 0000000000..f590317c63
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/irq/irq.h
@@ -0,0 +1,204 @@
+/*===============================================================*\
+| Project: RTEMS TQM8xx BSP |
++-----------------------------------------------------------------+
+| This file has been adapted to MPC8xx by |
+| Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> |
+| Copyright (c) 2008 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
+| |
+| See the other copyright notice below for the original parts. |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the console driver |
+\*===============================================================*/
+/* derived from: generic MPC83xx BSP */
+/* irq.h
+ *
+ * This include file describe the data structure and the functions implemented
+ * by rtems to write interrupt handlers.
+ *
+ * CopyRight (C) 1999 valette@crf.canon.fr
+ *
+ * This code is heavilly inspired by the public specification of STREAM V2
+ * that can be found at :
+ *
+ * <http://www.chorus.com/Documentation/index.html> by following
+ * the STREAM API Specification Document link.
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef LIBBSP_POWERPC_TQM8XX_IRQ_IRQ_H
+#define LIBBSP_POWERPC_TQM8XX_IRQ_IRQ_H
+
+#include <rtems/irq.h>
+
+#ifndef ASM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern volatile unsigned int ppc_cached_irq_mask;
+
+/*
+ * Symblolic IRQ names and related definitions.
+ */
+
+ /*
+ * SIU IRQ handler related definitions
+ */
+#define BSP_SIU_IRQ_NUMBER 16 /* 16 reserved but in the future... */
+#define BSP_SIU_IRQ_LOWEST_OFFSET 0
+#define BSP_SIU_IRQ_MAX_OFFSET (BSP_SIU_IRQ_LOWEST_OFFSET + BSP_SIU_IRQ_NUMBER - 1)
+ /*
+ * CPM IRQ handlers related definitions
+ * CAUTION : BSP_CPM_IRQ_LOWEST_OFFSET should be equal to OPENPIC_VEC_SOURCE
+ */
+#define BSP_CPM_IRQ_NUMBER 32
+#define BSP_CPM_IRQ_LOWEST_OFFSET (BSP_SIU_IRQ_NUMBER + BSP_SIU_IRQ_LOWEST_OFFSET)
+#define BSP_CPM_IRQ_MAX_OFFSET (BSP_CPM_IRQ_LOWEST_OFFSET + BSP_CPM_IRQ_NUMBER - 1)
+ /*
+ * PowerPc exceptions handled as interrupt where a rtems managed interrupt
+ * handler might be connected
+ */
+#define BSP_PROCESSOR_IRQ_NUMBER 1
+#define BSP_PROCESSOR_IRQ_LOWEST_OFFSET (BSP_CPM_IRQ_MAX_OFFSET + 1)
+#define BSP_PROCESSOR_IRQ_MAX_OFFSET (BSP_PROCESSOR_IRQ_LOWEST_OFFSET + BSP_PROCESSOR_IRQ_NUMBER - 1)
+ /*
+ * Summary
+ */
+#define BSP_IRQ_NUMBER (BSP_PROCESSOR_IRQ_MAX_OFFSET + 1)
+#define BSP_LOWEST_OFFSET (BSP_SIU_IRQ_LOWEST_OFFSET)
+#define BSP_MAX_OFFSET (BSP_PROCESSOR_IRQ_MAX_OFFSET)
+ /*
+ * Some SIU IRQ symbolic name definition. Please note that
+ * INT IRQ are defined but a single one will be used to
+ * redirect all CPM interrupt.
+ */
+#define BSP_SIU_EXT_IRQ_0 0
+#define BSP_SIU_INT_IRQ_0 1
+
+#define BSP_SIU_EXT_IRQ_1 2
+#define BSP_SIU_INT_IRQ_1 3
+
+#define BSP_SIU_EXT_IRQ_2 4
+#define BSP_SIU_INT_IRQ_2 5
+
+#define BSP_SIU_EXT_IRQ_3 6
+#define BSP_SIU_INT_IRQ_3 7
+
+#define BSP_SIU_EXT_IRQ_4 8
+#define BSP_SIU_INT_IRQ_4 9
+
+#define BSP_SIU_EXT_IRQ_5 10
+#define BSP_SIU_INT_IRQ_5 11
+
+#define BSP_SIU_EXT_IRQ_6 12
+#define BSP_SIU_INT_IRQ_6 13
+
+#define BSP_SIU_EXT_IRQ_7 14
+#define BSP_SIU_INT_IRQ_7 15
+ /*
+ * Symbolic name for CPM interrupt on SIU Internal level 2
+ */
+#define BSP_CPM_INTERRUPT BSP_SIU_INT_IRQ_2
+#define BSP_PERIODIC_TIMER BSP_SIU_INT_IRQ_6
+#define BSP_FAST_ETHERNET_CTRL BSP_SIU_INT_IRQ_3
+ /*
+ * Some CPM IRQ symbolic name definition
+ */
+#define BSP_CPM_IRQ_ERROR BSP_CPM_IRQ_LOWEST_OFFSET
+#define BSP_CPM_IRQ_PARALLEL_IO_PC4 (BSP_CPM_IRQ_LOWEST_OFFSET + 1)
+#define BSP_CPM_IRQ_PARALLEL_IO_PC5 (BSP_CPM_IRQ_LOWEST_OFFSET + 2)
+#define BSP_CPM_IRQ_SMC2_OR_PIP (BSP_CPM_IRQ_LOWEST_OFFSET + 3)
+#define BSP_CPM_IRQ_SMC1 (BSP_CPM_IRQ_LOWEST_OFFSET + 4)
+#define BSP_CPM_IRQ_SPI (BSP_CPM_IRQ_LOWEST_OFFSET + 5)
+#define BSP_CPM_IRQ_PARALLEL_IO_PC6 (BSP_CPM_IRQ_LOWEST_OFFSET + 6)
+#define BSP_CPM_IRQ_TIMER_4 (BSP_CPM_IRQ_LOWEST_OFFSET + 7)
+
+#define BSP_CPM_IRQ_PARALLEL_IO_PC7 (BSP_CPM_IRQ_LOWEST_OFFSET + 9)
+#define BSP_CPM_IRQ_PARALLEL_IO_PC8 (BSP_CPM_IRQ_LOWEST_OFFSET + 10)
+#define BSP_CPM_IRQ_PARALLEL_IO_PC9 (BSP_CPM_IRQ_LOWEST_OFFSET + 11)
+#define BSP_CPM_IRQ_TIMER_3 (BSP_CPM_IRQ_LOWEST_OFFSET + 12)
+
+#define BSP_CPM_IRQ_PARALLEL_IO_PC10 (BSP_CPM_IRQ_LOWEST_OFFSET + 14)
+#define BSP_CPM_IRQ_PARALLEL_IO_PC11 (BSP_CPM_IRQ_LOWEST_OFFSET + 15)
+#define BSP_CPM_I2C (BSP_CPM_IRQ_LOWEST_OFFSET + 16)
+#define BSP_CPM_RISC_TIMER_TABLE (BSP_CPM_IRQ_LOWEST_OFFSET + 17)
+#define BSP_CPM_IRQ_TIMER_2 (BSP_CPM_IRQ_LOWEST_OFFSET + 18)
+
+#define BSP_CPM_IDMA2 (BSP_CPM_IRQ_LOWEST_OFFSET + 20)
+#define BSP_CPM_IDMA1 (BSP_CPM_IRQ_LOWEST_OFFSET + 21)
+#define BSP_CPM_SDMA_CHANNEL_BUS_ERR (BSP_CPM_IRQ_LOWEST_OFFSET + 22)
+#define BSP_CPM_IRQ_PARALLEL_IO_PC12 (BSP_CPM_IRQ_LOWEST_OFFSET + 23)
+#define BSP_CPM_IRQ_PARALLEL_IO_PC13 (BSP_CPM_IRQ_LOWEST_OFFSET + 24)
+#define BSP_CPM_IRQ_TIMER_1 (BSP_CPM_IRQ_LOWEST_OFFSET + 25)
+#define BSP_CPM_IRQ_PARALLEL_IO_PC14 (BSP_CPM_IRQ_LOWEST_OFFSET + 26)
+#define BSP_CPM_IRQ_SCC4 (BSP_CPM_IRQ_LOWEST_OFFSET + 27)
+#define BSP_CPM_IRQ_SCC3 (BSP_CPM_IRQ_LOWEST_OFFSET + 28)
+#define BSP_CPM_IRQ_SCC2 (BSP_CPM_IRQ_LOWEST_OFFSET + 29)
+#define BSP_CPM_IRQ_SCC1 (BSP_CPM_IRQ_LOWEST_OFFSET + 30)
+#define BSP_CPM_IRQ_PARALLEL_IO_PC15 (BSP_CPM_IRQ_LOWEST_OFFSET + 31)
+ /*
+ * Some Processor exception handled as rtems IRQ symbolic name definition
+ */
+#define BSP_DECREMENTER BSP_PROCESSOR_IRQ_LOWEST_OFFSET
+
+
+#define CPM_INTERRUPT
+
+/*-------------------------------------------------------------------------+
+| Function Prototypes.
++--------------------------------------------------------------------------*/
+/*
+ * ------------------------ PPC SIU Mngt Routines -------
+ */
+
+/*
+ * function to disable a particular irq at 8259 level. After calling
+ * this function, even if the device asserts the interrupt line it will
+ * not be propagated further to the processor
+ */
+int BSP_irq_disable_at_siu (const rtems_irq_number irqLine);
+/*
+ * function to enable a particular irq at 8259 level. After calling
+ * this function, if the device asserts the interrupt line it will
+ * be propagated further to the processor
+ */
+int BSP_irq_enable_at_siu (const rtems_irq_number irqLine);
+/*
+ * function to acknoledge a particular irq at 8259 level. After calling
+ * this function, if a device asserts an enabled interrupt line it will
+ * be propagated further to the processor. Mainly usefull for people
+ * writting raw handlers as this is automagically done for rtems managed
+ * handlers.
+ */
+int BSP_irq_ack_at_siu (const rtems_irq_number irqLine);
+/*
+ * function to check if a particular irq is enabled at 8259 level. After calling
+ */
+int BSP_irq_enabled_at_siu (const rtems_irq_number irqLine);
+
+extern void BSP_rtems_irq_mng_init(unsigned cpuId);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#endif
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/irq/irq_asm.S b/c/src/lib/libbsp/powerpc/tqm8xx/irq/irq_asm.S
new file mode 100644
index 0000000000..1a67196b0a
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/irq/irq_asm.S
@@ -0,0 +1,433 @@
+/*===============================================================*\
+| Project: RTEMS TQM8xx BSP |
++-----------------------------------------------------------------+
+| This file has been adapted to MPC8xx by |
+| Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> |
+| Copyright (c) 2008 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
+| |
+| See the other copyright notice below for the original parts. |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the console driver |
+\*===============================================================*/
+/* derived from: generic MPC83xx BSP */
+/*
+ * This file contains the assembly code for the PowerPC
+ * IRQ veneers for RTEMS.
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * Modified to support the MCP750.
+ * Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
+ *
+ * Till Straumann <strauman@slac.stanford.edu>, 2003/7:
+ * - store isr nesting level in _ISR_Nest_level rather than
+ * SPRG0 - RTEMS relies on that variable.
+ * Till Straumann <strauman@slac.stanford.edu>, 2005/4:
+ * - DONT enable FP across user ISR since fpregs are never saved!!
+ *
+ * $Id$
+ */
+
+#include <rtems/asm.h>
+#include <rtems/score/cpu.h>
+#include <bsp/vectors.h>
+#include <libcpu/raw_exception.h>
+
+#define SYNC \
+ sync; \
+ isync
+
+ .text
+ .p2align 5
+
+ PUBLIC_VAR(decrementer_exception_vector_prolog_code)
+
+SYM (decrementer_exception_vector_prolog_code):
+ /*
+ * let room for exception frame
+ */
+ stwu r1, - (EXCEPTION_FRAME_END)(r1)
+ stw r4, GPR4_OFFSET(r1)
+#ifdef THIS_CODE_LINKED_USING_FLASH_ADDR_RANGE
+ /*
+ * save link register
+ */
+ mflr r4
+ stw r4, EXC_LR_OFFSET(r1)
+ /*
+ * make link register contain shared_raw_irq_code_entry
+ * address
+ */
+ lis r4,shared_raw_irq_code_entry@h
+ ori r4,r4,shared_raw_irq_code_entry@l
+ mtlr r4
+
+ li r4, ASM_DEC_VECTOR
+ blr
+#else
+ li r4, ASM_DEC_VECTOR
+ ba shared_raw_irq_code_entry
+#endif
+
+ PUBLIC_VAR (decrementer_exception_vector_prolog_code_size)
+
+ decrementer_exception_vector_prolog_code_size = . - decrementer_exception_vector_prolog_code
+
+ PUBLIC_VAR(external_exception_vector_prolog_code)
+
+SYM (external_exception_vector_prolog_code):
+ /*
+ * let room for exception frame
+ */
+ stwu r1, - (EXCEPTION_FRAME_END)(r1)
+ stw r4, GPR4_OFFSET(r1)
+#ifdef THIS_CODE_LINKED_USING_FLASH_ADDR_RANGE
+ /*
+ * save link register
+ */
+ mflr r4
+ stw r4, EXC_LR_OFFSET(r1)
+ /*
+ * make link register contain shared_raw_irq_code_entry
+ * address
+ */
+ lis r4,shared_raw_irq_code_entry@h
+ ori r4,r4,shared_raw_irq_code_entry@l
+ mtlr r4
+
+ li r4, ASM_EXT_VECTOR
+ blr
+#else
+ li r4, ASM_EXT_VECTOR
+ ba shared_raw_irq_code_entry
+#endif
+
+ PUBLIC_VAR (external_exception_vector_prolog_code_size)
+
+ external_exception_vector_prolog_code_size = . - external_exception_vector_prolog_code
+
+ PUBLIC_VAR(shared_raw_irq_code_entry)
+ PUBLIC_VAR(C_dispatch_irq_handler)
+
+ .p2align 5
+SYM (shared_raw_irq_code_entry):
+ /*
+ * Entry conditions :
+ * Registers already saved : R1, R4
+ * R1 : points to a location with enough room for the
+ * interrupt frame
+ * R4 : vector number
+ */
+ /*
+ * Save SRR0/SRR1 As soon As possible as it is the minimal needed
+ * to reenable exception processing
+ */
+ stw r0, GPR0_OFFSET(r1)
+ stw r2, GPR2_OFFSET(r1)
+ stw r3, GPR3_OFFSET(r1)
+
+ mfsrr0 r0
+ mfsrr1 r2
+ mfmsr r3
+
+ stw r0, SRR0_FRAME_OFFSET(r1)
+ stw r2, SRR1_FRAME_OFFSET(r1)
+ /*
+ * Enable data and instruction address translation, exception recovery
+ *
+ * also, on CPUs with FP, enable FP so that FP context can be
+ * saved and restored (using FP instructions)
+ */
+ ori r3, r3, MSR_RI | MSR_IR | MSR_DR
+ mtmsr r3
+ SYNC
+ /*
+ * Push C scratch registers on the current stack. It may
+ * actually be the thread stack or the interrupt stack.
+ * Anyway we have to make it in order to be able to call C/C++
+ * functions. Depending on the nesting interrupt level, we will
+ * switch to the right stack later.
+ */
+ stw r5, GPR5_OFFSET(r1)
+ stw r6, GPR6_OFFSET(r1)
+ stw r7, GPR7_OFFSET(r1)
+ stw r8, GPR8_OFFSET(r1)
+ stw r9, GPR9_OFFSET(r1)
+ stw r10, GPR10_OFFSET(r1)
+ stw r11, GPR11_OFFSET(r1)
+ stw r12, GPR12_OFFSET(r1)
+ stw r13, GPR13_OFFSET(r1)
+
+ mfcr r5
+ mfctr r6
+ mfxer r7
+#ifndef THIS_CODE_LINKED_USING_FLASH_ADDR_RANGE
+ mflr r8
+#endif
+
+ stw r5, EXC_CR_OFFSET(r1)
+ stw r6, EXC_CTR_OFFSET(r1)
+ stw r7, EXC_XER_OFFSET(r1)
+#ifndef THIS_CODE_LINKED_USING_FLASH_ADDR_RANGE
+ stw r8, EXC_LR_OFFSET(r1)
+#endif
+
+ /*
+ * Add some non volatile registers to store information
+ * that will be used when returning from C handler
+ */
+ stw r14, GPR14_OFFSET(r1)
+ stw r15, GPR15_OFFSET(r1)
+ /*
+ * save current stack pointer location in R14
+ */
+ addi r14, r1, 0
+ /*
+ * store part of _Thread_Dispatch_disable_level address in R15
+ */
+ addis r15,0, _Thread_Dispatch_disable_level@ha
+#if BROKEN_ISR_NEST_LEVEL
+ /*
+ * Get current nesting level in R2
+ */
+ mfspr r2, SPRG0
+#else
+ /*
+ * Retrieve current nesting level from _ISR_Nest_level
+ */
+ lis r7, _ISR_Nest_level@ha
+ lwz r2, _ISR_Nest_level@l(r7)
+#endif
+ /*
+ * Check if stack switch is necessary
+ */
+ cmpwi r2,0
+ bne nested
+ mfspr r1, SPRG1
+
+nested:
+ /*
+ * Start Incrementing nesting level in R2
+ */
+ addi r2,r2,1
+ /*
+ * Start Incrementing _Thread_Dispatch_disable_level R4 = _Thread_Dispatch_disable_level
+ */
+ lwz r6,_Thread_Dispatch_disable_level@l(r15)
+#if BROKEN_ISR_NEST_LEVEL
+ /*
+ * Store new nesting level in SPRG0
+ */
+ mtspr SPRG0, r2
+#else
+ /* store new nesting level in _ISR_Nest_level */
+ stw r2, _ISR_Nest_level@l(r7)
+#endif
+
+ addi r6, r6, 1
+ mfmsr r5
+ /*
+ * store new _Thread_Dispatch_disable_level value
+ */
+ stw r6, _Thread_Dispatch_disable_level@l(r15)
+ /*
+ * We are now running on the interrupt stack. External and decrementer
+ * exceptions are still disabled. I see no purpose trying to optimize
+ * further assembler code.
+ */
+ /*
+ * Call C exception handler for decrementer Interrupt frame is passed just
+ * in case...
+ */
+ addi r3, r14, 0x8
+ bl C_dispatch_irq_handler /* C_dispatch_irq_handler(cpu_interrupt_frame* r3, vector r4) */
+ /*
+ * start decrementing nesting level. Note : do not test result against 0
+ * value as an easy exit condition because if interrupt nesting level > 1
+ * then _Thread_Dispatch_disable_level > 1
+ */
+#if BROKEN_ISR_NEST_LEVEL
+ mfspr r2, SPRG0
+#else
+ lis r7, _ISR_Nest_level@ha
+ lwz r2, _ISR_Nest_level@l(r7)
+#endif
+ /*
+ * start decrementing _Thread_Dispatch_disable_level
+ */
+ lwz r3,_Thread_Dispatch_disable_level@l(r15)
+ addi r2, r2, -1 /* Continue decrementing nesting level */
+ addi r3, r3, -1 /* Continue decrementing _Thread_Dispatch_disable_level */
+#if BROKEN_ISR_NEST_LEVEL
+ mtspr SPRG0, r2 /* End decrementing nesting level */
+#else
+ stw r2, _ISR_Nest_level@l(r7) /* End decrementing nesting level */
+#endif
+ stw r3,_Thread_Dispatch_disable_level@l(r15) /* End decrementing _Thread_Dispatch_disable_level */
+ cmpwi r3, 0
+ /*
+ * switch back to original stack (done here just optimize registers
+ * contention. Could have been done before...)
+ */
+ addi r1, r14, 0
+ bne easy_exit /* if (_Thread_Dispatch_disable_level != 0) goto easy_exit */
+ /*
+ * Here we are running again on the thread system stack.
+ * We have interrupt nesting level = _Thread_Dispatch_disable_level = 0.
+ * Interrupt are still disabled. Time to check if scheduler request to
+ * do something with the current thread...
+ */
+ addis r4, 0, _Context_Switch_necessary@ha
+ lwz r5, _Context_Switch_necessary@l(r4)
+ cmpwi r5, 0
+ bne switch
+
+ addis r6, 0, _ISR_Signals_to_thread_executing@ha
+ lwz r7, _ISR_Signals_to_thread_executing@l(r6)
+ cmpwi r7, 0
+ li r8, 0
+ beq easy_exit
+ stw r8, _ISR_Signals_to_thread_executing@l(r6)
+ /*
+ * going to call _ThreadProcessSignalsFromIrq
+ * Push a complete exception like frame...
+ */
+ stmw r16, GPR16_OFFSET(r1)
+ addi r3, r1, 0x8
+ /*
+ * compute SP at exception entry
+ */
+ addi r2, r1, EXCEPTION_FRAME_END
+ /*
+ * store it at the right place
+ */
+ stw r2, GPR1_OFFSET(r1)
+ /*
+ * Call High Level signal handling code
+ */
+ bl _ThreadProcessSignalsFromIrq
+ /*
+ * start restoring exception like frame
+ */
+ lwz r31, EXC_CTR_OFFSET(r1)
+ lwz r30, EXC_XER_OFFSET(r1)
+ lwz r29, EXC_CR_OFFSET(r1)
+ lwz r28, EXC_LR_OFFSET(r1)
+
+ mtctr r31
+ mtxer r30
+ mtcr r29
+ mtlr r28
+
+ lmw r4, GPR4_OFFSET(r1)
+ lwz r2, GPR2_OFFSET(r1)
+ lwz r0, GPR0_OFFSET(r1)
+
+ /*
+ * Disable data and instruction translation. Make path non recoverable...
+ */
+ mfmsr r3
+ xori r3, r3, MSR_RI | MSR_IR | MSR_DR
+ mtmsr r3
+ SYNC
+ /*
+ * Restore rfi related settings
+ */
+
+ lwz r3, SRR1_FRAME_OFFSET(r1)
+ mtsrr1 r3
+ lwz r3, SRR0_FRAME_OFFSET(r1)
+ mtsrr0 r3
+
+ lwz r3, GPR3_OFFSET(r1)
+ addi r1,r1, EXCEPTION_FRAME_END
+ SYNC
+ rfi
+
+switch:
+#if ( PPC_HAS_FPU != 0 )
+#if ! defined( CPU_USE_DEFERRED_FP_SWITCH )
+#error missing include file???
+#endif
+ mfmsr r4
+#if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
+ /* if the executing thread has FP enabled propagate
+ * this now so _Thread_Dispatch can save/restore the FPREGS
+ * NOTE: it is *crucial* to disable the FPU across the
+ * user ISR [independent of using the 'deferred'
+ * strategy or not]. We don't save FP regs across
+ * the user ISR and hence we prefer an exception to
+ * be raised rather than experiencing corruption.
+ */
+ lwz r3, SRR1_FRAME_OFFSET(r1)
+ rlwimi r4, r3, 0, 18, 18 /* MSR_FP */
+#else
+ ori r4, r4, MSR_FP
+#endif
+ mtmsr r4
+#endif
+ bl SYM (_Thread_Dispatch)
+
+easy_exit:
+ /*
+ * start restoring interrupt frame
+ */
+ lwz r3, EXC_CTR_OFFSET(r1)
+ lwz r4, EXC_XER_OFFSET(r1)
+ lwz r5, EXC_CR_OFFSET(r1)
+ lwz r6, EXC_LR_OFFSET(r1)
+
+ mtctr r3
+ mtxer r4
+ mtcr r5
+ mtlr r6
+
+ lwz r15, GPR15_OFFSET(r1)
+ lwz r14, GPR14_OFFSET(r1)
+ lwz r13, GPR13_OFFSET(r1)
+ lwz r12, GPR12_OFFSET(r1)
+ lwz r11, GPR11_OFFSET(r1)
+ lwz r10, GPR10_OFFSET(r1)
+ lwz r9, GPR9_OFFSET(r1)
+ lwz r8, GPR8_OFFSET(r1)
+ lwz r7, GPR7_OFFSET(r1)
+ lwz r6, GPR6_OFFSET(r1)
+ lwz r5, GPR5_OFFSET(r1)
+
+ /*
+ * Disable nested exception processing, data and instruction
+ * translation.
+ */
+ mfmsr r3
+ xori r3, r3, MSR_RI | MSR_IR | MSR_DR
+ mtmsr r3
+ SYNC
+ /*
+ * Restore rfi related settings
+ */
+
+ lwz r4, SRR1_FRAME_OFFSET(r1)
+ lwz r2, SRR0_FRAME_OFFSET(r1)
+ lwz r3, GPR3_OFFSET(r1)
+ lwz r0, GPR0_OFFSET(r1)
+
+ mtsrr1 r4
+ mtsrr0 r2
+ lwz r4, GPR4_OFFSET(r1)
+ lwz r2, GPR2_OFFSET(r1)
+ addi r1,r1, EXCEPTION_FRAME_END
+ SYNC
+ rfi
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/irq/irq_init.c b/c/src/lib/libbsp/powerpc/tqm8xx/irq/irq_init.c
new file mode 100644
index 0000000000..6ed06ccfeb
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/irq/irq_init.c
@@ -0,0 +1,185 @@
+/*===============================================================*\
+| Project: RTEMS TQM8xx BSP |
++-----------------------------------------------------------------+
+| This file has been adapted to MPC8xx by |
+| Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> |
+| Copyright (c) 2008 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
+| |
+| See the other copyright notice below for the original parts. |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the console driver |
+\*===============================================================*/
+/* derived from: generic MPC83xx BSP */
+/* irq_init.c
+ *
+ * This file contains the implementation of rtems initialization
+ * related to interrupt handling.
+ *
+ * CopyRight (C) 2001 valette@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+#include <bsp/irq.h>
+#include <bsp.h>
+#include <libcpu/raw_exception.h>
+#include <bsp/8xx_immap.h>
+#include <bsp/mpc8xx.h>
+
+extern unsigned int external_exception_vector_prolog_code_size;
+extern void external_exception_vector_prolog_code();
+extern unsigned int decrementer_exception_vector_prolog_code_size;
+extern void decrementer_exception_vector_prolog_code();
+
+volatile unsigned int ppc_cached_irq_mask;
+
+/*
+ * default on/off function
+ */
+static void nop_func1(void *unused){}
+static void nop_func2(){}
+
+/*
+ * default isOn function
+ */
+static int not_connected() {return 0;}
+/*
+ * default possible isOn function
+ */
+static int connected() {return 1;}
+
+static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER];
+static rtems_irq_global_settings initial_config;
+static rtems_irq_connect_data defaultIrq = {
+ /* vectorIdex, hdl , handle , on , off , isOn */
+ 0, nop_func1 , 0 , nop_func2 , nop_func2 , not_connected
+};
+static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={
+ /*
+ * actual rpiorities for interrupt :
+ * 0 means that only current interrupt is masked
+ * 255 means all other interrupts are masked
+ */
+ /*
+ * SIU interrupts.
+ */
+ 7,7, 6,6, 5,5, 4,4, 3,3, 2,2, 1,1, 0,0,
+ /*
+ * CPM Interrupts
+ */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ /*
+ * Processor exceptions handled as interrupts
+ */
+ 0
+};
+
+void BSP_SIU_irq_init()
+{
+ /*
+ * In theory we should initialize two registers at least :
+ * SIMASK, SIEL. SIMASK is reset at 0 value meaning no interrupt. But
+ * we should take care that a monitor may have restoreed to another value.
+ * If someone find a reasonnable value for SIEL, AND THE NEED TO CHANGE IT
+ * please feel free to add it here.
+ */
+ ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = 0;
+ ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = 0xffff0000;
+ ppc_cached_irq_mask = 0;
+ ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel = ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel;
+}
+
+/*
+ * Initialize CPM interrupt management
+ */
+void
+BSP_CPM_irq_init(void)
+{
+ /*
+ * Initialize the CPM interrupt controller.
+ */
+ ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr =
+#ifdef mpc860
+ (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
+#else
+ (CICR_SCB_SCC2 | CICR_SCA_SCC1) |
+#endif
+ ((BSP_CPM_INTERRUPT/2) << 13) | CICR_HP_MASK;
+ ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr = 0;
+
+ ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN;
+}
+
+void BSP_rtems_irq_mng_init(unsigned cpuId)
+{
+ rtems_raw_except_connect_data vectorDesc;
+ int i;
+
+ BSP_SIU_irq_init();
+ BSP_CPM_irq_init();
+ /*
+ * Initialize Rtems management interrupt table
+ */
+ /*
+ * re-init the rtemsIrq table
+ */
+ for (i = 0; i < BSP_IRQ_NUMBER; i++) {
+ rtemsIrq[i] = defaultIrq;
+ rtemsIrq[i].name = i;
+ }
+ /*
+ * Init initial Interrupt management config
+ */
+ initial_config.irqNb = BSP_IRQ_NUMBER;
+ initial_config.defaultEntry = defaultIrq;
+ initial_config.irqHdlTbl = rtemsIrq;
+ initial_config.irqBase = BSP_LOWEST_OFFSET;
+ initial_config.irqPrioTbl = irqPrioTable;
+
+ if (!BSP_rtems_irq_mngt_set(&initial_config)) {
+ /*
+ * put something here that will show the failure...
+ */
+ BSP_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
+ }
+
+ /*
+ * We must connect the raw irq handler for the two
+ * expected interrupt sources : decrementer and external interrupts.
+ */
+ vectorDesc.exceptIndex = ASM_DEC_VECTOR;
+ vectorDesc.hdl.vector = ASM_DEC_VECTOR;
+ vectorDesc.hdl.raw_hdl = decrementer_exception_vector_prolog_code;
+ vectorDesc.hdl.raw_hdl_size = (unsigned) &decrementer_exception_vector_prolog_code_size;
+ vectorDesc.on = nop_func2;
+ vectorDesc.off = nop_func2;
+ vectorDesc.isOn = connected;
+ if (!ppc_set_exception (&vectorDesc)) {
+ BSP_panic("Unable to initialize RTEMS decrementer raw exception\n");
+ }
+ vectorDesc.exceptIndex = ASM_EXT_VECTOR;
+ vectorDesc.hdl.vector = ASM_EXT_VECTOR;
+ vectorDesc.hdl.raw_hdl = external_exception_vector_prolog_code;
+ vectorDesc.hdl.raw_hdl_size = (unsigned) &external_exception_vector_prolog_code_size;
+ if (!ppc_set_exception (&vectorDesc)) {
+ BSP_panic("Unable to initialize RTEMS external raw exception\n");
+ }
+#ifdef TRACE_IRQ_INIT
+ printk("RTEMS IRQ management is now operationnal\n");
+#endif
+}
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/network/network_fec.c b/c/src/lib/libbsp/powerpc/tqm8xx/network/network_fec.c
new file mode 100644
index 0000000000..fd2346ed24
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/network/network_fec.c
@@ -0,0 +1,926 @@
+/*===============================================================*\
+| Project: RTEMS TQM8xx BSP |
++-----------------------------------------------------------------+
+| This file has been adapted to MPC8xx by |
+| Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> |
+| Copyright (c) 2008 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
+| |
+| See the other copyright notice below for the original parts. |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the console driver |
+\*===============================================================*/
+/* derived from: */
+/*
+ * RTEMS/TCPIP driver for MPC8xx Ethernet
+ *
+ * split into separate driver files for SCC and FEC by
+ * Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
+ *
+ * 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 <errno.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>
+#include <bsp/irq.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.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
+
+#define INET_ADDR_MAX_BUF_SIZE (sizeof "255.255.255.255")
+
+/*
+ * 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
+
+/*
+ * Per-device data
+ */
+struct m8xx_fec_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_fec_enet_struct enet_driver[NIFACES];
+
+/*
+ * FEC interrupt handler
+ */
+static void m8xx_fec_interrupt_handler ()
+{
+ /*
+ * 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);
+ }
+}
+
+/*
+ * Please organize FEC controller code better by moving code from
+ * m860_fec_initialize_hardware to m8xx_fec_ethernet_on
+ */
+static void m8xx_fec_ethernet_on(){};
+static void m8xx_fec_ethernet_off(){};
+static int m8xx_fec_ethernet_isOn (const rtems_irq_connect_data* ptr)
+{
+ return BSP_irq_enabled_at_siu (ptr->name);
+}
+
+static rtems_irq_connect_data ethernetFECIrqData = {
+ BSP_FAST_ETHERNET_CTRL,
+ (rtems_irq_hdl) m8xx_fec_interrupt_handler,
+ (rtems_irq_enable) m8xx_fec_ethernet_on,
+ (rtems_irq_disable) m8xx_fec_ethernet_off,
+ (rtems_irq_is_enabled)m8xx_fec_ethernet_isOn
+};
+
+static void
+m8xx_fec_initialize_hardware (struct m8xx_fec_enet_struct *sc)
+{
+ int i;
+ unsigned char *hwaddr;
+
+ /*
+ * 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 = ((((unsigned) BSP_FAST_ETHERNET_CTRL)/2) << 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
+ */
+ if (!BSP_install_rtems_irq_handler (&ethernetFECIrqData))
+ rtems_panic ("Can't attach M860 FEC interrupt handler\n");
+
+}
+static void fec_rxDaemon (void *arg)
+{
+ struct m8xx_fec_enet_struct *sc = (struct m8xx_fec_enet_struct *)arg;
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ struct mbuf *m;
+ uint16_t 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_cache_invalidate_multiple_data_lines((const void *)rxBd->buffer, rxBd->length);
+
+ m = sc->rxMbuf[rxBdIndex];
+ m->m_len = m->m_pkthdr.len = rxBd->length -
+ sizeof(uint32_t) -
+ 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;
+ }
+}
+
+/*
+ * 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_fec_Enet_retire_tx_bd (struct m8xx_fec_enet_struct *sc)
+{
+ uint16_t 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;
+ }
+}
+
+static void fec_sendpacket (struct ifnet *ifp, struct mbuf *m)
+{
+ struct m8xx_fec_enet_struct *sc = ifp->if_softc;
+ volatile m8xxBufferDescriptor_t *firstTxBd, *txBd;
+ /* struct mbuf *l = NULL; */
+ uint16_t status;
+ int nAdded;
+
+ /*
+ * Free up buffer descriptors
+ */
+ m8xx_fec_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_fec_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_fec_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_cache_flush_multiple_data_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;
+ }
+}
+void fec_txDaemon (void *arg)
+{
+ struct m8xx_fec_enet_struct *sc = (struct m8xx_fec_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;
+ }
+}
+static void fec_init (void *arg)
+{
+ struct m8xx_fec_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;
+}
+
+/*
+ * Send packet (caller provides header).
+ */
+static void
+m8xx_fec_enet_start (struct ifnet *ifp)
+{
+ struct m8xx_fec_enet_struct *sc = ifp->if_softc;
+
+ rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT);
+ ifp->if_flags |= IFF_OACTIVE;
+}
+
+static void fec_stop (struct m8xx_fec_enet_struct *sc)
+{
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+
+ ifp->if_flags &= ~IFF_RUNNING;
+
+ /*
+ * Shut down receiver and transmitter
+ */
+ m8xx.fec.ecntrl = 0x0;
+}
+
+/*
+ * Show interface statistics
+ */
+static void fec_enet_stats (struct m8xx_fec_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);
+}
+
+static int fec_ioctl (struct ifnet *ifp, int command, caddr_t data)
+{
+ struct m8xx_fec_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:
+ fec_enet_stats (sc);
+ break;
+
+ /*
+ * FIXME: All sorts of multicast commands need to be added here!
+ */
+ default:
+ error = EINVAL;
+ break;
+ }
+ return error;
+}
+int rtems_fec_driver_attach (struct rtems_bsdnet_ifconfig *config)
+{
+ struct m8xx_fec_enet_struct *sc;
+ struct ifnet *ifp;
+ int mtu;
+ int unitNumber;
+ char *unitName;
+ static const uint8_t maczero[] ={0,0,0,0,0,0};
+
+ /*
+ * 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);
+ }
+#ifdef BSP_HAS_TQMMON
+ else if(0 != memcmp(maczero,TQM_BD_INFO.eth_addr,ETHER_ADDR_LEN)) {
+ memcpy (sc->arpcom.ac_enaddr, TQM_BD_INFO.eth_addr, ETHER_ADDR_LEN);
+ }
+#endif
+ 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_fec_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;
+};
+
+int rtems_fec_enet_driver_attach(struct rtems_bsdnet_ifconfig *config,
+ int attaching)
+{
+ return rtems_fec_driver_attach(config);
+}
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/network/network_scc.c b/c/src/lib/libbsp/powerpc/tqm8xx/network/network_scc.c
new file mode 100644
index 0000000000..317ef27a6f
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/network/network_scc.c
@@ -0,0 +1,1047 @@
+/*===============================================================*\
+| Project: RTEMS TQM8xx BSP |
++-----------------------------------------------------------------+
+| This file has been adapted to MPC8xx by |
+| Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> |
+| Copyright (c) 2008 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
+| |
+| See the other copyright notice below for the original parts. |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the console driver |
+\*===============================================================*/
+/* derived from: */
+/*
+ * 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 <errno.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>
+#include <bsp/irq.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.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
+
+#define INET_ADDR_MAX_BUF_SIZE (sizeof "255.255.255.255")
+
+/*
+ * 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
+
+/*
+ * 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];
+
+static void m8xx_scc1_ethernet_on(const rtems_irq_connect_data* ptr)
+{
+}
+
+static void m8xx_scc1_ethernet_off(const rtems_irq_connect_data* ptr)
+{
+ /*
+ * Please put relevant code there
+ */
+}
+
+static void m8xx_scc1_ethernet_isOn(const rtems_irq_connect_data* ptr)
+{
+ int BSP_irq_enabled_at_cpm(const rtems_irq_number );
+ BSP_irq_enabled_at_cpm (ptr->name);
+}
+
+/*
+ * SCC1 interrupt handler
+ */
+static void m8xx_scc1_interrupt_handler (void *unused)
+{
+ /* 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);
+ }
+}
+
+
+static rtems_irq_connect_data ethernetSCC1IrqData = {
+ BSP_CPM_IRQ_SCC1,
+ (rtems_irq_hdl) m8xx_scc1_interrupt_handler,
+ 0,
+ (rtems_irq_enable) m8xx_scc1_ethernet_on,
+ (rtems_irq_disable) m8xx_scc1_ethernet_off,
+ (rtems_irq_is_enabled)m8xx_scc1_ethernet_isOn
+};
+
+/*
+ * Initialize the ethernet hardware
+ */
+static void
+m8xx_enet_initialize (struct m8xx_enet_struct *sc)
+{
+ int i;
+ unsigned char *hwaddr;
+
+ /*
+ * 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
+ */
+ if (!BSP_install_rtems_irq_handler (&ethernetSCC1IrqData)) {
+ rtems_panic ("Can't attach M8xx SCC1 interrupt handler\n");
+ }
+ m8xx.scc1.sccm = 0; /* No interrupts unmasked till necessary */
+
+ /*
+ * 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;
+
+ /*
+ * Enable receiver and transmitter
+ */
+ m8xx.scc1.gsmr_l = 0x1088003c;
+}
+
+
+/*
+ * 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)
+{
+ uint16_t 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
+ */
+ 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;
+ uint16_t 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_cache_invalidate_multiple_data_lines((const void *)rxBd->buffer, rxBd->length);
+
+ m = sc->rxMbuf[rxBdIndex];
+ m->m_len = m->m_pkthdr.len = rxBd->length -
+ sizeof(uint32_t) -
+ 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;
+ }
+}
+
+
+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;
+ uint16_t 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_cache_flush_multiple_data_lines((const void *)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;
+ }
+}
+
+
+/*
+ * 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;
+ }
+}
+
+
+/*
+ * 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;
+}
+
+
+/*
+ * 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;
+}
+
+
+/*
+ * 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, ioctl_command_t 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;
+}
+
+
+/*
+ * 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;
+ static const uint8_t maczero[] ={0,0,0,0,0,0};
+ /*
+ * 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
+ */
+
+ /*
+ * MAC address: try to fetch it from config, else from TQMMon, else panic
+ */
+ if (config->hardware_address) {
+ memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
+ }
+#ifdef BSP_HAS_TQMMON
+ else if(0 != memcmp(maczero,TQM_BD_INFO.eth_addr,ETHER_ADDR_LEN)) {
+ memcpy (sc->arpcom.ac_enaddr, TQM_BD_INFO.eth_addr, ETHER_ADDR_LEN);
+ }
+#endif
+ else {
+ /* There is no ethernet address provided, so it could be read
+ * from the Ethernet protocol block of SCC1 in DPRAM.
+ */
+ rtems_panic("No Ethernet address specified!\n");
+ }
+
+ 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;
+};
+
+int
+rtems_scc_enet_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching)
+{
+ return rtems_scc1_driver_attach(config);
+}
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/preinstall.am b/c/src/lib/libbsp/powerpc/tqm8xx/preinstall.am
new file mode 100644
index 0000000000..123726ebb4
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/preinstall.am
@@ -0,0 +1,104 @@
+## Automatically generated by ampolish3 - Do not edit
+
+if AMPOLISH3
+$(srcdir)/preinstall.am: Makefile.am
+ $(AMPOLISH3) $(srcdir)/Makefile.am > $(srcdir)/preinstall.am
+endif
+
+PREINSTALL_DIRS =
+DISTCLEANFILES += $(PREINSTALL_DIRS)
+
+all-local: $(TMPINSTALL_FILES)
+
+TMPINSTALL_FILES =
+CLEANFILES = $(TMPINSTALL_FILES)
+
+all-am: $(PREINSTALL_FILES)
+
+PREINSTALL_FILES =
+CLEANFILES += $(PREINSTALL_FILES)
+
+$(PROJECT_LIB)/$(dirstamp):
+ @$(MKDIR_P) $(PROJECT_LIB)
+ @: > $(PROJECT_LIB)/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_LIB)/$(dirstamp)
+
+$(PROJECT_INCLUDE)/$(dirstamp):
+ @$(MKDIR_P) $(PROJECT_INCLUDE)
+ @: > $(PROJECT_INCLUDE)/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp)
+
+$(PROJECT_LIB)/bsp_specs: bsp_specs $(PROJECT_LIB)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_LIB)/bsp_specs
+PREINSTALL_FILES += $(PROJECT_LIB)/bsp_specs
+
+$(PROJECT_INCLUDE)/bsp.h: include/bsp.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp.h
+
+$(PROJECT_INCLUDE)/tm27.h: include/tm27.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/tm27.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/tm27.h
+
+../../../libcpu/@RTEMS_CPU@/$(dirstamp):
+ @$(MKDIR_P) ../../../libcpu/@RTEMS_CPU@
+ @: > ../../../libcpu/@RTEMS_CPU@/$(dirstamp)
+PREINSTALL_DIRS += ../../../libcpu/@RTEMS_CPU@/$(dirstamp)
+
+$(PROJECT_INCLUDE)/bspopts.h: include/bspopts.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bspopts.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bspopts.h
+
+$(PROJECT_INCLUDE)/bsp/$(dirstamp):
+ @$(MKDIR_P) $(PROJECT_INCLUDE)/bsp
+ @: > $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+
+$(PROJECT_INCLUDE)/coverhd.h: include/coverhd.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/coverhd.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/coverhd.h
+
+$(PROJECT_INCLUDE)/bsp/tqm.h: include/tqm.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/tqm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/tqm.h
+
+$(PROJECT_INCLUDE)/bsp/8xx_immap.h: include/8xx_immap.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/8xx_immap.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/8xx_immap.h
+
+$(PROJECT_INCLUDE)/bsp/irq.h: include/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h
+
+$(PROJECT_INCLUDE)/bsp/irq-config.h: include/irq-config.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-config.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-config.h
+
+$(PROJECT_INCLUDE)/bsp/irq-generic.h: ../../shared/include/irq-generic.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-generic.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-generic.h
+
+$(PROJECT_INCLUDE)/bsp/vectors.h: $(libcpudir)/@exceptions@/bspsupport/vectors.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/vectors.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/vectors.h
+
+$(PROJECT_INCLUDE)/bsp/ppc_exc_bspsupp.h: $(libcpudir)/@exceptions@/bspsupport/ppc_exc_bspsupp.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/ppc_exc_bspsupp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/ppc_exc_bspsupp.h
+
+$(PROJECT_LIB)/start.$(OBJEXT): start.$(OBJEXT) $(PROJECT_LIB)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_LIB)/start.$(OBJEXT)
+TMPINSTALL_FILES += $(PROJECT_LIB)/start.$(OBJEXT)
+
+$(PROJECT_LIB)/rtems_crti.$(OBJEXT): rtems_crti.$(OBJEXT) $(PROJECT_LIB)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_LIB)/rtems_crti.$(OBJEXT)
+TMPINSTALL_FILES += $(PROJECT_LIB)/rtems_crti.$(OBJEXT)
+
+$(PROJECT_LIB)/linkcmds.base: startup/linkcmds.base $(PROJECT_LIB)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds.base
+PREINSTALL_FILES += $(PROJECT_LIB)/linkcmds.base
+
+$(PROJECT_LIB)/linkcmds.tqm8xx: startup/linkcmds.tqm8xx $(PROJECT_LIB)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds.tqm8xx
+PREINSTALL_FILES += $(PROJECT_LIB)/linkcmds.tqm8xx
+
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/startup/bspstart.c b/c/src/lib/libbsp/powerpc/tqm8xx/startup/bspstart.c
new file mode 100644
index 0000000000..2b4b38fe87
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/startup/bspstart.c
@@ -0,0 +1,234 @@
+/**
+ * @file
+ *
+ * @ingroup tqm8xx
+ *
+ * @brief Source for BSP startup code.
+ */
+
+/*
+ * Copyright (c) 2008
+ * Embedded Brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * rtems@embedded-brains.de
+ *
+ * The license and distribution terms for this file may be found in the file
+ * LICENSE in this distribution or at http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <string.h>
+
+#include <rtems/libio.h>
+#include <rtems/libcsupport.h>
+#include <rtems/score/thread.h>
+
+#include <libcpu/powerpc-utility.h>
+
+#include <bsp.h>
+#include <bsp/bootcard.h>
+/* #include <bsp/irq-generic.h>
+ #include <bsp/ppc_exc_bspsupp.h> */
+
+#ifdef BSP_HAS_TQMMON
+/*
+ * FIXME: TQ Monitor structure
+ */
+#endif /* BSP_HAS_TQMMON */
+
+/* Configuration parameters for console driver, ... */
+unsigned int BSP_bus_frequency;
+
+/* Configuration parameters for clock driver, ... */
+uint32_t bsp_clicks_per_usec; /* for PIT driver: OSCCLK */
+uint32_t bsp_clock_speed ; /* needed for PIT driver */
+
+/*
+ * Use the shared implementations of the following routines.
+ * Look in rtems/c/src/lib/libbsp/shared/bsplibc.c.
+ */
+extern void cpu_init( void);
+
+void BSP_panic( char *s)
+{
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable( level);
+
+ printk( "%s PANIC %s\n", _RTEMS_version, s);
+
+ while (1) {
+ /* Do nothing */
+ }
+}
+
+void _BSP_Fatal_error( unsigned n)
+{
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable( level);
+
+ printk( "%s PANIC ERROR %u\n", _RTEMS_version, n);
+
+ while (1) {
+ /* Do nothing */
+ }
+}
+
+void bsp_pretasking_hook( void)
+{
+ /* Do noting */
+}
+
+const char *bsp_tqm_get_cib_string( const char *cib_id)
+{
+ char srch_pattern[10] = "";
+ char *fnd_str;
+ /*
+ * create search pattern
+ */
+ strcat(srch_pattern,"-");
+ strncat(srch_pattern,
+ cib_id,
+ sizeof(srch_pattern)-1-strlen(srch_pattern));
+ strncat(srch_pattern,
+ " ",
+ sizeof(srch_pattern)-1-strlen(srch_pattern));
+ /*
+ * search for pattern in info block (CIB)
+ */
+ fnd_str = strstr(TQM_CONF_INFO_BLOCK_ADDR,srch_pattern);
+
+ if (fnd_str == NULL) {
+ return NULL;
+ }
+ else {
+ /*
+ * found? then advance behind search pattern
+ */
+ return fnd_str + strlen(srch_pattern);
+ }
+}
+
+rtems_status_code bsp_tqm_get_cib_uint32( const char *cib_id,
+ uint32_t *result)
+{
+ const char *item_ptr;
+ const char *end_ptr;
+ item_ptr = bsp_tqm_get_cib_string(cib_id);
+ if (item_ptr == NULL) {
+ return RTEMS_INVALID_ID;
+ }
+ /*
+ * convert string to uint32
+ */
+ *result = strtoul(item_ptr,&end_ptr,10);
+ return RTEMS_SUCCESSFUL;
+}
+
+void bsp_get_work_area( void **work_area_start, size_t *work_area_size, void **heap_start, size_t *heap_size)
+{
+ char *ram_end = (char *) (TQM_BD_INFO.sdram_size - (uint32_t)TopRamReserved);
+
+ *work_area_start = bsp_work_area_start;
+ *work_area_size = ram_end - bsp_work_area_start;
+ *heap_start = BSP_BOOTCARD_HEAP_USES_WORK_AREA;
+ *heap_size = BSP_BOOTCARD_HEAP_SIZE_DEFAULT;
+}
+
+void bsp_start( void)
+{
+ ppc_cpu_id_t myCpu;
+ ppc_cpu_revision_t myCpuRevision;
+
+ uint32_t interrupt_stack_start = (uint32_t) bsp_interrupt_stack_start;
+ uint32_t interrupt_stack_size = (uint32_t) bsp_interrupt_stack_size;
+
+ /*
+ * Get CPU identification dynamically. Note that the get_ppc_cpu_type() function
+ * store the result in global variables so that it can be used latter...
+ */
+ myCpu = get_ppc_cpu_type();
+ myCpuRevision = get_ppc_cpu_revision();
+
+ /* Basic CPU initialization */
+ cpu_init();
+
+ /*
+ * Enable instruction and data caches. Do not force writethrough mode.
+ */
+
+#if INSTRUCTION_CACHE_ENABLE
+ rtems_cache_enable_instruction();
+#endif
+
+#if DATA_CACHE_ENABLE
+ rtems_cache_enable_data();
+#endif
+
+ /*
+ * This is evaluated during runtime, so it should be ok to set it
+ * before we initialize the drivers.
+ */
+
+ /* Initialize some device driver parameters */
+ /*
+ * get the (internal) bus frequency
+ * NOTE: the external bus may be clocked at a lower speed
+ * but this does not concern the internal units like PIT,
+ * DEC, baudrate generator etc)
+ */
+ if (RTEMS_SUCCESSFUL !=
+ bsp_tqm_get_cib_uint32("cu",
+ &BSP_bus_frequency)) {
+ BSP_panic("Cannot determine BUS frequency\n");
+ }
+
+ bsp_clicks_per_usec = 0; /* force to zero to control
+ * PIT clock driver from EXTCLK
+ */
+ bsp_clock_speed = BSP_bus_frequency;
+
+ /* Initialize exception handler */
+ ppc_exc_initialize(PPC_INTERRUPT_DISABLE_MASK_DEFAULT,
+ interrupt_stack_start,
+ interrupt_stack_size
+ );
+
+ /* Initalize interrupt support */
+ if (bsp_interrupt_initialize() != RTEMS_SUCCESSFUL) {
+ BSP_panic("Cannot intitialize interrupt support\n");
+ }
+
+#ifdef SHOW_MORE_INIT_SETTINGS
+ printk("Exit from bspstart\n");
+#endif
+}
+
+/**
+ * @brief Idle thread body.
+ *
+ * Replaces the one in c/src/exec/score/src/threadidlebody.c
+ * The MSR[POW] bit is set to put the CPU into the low power mode
+ * defined in HID0. HID0 is set during starup in start.S.
+ */
+Thread _Thread_Idle_body( uint32_t ignored)
+{
+
+ while (1) {
+ asm volatile (
+ "mfmsr 3;"
+ "oris 3, 3, 4;"
+ "sync;"
+ "mtmsr 3;"
+ "isync;"
+ "ori 3, 3, 0;"
+ "ori 3, 3, 0"
+ );
+ }
+
+ return NULL;
+}
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/startup/cpuinit.c b/c/src/lib/libbsp/powerpc/tqm8xx/startup/cpuinit.c
new file mode 100644
index 0000000000..e99e9d9a6a
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/startup/cpuinit.c
@@ -0,0 +1,134 @@
+/*
+ * cpuinit.c
+ *
+ * TQM8xx initialization routines.
+ * derived from MBX8xx BSP
+ * adapted to TQM8xx by Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
+ *
+ * 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.rtems.com/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <bsp/tqm.h>
+
+
+/*
+ * Initialize TQM8xx
+ */
+void _InitTQM8xx (void)
+{
+ register uint32_t 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 SIU Module Configuration Register (SIUMCR)
+ * m8xx.siumcr = 0x00602900, the default 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
+ */
+ m8xx.sccrk = M8xx_UNLOCK_KEY; /* unlock SCCR */
+ m8xx.sccr |= 0x02000000;
+
+ /* 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 );
+}
+/*
+ * further initialization (called from bsp_start)
+ */
+void cpu_init(void)
+{
+ /*
+ * none up to now
+ */
+}
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/startup/linkcmds.base b/c/src/lib/libbsp/powerpc/tqm8xx/startup/linkcmds.base
new file mode 100644
index 0000000000..c4a0eec115
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/startup/linkcmds.base
@@ -0,0 +1,316 @@
+/**
+ * @file
+ *
+ * Derived from internal linker script of GNU ld (GNU Binutils) 2.18 for elf32ppc emulation.
+ */
+
+OUTPUT_FORMAT ("elf32-powerpc", "elf32-powerpc", "elf32-powerpc")
+OUTPUT_ARCH (powerpc)
+ENTRY (start)
+
+bsp_ram_start = ORIGIN (RAM);
+bsp_ram_end = ORIGIN (RAM) + LENGTH (RAM);
+bsp_ram_size = LENGTH (RAM);
+
+bsp_rom_start = ORIGIN (ROM);
+bsp_rom_end = ORIGIN (ROM) + LENGTH (ROM);
+bsp_rom_size = LENGTH (ROM);
+
+bsp_section_align = 32;
+
+SECTIONS {
+
+ dpram :
+ {
+ m8xx = .;
+ _m8xx = .;
+ /* . += (16 * 1024); this makes the mbx loader crash */
+ } >immr
+
+ /*
+ * BSP: Exception vectors
+ */
+ .vectors 0x100 : {
+ *(.vectors)
+ } > RAM
+
+ /*
+ * BSP: The initial stack will live in this area - between the vectors
+ * and the text section.
+ */
+
+ .text 0x10000 : {
+ /*
+ * BSP: Start of text section
+ */
+ bsp_section_text_start = .;
+
+ /*
+ * BSP: System startup entry
+ */
+ KEEP (*(.entry))
+
+ /*
+ * BSP: Moved into .text from .init
+ */
+ KEEP (*(.init))
+
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ KEEP (*(.text.*personality*))
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.glink)
+
+ /*
+ * BSP: Special FreeBSD sysctl sections
+ */
+ . = ALIGN (16);
+ __start_set_sysctl_set = .;
+ *(set_sysctl_*);
+ __stop_set_sysctl_set = ABSOLUTE(.);
+ *(set_domain_*);
+ *(set_pseudo_*);
+
+ /*
+ * BSP: Moved into .text from .*
+ */
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.rodata1)
+ *(.interp)
+ *(.note.gnu.build-id)
+ *(.hash)
+ *(.gnu.hash)
+ *(.dynsym)
+ *(.dynstr)
+ *(.gnu.version)
+ *(.gnu.version_d)
+ *(.gnu.version_r)
+ *(.eh_frame_hdr)
+
+ /*
+ * BSP: Magic PPC stuff
+ */
+ *(.PPC.*)
+
+ /*
+ * BSP: Required by cpukit/score/src/threadhandler.c
+ */
+ PROVIDE (_fini = .);
+
+ /*
+ * BSP: Moved into .text from .fini
+ */
+ KEEP (*(.fini))
+
+ . = ALIGN (bsp_section_align);
+
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+ } > RAM
+
+ .sdata2 : {
+ PROVIDE (_SDA2_BASE_ = 32768);
+
+ *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
+
+ . = ALIGN (bsp_section_align);
+ } > RAM
+
+ .sbss2 : {
+ *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*)
+
+ . = ALIGN (bsp_section_align);
+
+ /*
+ * BSP: End and size of text section
+ */
+ bsp_section_text_end = .;
+ bsp_section_text_size = bsp_section_text_end - bsp_section_text_start;
+ } > RAM
+
+ .data : {
+ /*
+ * BSP: Start of data section
+ */
+ bsp_section_data_start = .;
+
+ /*
+ * BSP: Moved into .data from .ctors
+ */
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*crtbegin?.o(.ctors))
+ /* We don't want to include the .ctor section from
+ the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+
+ /*
+ * BSP: Moved into .data from .dtors
+ */
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*crtbegin?.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+
+ /*
+ * BSP: Moved into .data from .*
+ */
+ *(.tdata .tdata.* .gnu.linkonce.td.*)
+ *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon)
+ *(.data1)
+ KEEP (*(.eh_frame))
+ *(.gcc_except_table .gcc_except_table.*)
+ KEEP (*(.jcr))
+ *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*)
+ *(.fixup)
+ *(.got1)
+ *(.got2)
+ *(.dynamic)
+ *(.got)
+ *(.plt)
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+
+ *(.data .data.* .gnu.linkonce.d.*)
+ KEEP (*(.gnu.linkonce.d.*personality*))
+ SORT(CONSTRUCTORS)
+
+ . = ALIGN (bsp_section_align);
+ } > RAM
+
+ .sdata : {
+ PROVIDE (_SDA_BASE_ = 32768);
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+
+ . = ALIGN (bsp_section_align);
+
+ _edata = .;
+ PROVIDE (edata = .);
+
+ /*
+ * BSP: End and size of data section
+ */
+ bsp_section_data_end = .;
+ bsp_section_data_size = bsp_section_data_end - bsp_section_data_start;
+ } > RAM
+
+ .sbss : {
+ /*
+ * BSP: Start of bss section
+ */
+ bsp_section_bss_start = .;
+
+ __bss_start = .;
+
+ PROVIDE (__sbss_start = .); PROVIDE (___sbss_start = .);
+ *(.scommon)
+ *(.dynsbss)
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ PROVIDE (__sbss_end = .); PROVIDE (___sbss_end = .);
+
+ . = ALIGN (bsp_section_align);
+ } > RAM
+
+ .bss : {
+ *(COMMON)
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+
+ . = ALIGN (bsp_section_align);
+
+ __end = .;
+ _end = .;
+ PROVIDE (end = .);
+
+ /*
+ * BSP: End and size of bss section
+ */
+ bsp_section_bss_end = .;
+ bsp_section_bss_size = bsp_section_bss_end - bsp_section_bss_start;
+ } > RAM
+
+ /*
+ * BSP: Interrupt stack
+ */
+ bsp_interrupt_stack_start = .;
+ bsp_interrupt_stack_end = bsp_interrupt_stack_start + 32k;
+ bsp_interrupt_stack_size = bsp_interrupt_stack_end - bsp_interrupt_stack_start;
+ . = bsp_interrupt_stack_end;
+
+ /*
+ * BSP: Work area start
+ */
+ bsp_work_area_start = .;
+
+ /* 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 .gnu.linkonce.wi.*) }
+ .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) }
+ /* DWARF 3 */
+ .debug_pubtypes 0 : { *(.debug_pubtypes) }
+ .debug_ranges 0 : { *(.debug_ranges) }
+ .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+
+ /DISCARD/ : {
+ *(.note.GNU-stack) *(.gnu_debuglink)
+ }
+
+ /*
+ * BSP: Catch all unknown sections
+ */
+ .nirvana : {
+ *(*)
+ } > NIRVANA
+}
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/startup/linkcmds.tqm8xx b/c/src/lib/libbsp/powerpc/tqm8xx/startup/linkcmds.tqm8xx
new file mode 100644
index 0000000000..69b9c32799
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/startup/linkcmds.tqm8xx
@@ -0,0 +1,15 @@
+/**
+ * @file
+ *
+ * TQM8xx
+ */
+
+TopRamReserved = DEFINED(TopRamReserved) ? TopRamReserved : 0;
+MEMORY {
+ RAM : ORIGIN = 0x0, LENGTH = 128M
+ immr : org = 0xfa200000, l = 16K
+ ROM : ORIGIN = 0x40000000, LENGTH = 8M
+ NIRVANA : ORIGIN = 0x0, LENGTH = 0
+}
+
+INCLUDE linkcmds.base
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/startup/mmutlbtab.c b/c/src/lib/libbsp/powerpc/tqm8xx/startup/mmutlbtab.c
new file mode 100644
index 0000000000..6dc3aea712
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/startup/mmutlbtab.c
@@ -0,0 +1,103 @@
+/*===============================================================*\
+| Project: RTEMS TQM8xx BSP |
++-----------------------------------------------------------------+
+| This file has been adapted to MPC8xx by |
+| Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> |
+| Copyright (c) 2008 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
+| |
+| See the other copyright notice below for the original parts. |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the console driver |
+\*===============================================================*/
+/* derived from: */
+/*
+ * mmutlbtab.c
+ *
+ * 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.rtems.com/license/LICENSE.
+ */
+
+#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 TQM8xx 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: Start address 0x00000000, 128M,
+ * ASID=0x0, APG=0x0, not guarded memory, copyback data cache policy,
+ * R/W,X for all, no ASID comparison, not cache-inhibited.
+ * EPN TWC RPN
+ */
+ { 0x00000200, 0x0D, 0x000009FD }, /* DRAM - PS=8M */
+ { 0x00800200, 0x0D, 0x008009FD }, /* DRAM - PS=8M */
+ { 0x01000200, 0x0D, 0x010009FD }, /* DRAM - PS=8M */
+ { 0x01800200, 0x0D, 0x018009FD }, /* DRAM - PS=8M */
+ { 0x02000200, 0x0D, 0x020009FD }, /* DRAM - PS=8M */
+ { 0x02800200, 0x0D, 0x028009FD }, /* DRAM - PS=8M */
+ { 0x03000200, 0x0D, 0x030009FD }, /* DRAM - PS=8M */
+ { 0x03800200, 0x0D, 0x038009FD }, /* DRAM - PS=8M */
+ { 0x04000200, 0x0D, 0x040009FD }, /* DRAM - PS=8M */
+ { 0x04800200, 0x0D, 0x048009FD }, /* DRAM - PS=8M */
+ { 0x05000200, 0x0D, 0x050009FD }, /* DRAM - PS=8M */
+ { 0x05800200, 0x0D, 0x058009FD }, /* DRAM - PS=8M */
+ { 0x06000200, 0x0D, 0x060009FD }, /* DRAM - PS=8M */
+ { 0x06800200, 0x0D, 0x068009FD }, /* DRAM - PS=8M */
+ { 0x07000200, 0x0D, 0x070009FD }, /* DRAM - PS=8M */
+ { 0x07800200, 0x0D, 0x078009FD }, /* DRAM - PS=8M */
+ /*
+ *
+ * (IMMR-SPRs) Dual Port RAM: Start address 0xFA200000, 16K,
+ * ASID=0x0, APG=0x0, guarded memory, write-through 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, 0x13, 0xFA2009FF }, /* IMMR - PS=16K */
+ /*
+ *
+ * Flash: Start address 0x40000000, 8M,
+ * ASID=0x0, APG=0x0, not guarded memory,
+ * R/O,X for all, no ASID comparison, not cache-inhibited.
+ * EPN TWC RPN
+ */
+ { 0x40000200, 0x0D, 0x40000CFD } /* Flash - PS=8M */
+};
+
+/*
+ * 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/tqm8xx/startup/start.S b/c/src/lib/libbsp/powerpc/tqm8xx/startup/start.S
new file mode 100644
index 0000000000..42bbdb07d2
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/startup/start.S
@@ -0,0 +1,287 @@
+/*===============================================================*\
+| Project: RTEMS generic TQM8xx BSP |
++-----------------------------------------------------------------+
+| Copyright (c) 2008 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the startup assembly code |
+| it is based on the gen83xx BSP |
+\*===============================================================*/
+/* $Id$ */
+
+#include <libcpu/powerpc-utility.h>
+#include <rtems/powerpc/cache.h>
+#include <bsp.h>
+#include <mpc8xx.h>
+
+.extern boot_card
+
+.section ".entry"
+PUBLIC_VAR (start)
+start:
+
+ /*
+ * basic CPU setup:
+ * init MSR
+ */
+ mfmsr r30
+ SETBITS r30, r29, MSR_ME|MSR_RI
+ CLRBITS r30, r29, MSR_IP|MSR_EE
+ mtmsr r30 /* Set RI/ME, Clr EE in MSR */
+ /*
+ * init IMMR
+ */
+ LA r30,m8xx
+ mtspr immr,r30
+ /*
+ * determine current execution address offset
+ */
+ bl start_1
+start_1:
+ mflr r20
+ LA r30,start_1
+ sub. r20,r20,r30
+ /*
+ * execution address offset == 0?
+ * then do not relocate code and data
+ */
+ beq start_code_in_ram
+ /*
+ * ROM or relocatable startup: copy startup code to SDRAM
+ */
+ /* get start address of text section in RAM */
+ LA r29, bsp_section_text_start
+ /* get start address of text section in ROM (add reloc offset) */
+ add r30, r20, r29
+ /* get size of startup code */
+ LA r28, end_reloc_startup
+ LA r31, bsp_section_text_start
+ sub 28,r28,r31
+ /* copy startup code from ROM to RAM location */
+ bl copy_image
+
+ /*
+ * jump to code copy in SDRAM
+ */
+ /* get compile time address of label */
+ LA r29, copy_rest_of_text
+ mtlr r29
+ blr /* now further execution RAM */
+copy_rest_of_text:
+ /*
+ * ROM or relocatable startup: copy rest of code to SDRAM
+ */
+ /* get start address of rest of code in RAM */
+ LA r29, end_reloc_startup
+ /* get start address of text section in ROM (add reloc offset) */
+ add r30, r20, r29
+ /* get size of rest of code */
+ LA r28, bsp_section_text_start
+ LA r31, bsp_section_text_size
+ add r28,r28,r31
+ sub r28,r28,r29
+ bl copy_image /* copy text section from ROM to RAM location */
+
+ /*
+ * ROM or relocatable startup: copy data to SDRAM
+ */
+ /* get start address of data section in RAM */
+ LA r29, bsp_section_data_start
+ /* get start address of data section in ROM (add reloc offset) */
+ add r30, r20, r29
+ /* get size of RAM image */
+ LA r28, bsp_section_data_size
+ /* copy initialized data section from ROM to RAM location */
+ bl copy_image
+
+start_code_in_ram:
+
+ /*
+ * ROM/RAM startup: clear bss in SDRAM
+ */
+ LA r3, bsp_section_bss_start /* get start address of bss section */
+ LWI r4, bsp_section_bss_size /* get size of bss section */
+ bl mpc8xx_zero_4 /* Clear the bss section */
+ /*
+ * call boot_card
+ */
+
+ /* Set stack pointer (common for RAM/ROM startup) */
+ LA r1, bsp_section_text_start
+ addi r1, r1, -0x10 /* Set up stack pointer = beginning of text section - 0x10 */
+
+ /* Create NULL */
+ li r0, 0
+
+ /* Return address */
+ stw r0, 4(r1)
+
+ /* Back chain */
+ stw r0, 0(r1)
+
+ /* Read-only small data */
+ LA r2, _SDA2_BASE_
+
+ /* Read-write small data */
+ LA r13, _SDA_BASE_
+
+ /*
+ * init some CPU stuff
+ */
+ bl SYM (_InitTQM8xx)
+
+/* clear arguments and do further init. in C (common for RAM/ROM startup) */
+
+ /* Clear argc, argv and envp */
+ xor r3, r3, r3
+ xor r4, r4, r4
+ xor r5, r5, r5
+
+ bl SYM (boot_card) /* Call the first C routine */
+
+twiddle:
+ /* We don't expect to return from boot_card but if we do */
+ /* wait here for watchdog to kick us into hard reset */
+ b twiddle
+
+copy_with_watchdog:
+ addi r5,r5,16
+ rlwinm. r5,r5,28,4,31
+ mtctr r5
+
+copy_loop:
+ lwz r6,0(r3)
+ lwz r7,4(r3)
+ lwz r8,8(r3)
+ lwz r9,12(r3)
+ stw r6,0(r4)
+ stw r7,4(r4)
+ stw r8,8(r4)
+ stw r9,12(r4)
+ addi r3,r3,16
+ addi r4,r4,16
+ sth r28,14(r30)
+ sth r29,14(r30)
+ bdnz+ copy_loop
+ blr
+
+copy_image:
+ /*
+ * watchdog:
+ * r26 = immr
+ * r25 = watchdog magic 1
+ * r24 = watchdog magic 2
+ */
+ mfimmr r26
+ rlwinm. r26,r26,0,0,15
+ li r25,0x556c
+ li r24,0xffffaa39
+
+ mr r27, r28 /* determine number of 4word chunks */
+ srwi r28, r28, 4
+ mtctr r28
+
+ slwi r28, r28, 4
+ sub r27, r27, r28 /* determine residual bytes */
+copy_image_4word:
+ lwz r20, 0(r30) /* fetch data */
+ lwz r21, 4(r30)
+ lwz r22, 8(r30)
+ lwz r23,12(r30)
+ stw r20, 0(r29) /* store data */
+ stw r21, 4(r29)
+ stw r22, 8(r29)
+ stw r23,12(r29)
+
+ addi r30, r30, 0x10 /* increment source pointer */
+ addi r29, r29, 0x10 /* increment destination pointer */
+ /*
+ * trigger watchdog
+ */
+ sth r25,14(r26)
+ sth r24,14(r26)
+
+ bdnz copy_image_4word /* decrement ctr and branch if not 0 */
+
+ cmpwi r27, 0x00 /* copy image finished ? */
+ beq copy_image_end;
+ mtctr r27 /* reload counter for residual bytes */
+copy_image_byte:
+ lswi r28, r30, 0x01
+
+ stswi r28, r29, 0x01 /* do byte copy ROM -> RAM */
+
+
+ addi r30, r30, 0x01 /* increment source pointer */
+ addi r29, r29, 0x01 /* increment destination pointer */
+
+ bdnz copy_image_byte /* decrement ctr and branch if not 0 */
+
+copy_image_end:
+ blr
+
+
+/**
+ * @fn int mpc8xx_zero_4( void *dest, size_t n)
+ *
+ * @brief Zero all @a n bytes starting at @a dest with 4 byte writes.
+ *
+ * The address @a dest has to be aligned on 4 byte boundaries. The size @a n
+ * must be evenly divisible by 4.
+ */
+GLOBAL_FUNCTION mpc8xx_zero_4
+ /* Create zero */
+ xor r0, r0, r0
+
+ /* Set offset */
+ xor r5, r5, r5
+
+ /* Loop counter for the first bytes up to 16 bytes */
+ rlwinm. r9, r4, 30, 30, 31
+ beq mpc8xx_zero_4_more
+ mtctr r9
+
+mpc8xx_zero_4_head:
+
+ stwx r0, r3, r5
+ addi r5, r5, 4
+ bdnz mpc8xx_zero_4_head
+
+mpc8xx_zero_4_more:
+
+ /* More than 16 bytes? */
+ srwi. r9, r4, 4
+ beqlr
+ mtctr r9
+
+ /* Set offsets */
+ addi r6, r5, 4
+ addi r7, r5, 8
+ addi r8, r5, 12
+
+mpc8xx_zero_4_tail:
+
+ stwx r0, r3, r5
+ addi r5, r5, 16
+ stwx r0, r3, r6
+ addi r6, r6, 16
+ stwx r0, r3, r7
+ addi r7, r7, 16
+ stwx r0, r3, r8
+ addi r8, r8, 16
+ bdnz mpc8xx_zero_4_tail
+
+ /* Return */
+ blr
+
+end_reloc_startup:
diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/timer/timer.c b/c/src/lib/libbsp/powerpc/tqm8xx/timer/timer.c
new file mode 100644
index 0000000000..1df80461d1
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/tqm8xx/timer/timer.c
@@ -0,0 +1,110 @@
+/*===============================================================*\
+| Project: RTEMS TQM8xx BSP |
++-----------------------------------------------------------------+
+| This file has been adapted to MPC8xx by |
+| Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> |
+| Copyright (c) 2008 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
+| |
+| See the other copyright notice below for the original parts. |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the console driver |
+\*===============================================================*/
+/*
+ * Timer_init()
+ *
+ * Use TIMER 1 and TIMER 2 for Timing Test Suite
+ *
+ * this is derived from "timer.c" available in the m68k/gen68360 BSP
+ * adapted by Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
+ *
+ * $Id$
+ */
+
+/*
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * NOTE: It is important that the timer start/stop overhead be
+ * determined when porting or modifying this code.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <bsp.h>
+#include <mpc8xx.h>
+
+void
+Timer_initialize (void)
+{
+ /*
+ * Reset timers 1 and 2
+ */
+ m8xx.tgcr &= ~0x00FF;
+ m8xx.tcn1 = 0;
+ m8xx.tcn2 = 0;
+ m8xx.ter1 = 0xFFFF;
+ m8xx.ter2 = 0xFFFF;
+
+ /*
+ * Cascade timers 1 and 2
+ */
+ m8xx.tgcr |= M8xx_TGCR_CAS2;
+
+ /*
+ * Configure timers 1 and 2 to a single 32-bit, BUS_clock timer.
+ */
+ m8xx.tmr2 = (0 << 8) | 0x2;
+ m8xx.tmr1 = 0;
+
+ /*
+ * Start the timers
+ */
+ m8xx.tgcr |= 0x0011;
+}
+
+/*
+ * Return timer value in microsecond units
+ */
+int
+Read_timer (void)
+{
+ extern unsigned int BSP_bus_frequency;
+ int retval;
+ retval = *(uint32_t*)&m8xx.tcn1;
+ retval = retval * 1000000LL / BSP_bus_frequency;
+ return retval;
+}
+
+/*
+ * Empty function call used in loops to measure basic cost of looping
+ * in Timing Test Suite.
+ */
+rtems_status_code
+Empty_function (void)
+{
+ return RTEMS_SUCCESSFUL;
+}
+
+void
+Set_find_average_overhead(bool find_flag)
+{
+}