summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1999-02-18 19:23:28 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1999-02-18 19:23:28 +0000
commit5d024595a7cbb8a04fad883fd89b42d61d72acf7 (patch)
tree8bffa56dd3e0d9ab2c5d61651c43da9676105644
parentMissed this file in the merge. (diff)
downloadrtems-5d024595a7cbb8a04fad883fd89b42d61d72acf7.tar.bz2
MVME167 BSP submitted by Charles Gauthier <Charles.Gauthier@iit.nrc.ca>.
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/Makefile.in18
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/README395
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/bsp_specs23
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/clock/Makefile.in54
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/clock/ckinit.c281
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/console/Makefile.in54
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/console/console.c1297
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/fatal/Makefile.in54
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/fatal/bspfatal.c127
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/fatal/fatal.c127
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/include/Makefile.in34
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/include/bsp.h478
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/include/coverhd.h104
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/include/fatal.h19
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/include/page_table.h46
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/startup/Makefile.in53
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/startup/bspclean.c81
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/startup/bspstart.c201
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/startup/linkcmds103
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/startup/page_table.c139
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/timer/Makefile.in59
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/timer/timer.c153
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/timer/timerisr.s54
-rw-r--r--c/src/lib/libbsp/m68k/mvme167/wrapup/Makefile.in49
-rw-r--r--make/custom/mvme167.cfg74
25 files changed, 4077 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/m68k/mvme167/Makefile.in b/c/src/lib/libbsp/m68k/mvme167/Makefile.in
new file mode 100644
index 0000000000..8b88d9a0a5
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/Makefile.in
@@ -0,0 +1,18 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+VPATH = @srcdir@
+RTEMS_ROOT = @top_srcdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/directory.cfg
+
+# wrapup is the one that actually builds and installs the library
+# from the individual .rel files built in other directories
+# include subdir must be first, otherwise the header files will not
+# be installed when the other files are compiled.
+SUB_DIRS=include clock console fatal startup timer wrapup
diff --git a/c/src/lib/libbsp/m68k/mvme167/README b/c/src/lib/libbsp/m68k/mvme167/README
new file mode 100644
index 0000000000..8074c6eff2
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/README
@@ -0,0 +1,395 @@
+$Id$
+
+This is a README file for the MVME167 port of RTEMS 4.0.0.
+
+Please send any comments, improvements, or bug reports to:
+
+Charles-Antoine Gauthier
+Software Engineering Group
+Institute for Information Technology
+National Research Council of Canada
+Ottawa, ON, K1A 0R6
+Canada
+
+charles.gauthier@iit.nrc.ca
+
+
+Disclaimer
+----------
+
+The National Research Council of Canada is distributing this RTEMS
+board support package for the Motorola MVME167 as free software; you
+can redistribute it and/or modify it under terms of the GNU General
+Public License as published by the Free Software Foundation; either
+version 2, or (at your option) any later version. This software is
+distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details. You should have received a copy of the GNU General
+Public License along with RTEMS; see file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Under no circumstances will the National Research Council of Canada
+nor Her Majesty the Queen in right of Canada assume any liablility
+for the use this software, nor any responsibility for its quality or
+its support.
+
+
+Installation
+------------
+
+Nothing unique to the MVME167. It uses the standard build process for
+m68k targets. You will need to edit linkcmds to put in the start address
+of your board. We do TFTP transfers to our target. The mvme167.cfg file
+builds only the coff images, which we download to the target, skipping over
+the first 0xA8 bytes; Motorola S-records are not generated. Edit this file
+if you want S-records.
+
+
+Port Description
+----------------
+
+This BSP includes an termios-capable console driver that supports all
+four serial ports on the MVME167 model. The RTEMS console, /dev/console,
+corresponds to channel 1 in the CD2401. This corresponds to Serial Port
+2/TTY01 on the MVME712M. Serial Port 1/Console is normally used by 167Bug;
+do not open /dev/tty00 if you are debugging using 167Bug.
+
+The console is initialized with whatever parameters are set up in termios
+before it calls the firtOpen driver callback, EXCEPT THAT HARDWARE HANDSHAKING
+IS TURNED OFF, i.e. CLOCAL is set in the struct termios c_cflag field. We use
+3-wire cables for I/O, and find hardware handshaking a pain. If you enable
+hardware handshaking, you must drive CTS* low on the CD2401 for output to
+occur. If the port is in the DTE configuration, you must drive the RS-232 CTS
+line to space; if the port is in the DCE configuration, you must drive the
+RS-232 RTS line to space.
+
+Limited support is provided for polled terminal I/O. This is used when running
+the timing tests. Set the CD2401_POLLED_IO manifest constant to 1 in
+rtems/c/src/lib/libbsp/m68k/mvme167/console/console.c to enable polled I/O.
+In this case, I/O is done through 167Bug, usually to the Serial Port 1/Console
+port. Interrupt-driven and polled I/O cannot be mixed in the MVME167.
+
+The timer and clock drivers were patterned after the MVME162 and MVME152
+ports.
+
+At this time, we do not have an MPCI layer for the MVME167. We are planning
+to write one.
+
+The port does not have a network driver.
+
+This port supplies its own fatal_error_handler, which attempts to print some
+error message through 167Bug (on the Serial Port 1/Console on the MVME712M).
+
+
+Host System
+-----------
+
+The port was initially developed on an RS-6000 running AIX 4.2. The following
+tools were used:
+
+ - GNU gcc 2.8.1 configured for a powerpc-ibm-aix4.2.0.0 host and
+ m68k-rtems target;
+ - GNU binutils 2.9.1 configured for a powerpc-ibm-aix4.2.0.0 host and
+ m68k-rtems target;
+ - Cygnus newlib 1.8.0 with RTEMS 4.0.0 patches.
+
+
+Known Problems
+--------------
+
+The cdtest will not run with interrupt-driven I/O. The reason is that the
+constructors for the static objects are called at boot time when the
+interrupts are still disabled. The output buffer fills up, but never empties,
+and the application goes into an infinite loop waiting for buffer space. This
+should have been documented in the rtems/c/src/tests/PROBLEMS file. The moral
+of this story is: do not do I/O from the constructors or destructors of static
+objects.
+
+The cpuuse and malloctest tests do not work properly, either with polled I/O
+or interrupt-driven I/O. They are known not to work with interrupt-driven I/O,
+but should work with polled I/O?
+
+Output stops prematurely in the termios test when the console is operating in
+interrupt-driven mode because the serial port is re-initialized before all
+characters in the last raw output buffer are sent. Adding calls to tcdrain()
+in the test task helps, but it does not solve the problem. What happens is
+that the CD2401 raises a transmit interrupt when the last character in the
+DMA buffer is written into the transmit FIFO, not when the last character
+has been transmitted. When tcdrain() returns, there might be up to 16
+characters in the output FIFO. The call to tcsetattr() causes the serial port
+to re-initialize, at which point the output FIFO is cleared. We could not find
+a way to detect whether characters are still in the FIFO and to wait for them
+to be transmitted.
+
+The first raw buffer to be transmitted after the console is re-initialized
+with tcsetattr() is garbled. At this time, it does not seem worth while to
+track this problem down.
+
+In the rtmonuse test, an unimplemented floating point instruction exception
+is raised at the end of the test when CPU_usage_Dump() is called. The faulting
+instruction is FCMP.X FP0,FP2 in cvt().
+
+In the stackchk test, an access fault exception is raised after the stack is
+blown. This is one case were overwritting the first or last 16 bytes of the
+stack does cause problems (but hey, an exception occurred, which is better
+than propagating the error).
+
+When using interrupt-driven I/O, psx08 produces all the expected output, but
+it does not return control to 167Bug. Is this test supposed to work with
+interrupt-driven console I/O?
+
+
+What's new
+----------
+
+
+Thanks
+------
+
+- to On-Line Applications Research Corporation (OAR) for developing
+RTEMS and making it available on a Technology Transfer basis;
+
+- to FSF and Cygnus Support for great free software;
+
+
+Test Configuration
+------------------
+
+Board: Motorola MVME167
+CPU: Motorola MC68040
+Clock Speed: 25 MHz
+RAM: 4 MBytes of 32-bit DRAM with parity
+Cache Configuration: Instruction cache on; data cache on, copyback mode.
+Times Reported in: microseconds
+Timer Source: VMEchip2 Tick Timer 1
+GCC Flags: -m68040 -g -O4 -fomit-frame-pointer
+Console: Operate in polled mode. Set CD2401_POLLED_IO to 1 in
+ rtems/c/src/lib/libbsp/m68k/mvme167/console/console.c.
+
+
+Test Results
+------------
+
+Single processor tests: All tests passed, except the following ones:
+ sp19 and rtmonuse failed with an unimplemented floating point instruction
+ exception (FCMP.X FP0,FP2). We do not have a floating point emulation
+ library at this time.
+ cpuuse and malloctest did not work.
+ The stackchk test got an access fault exception before the RTEMS stack
+ checker had had a chance to detect the corrupted stack.
+
+Multi-processort tests: not applicable -- No MPCI layer yet.
+
+Timing tests:
+
+ Context Switch
+
+ context switch: no floating point contexts 12
+ context switch: self 3
+ context switch: to another task 3
+ fp context switch: restore 1st FP task 14
+ fp context switch: save idle, restore initialized 5
+ fp context switch: save idle, restore idle 15
+ fp context switch: save initialized, restore initialized 5
+
+
+ Miscellaneous
+
+ _ISR_Disable 1
+ _ISR_Flash 0
+ _ISR_Enable 0
+
+ _Thread_Disable_dispatch 0
+ _Thread_Enable_dispatch 3
+ _Thread_Set_state 9
+ _Thread_Disptach (NO FP) 16
+ _Thread_Resume 6
+ _Thread_Unblock 4
+ _Thread_Ready 6
+ _Thread_Get 3
+ _Thread_Get: invalid id 0
+
+ _Semaphore_Get 2
+
+
+ Task Manager
+
+ rtems_task_create 56
+ rtems_task_ident 106
+ rtems_task_start 21
+ rtems_task_restart: calling task 24
+ rtems_task_restart: suspended task -- returns to caller 27
+ rtems_task_restart: blocked task -- returns to caller 36
+ rtems_task_restart: ready task -- returns to caller 27
+ rtems_task_restart: suspended task -- preempts caller 40
+ rtems_task_restart: blocked task -- preempts caller 51
+ rtems_task_restart: ready task -- preempts caller 52
+ rtems_task_delete: calling task 67
+ rtems_task_delete: suspended task 52
+ rtems_task_delete: blocked task 54
+ rtems_task_delete: ready task 54
+ rtems_task_suspend: calling task 23
+ rtems_task_suspend: returns to caller 12
+ rtems_task_resume: task readied -- returns to caller 13
+ rtems_task_resume: task readied -- preempts caller 22
+ rtems_task_set_priority: obtain current priority 8
+ rtems_task_set_priority: returns to caller 16
+ rtems_task_set_priority: preempts caller 34
+ rtems_task_mode: obtain current mode 4
+ rtems_task_mode: no reschedule 5
+ rtems_task_mode: reschedule -- returns to caller 12
+ rtems_task_mode: reschedule -- preempts caller 26
+ rtems_task_get_note 8
+ rtems_task_set_note 8
+ rtems_task_wake_after: yield -- returns to caller 4
+ rtems_task_wake_after: yields -- preempts caller 19
+ rtems_task_wake_when 36
+
+
+ Interrupt Manager
+
+ interrupt entry overhead: returns to nested interrupt 5
+ interrupt entry overhead: returns to interrupted task 9
+ interrupt entry overhead: returns to preempting task 7
+ interrupt exit overhead: returns to nested interrupt 1
+ interrupt exit overhead: returns to interrupted task 2
+ interrupt exit overhead: returns to preempting task 26
+
+
+ Clock Manager
+
+ rtems_clock_set 20
+ rtems_clock_get <1
+ rtems_clock_tick 8
+
+
+ Timer Manager
+
+ rtems_timer_create 8
+ rtems_timer_ident 104
+ rtems_timer_delete: inactive 12
+ rtems_timer_delete: active 13
+ rtems_timer_fire_after: inactive 17
+ rtems_timer_fire_after: active 18
+ rtems_timer_fire_when: inactive 23
+ rtems_timer_fire_when: active 23
+ rtems_timer_reset: inactive 16
+ rtems_timer_reset: active 17
+ rtems_timer_cancel: inactive 9
+ rtems_timer_cancel: active 10
+
+
+ Semaphore Manager
+
+ rtems_semaphore_create 22
+ rtems_semaphore_ident 119
+ rtems_semaphore_delete 24
+ rtems_semaphore_obtain: available 10
+ rtems_semaphore_obtain: not available -- NO_WAIT 10
+ rtems_semaphore_obtain: not available -- caller blocks 35
+ rtems_semaphore_release: no waiting tasks 11
+ rtems_semaphore_release: task readied -- returns to caller 17
+ rtems_semaphore_release: task readied -- preempts caller 27
+
+
+ Message Queue Manager
+
+ rtems_message_queue_create 85
+ rtems_message_queue_ident 103
+ rtems_message_queue_delete 32
+ rtems_message_queue_send: no waiting tasks 25
+ rtems_message_queue_send: task readied -- returns to caller 27
+ rtems_message_queue_send: task readied -- preempts caller 39
+ rtems_message_queue_urgent: no waiting tasks 26
+ rtems_message_queue_urgent: task readied -- returns to caller 28
+ rtems_message_queue_urgent: task readied -- preempts caller 39
+ rtems_message_queue_broadcast: no waiting tasks 13
+ rtems_message_queue_broadcast: task readied -- returns to caller 37
+ rtems_message_queue_broadcast: task readied -- preempts caller 45
+ rtems_message_queue_receive: available 21
+ rtems_message_queue_receive: not available -- NO_WAIT 11
+ rtems_message_queue_receive: not available -- caller blocks 37
+ rtems_message_queue_flush: no messages flushed 7
+ rtems_message_queue_flush: messages flushed 10
+
+
+ Event Manager
+
+ rtems_event_send: no task readied 7
+ rtems_event_send: task readied -- returns to caller 18
+ rtems_event_send: task readied -- preempts caller 29
+ rtems_event_receive: obtain current events <1
+ rtems_event_receive: available 10
+ rtems_event_receive: not available -- NO_WAIT 5
+ rtems_event_receive: not available -- caller blocks 28
+
+
+ Signal Manager
+
+ rtems_signal_catch 5
+ rtems_signal_send: returns to caller 15
+ rtems_signal_send: signal to self 24
+ exit ASR overhead: returns to calling task 20
+ exit ASR overhead: returns to preempting task 21
+
+
+ Partition Manager
+
+ rtems_partition_create 30
+ rtems_partition_ident 103
+ rtems_partition_delete 14
+ rtems_partition_get_buffer: available 14
+ rtems_partition_get_buffer: not available 9
+ rtems_partition_return_buffer 18
+
+
+ Region Manager
+
+ rtems_region_create 25
+ rtems_region_ident 105
+ rtems_region_delete 13
+ rtems_region_get_segment: available 13
+ rtems_region_get_segment: not available -- NO_WAIT 17
+ rtems_region_get_segment: not available -- caller blocks 49
+ rtems_region_return_segment: no waiting tasks 16
+ rtems_region_return_segment: task readied -- returns to caller 35
+ rtems_region_return_segment: task readied -- preempts caller 58
+
+
+ Dual-Ported Memory Manager
+
+ rtems_port_create 13
+ rtems_port_ident 103
+ rtems_port_delete 14
+ rtems_port_external_to_internal 5
+ rtems_port_internal_to_external 5
+
+
+ IO Manager
+
+ rtems_io_initialize <1
+ rtems_io_open <1
+ rtems_io_close <1
+ rtems_io_read <1
+ rtems_io_write <1
+ rtems_io_control <1
+
+
+ Rate Monotonic Manager
+
+ rtems_rate_monotonic_create 15
+ rtems_rate_monotonic_ident 103
+ rtems_rate_monotonic_cancel 16
+ rtems_rate_monotonic_delete: active 18
+ rtems_rate_monotonic_delete: inactive 20
+ rtems_rate_monotonic_period: initiate period -- returns to caller 23
+ rtems_rate_monotonic_period: conclude periods -- caller blocks 25
+ rtems_rate_monotonic_period: obtain status 13
+
+
+Network tests:
+ Network driver is not implemented.
+
+
+
diff --git a/c/src/lib/libbsp/m68k/mvme167/bsp_specs b/c/src/lib/libbsp/m68k/mvme167/bsp_specs
new file mode 100644
index 0000000000..61dac86b53
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/bsp_specs
@@ -0,0 +1,23 @@
+%rename cpp old_cpp
+%rename lib old_lib
+%rename endfile old_endfile
+%rename startfile old_startfile
+%rename link old_link
+
+*cpp:
+%(old_cpp) %{qrtems: -D__embedded__} -Asystem(embedded)
+
+*lib:
+%{!qrtems: %(old_lib)} %{qrtems: --start-group \
+%{!qrtems_debug: -lrtemsall} %{qrtems_debug: -lrtemsall_g} \
+-lc -lgcc --end-group \
+%{!qnolinkcmds: -T linkcmds%s}}
+
+*startfile:
+%{!qrtems: %(old_startfile)} %{qrtems: \
+%{!qrtems_debug: start.o%s} \
+%{qrtems_debug: start_g.o%s}}
+
+*link:
+%{!qrtems: %(old_link)} %{qrtems: -dc -dp -N -e start}
+
diff --git a/c/src/lib/libbsp/m68k/mvme167/clock/Makefile.in b/c/src/lib/libbsp/m68k/mvme167/clock/Makefile.in
new file mode 100644
index 0000000000..59df4f2702
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/clock/Makefile.in
@@ -0,0 +1,54 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+VPATH = @srcdir@
+RTEMS_ROOT = @top_srcdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+PGM=${ARCH}/clock.rel
+
+# C source names, if any, go here -- minus the .c
+C_PIECES=ckinit
+C_FILES=$(C_PIECES:%=%.c)
+C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
+
+H_FILES=
+
+SRCS=$(C_FILES) $(H_FILES)
+OBJS=$(C_O_FILES)
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+DEFINES +=
+CPPFLAGS +=
+CFLAGS +=
+
+LD_PATHS +=
+LD_LIBS +=
+LDFLAGS +=
+
+#
+# Add your list of files to delete here. The config files
+# already know how to delete some stuff, so you may want
+# to just run 'make clean' first to see what gets missed.
+# 'make clobber' already includes 'make clean'
+#
+
+CLEAN_ADDITIONS +=
+CLOBBER_ADDITIONS +=
+
+${PGM}: ${SRCS} ${OBJS}
+ $(make-rel)
+
+all: ${ARCH} $(SRCS) $(PGM)
+
+# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
+install: all
diff --git a/c/src/lib/libbsp/m68k/mvme167/clock/ckinit.c b/c/src/lib/libbsp/m68k/mvme167/clock/ckinit.c
new file mode 100644
index 0000000000..b7d6059b95
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/clock/ckinit.c
@@ -0,0 +1,281 @@
+/* ckinit.c
+ *
+ * Implementation of the Clock_control() and Clock_initialize() functions
+ * prototyped in rtems/c/src/lib/include/clockdrv.h.
+ *
+ * This port does not allow the application to select which timer on the
+ * MVME167 to use for the clock, nor does it allow the application to
+ * configure the clock. The clock uses the VMEchip2 Tick Timer #2. This
+ * timer is set up to raise a MC680x0 level-6 interrupt every 1 ms. The
+ * interrupt vector is 0x69.
+ *
+ * All page references are to the MVME166/MVME167/MVME187 Single Board
+ * Computer Programmer's Reference Guide (MVME187PG/D2) with the April
+ * 1993 supplements/addenda (MVME187PG/D2A1).
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * Modifications of respective RTEMS files:
+ * Copyright (c) 1998, National Research Council of Canada
+ *
+ * $Id$
+ */
+
+#include <stdlib.h>
+#include <bsp.h>
+#include <rtems/libio.h>
+
+#define MS_COUNT 1000 /* T2's countdown constant (1 ms) */
+#define CLOCK_INT_LEVEL 6 /* T2's interrupt level */
+#define CLOCK_VECTOR (VBR0 * 0x10 + 0x9) /* T2 is vector $X9 (p. 2-71)*/
+
+/*
+ * These are declared in rtems/c/src/lib/include/clockdrv.h
+ * In other BSPs, rtems_clock_major is set to the largest possible value
+ * (which is almost certainly greater than the number of I/O devices) to
+ * indicate that this device has not been initialized yet. The actual
+ * device number is supplied during initialization. We do not do that.
+ *
+ * Initialized data ends up the the .data section. This causes two problems:
+ * 1) the .data section is no longer ROMable because we need to write into
+ * it. 2) The initial value is correct only after a download. On subsequent
+ * program restarts, the value is not re-initialized but left to whatever it
+ * was when the previous run terminated or aborted. If we depend on some
+ * global variable value, we must initialize that value explicitly in code
+ * at boot time.
+ */
+rtems_device_major_number rtems_clock_major;
+rtems_device_minor_number rtems_clock_minor;
+
+/*
+ * Clock_driver_ticks is a monotonically increasing counter of the number of
+ * VMEchip2 timer #2 ticks since the driver was initialized.
+ */
+volatile rtems_unsigned32 Clock_driver_ticks;
+
+
+/*
+ * Clock_isrs is the number of clock ISRs until the next invocation of the
+ * RTEMS clock tick routine. This clock tick device driver gets an interrupt
+ * once a millisecond and counts down until the length of time between the
+ * user configured microseconds per tick has passed. This allows the clock
+ * device to "tick" faster than the kernel clock. Of course, the kernel clock
+ * cannot tick faster than the hardware clock. Therefore, the kernel clock
+ * ticks cannot occur more frequently than every 1 millisecond.
+ */
+rtems_unsigned32 Clock_isrs;
+
+
+/*
+ * Records the previous clock ISR (should be NULL)
+ */
+rtems_isr_entry Old_ticker;
+
+
+/*
+ * Called when the kernel exits.
+ */
+void clock_exit( void );
+
+
+/*
+ * VMEchip2_T2_isr
+ *
+ * C ISR Handler. Increment the number of internal ticks. If it is time for a
+ * kernel clock tick (if Clock_isrs == 1), call rtems_clock_tick() to signal
+ * the event and reset the Clock_isrs counter; else, just decrement it.
+ *
+ * Input parameters:
+ * vector number
+ *
+ * Output parameters: NONE
+ *
+ * Return values: NONE
+ */
+rtems_isr VMEchip2_T2_isr(
+ rtems_vector_number vector
+)
+{
+ char overflow; /* Content of overflow counter */
+ long i;
+ long ct; /* Number of T2 ticks per RTEMS ticks */
+
+ ct = BSP_Configuration.microseconds_per_tick / 1000;
+
+ /*
+ * May have missed interrupts, so should look at the overflow counter.
+ */
+ lcsr->intr_clear |= 0x02000000; /* Clear the interrupt */
+ overflow = (lcsr->board_ctl >> 12) & 0xF;
+ lcsr->board_ctl |= 0x400; /* Reset overflow counter */
+
+ /* Attempt to protect against one more period */
+ if ( overflow == 0 )
+ overflow = 16;
+
+ Clock_driver_ticks += overflow; /* One or more internal ticks */
+
+ if ( Clock_isrs <= overflow ) {
+ /* If its time for kernel clock ticks, signal the events to RTEMS */
+ for( i = overflow - Clock_isrs; i >= 0; i -= ct ) {
+ rtems_clock_tick();
+ }
+ /* Reset the counter */
+ Clock_isrs = (rtems_unsigned32)-i;
+ }
+ else
+ Clock_isrs -= overflow;
+}
+
+
+/*
+ * VMEchip2_T2_initialize
+ *
+ * Initialize the VMEchip2 Tick Timer #2.
+ *
+ * THE VMECHIP2 PRESCALER REGISTER IS ASSUMED TO BE SET!
+ * The prescaler is used by all VMEchip2 timers, including the VMEbus grant
+ * timeout counter, the DMAC time off timer, the DMAC timer on timer, and the
+ * VMEbus global timeout timer. The prescaler value is normally set by the
+ * boot ROM to provide a 1 MHz clock to the timers. For a 25 MHz MVME167, the
+ * prescaler value should be 0xE7 (page 2-63).
+ *
+ * Input parameters: NONE
+ *
+ * Output paremeters: NONE
+ *
+ * Return values: NONE
+ */
+void VMEchip2_T2_initialize( void )
+{
+ Clock_driver_ticks = 0;
+ Clock_isrs = BSP_Configuration.microseconds_per_tick / 1000;
+
+ if ( BSP_Configuration.ticks_per_timeslice ) {
+ lcsr->intr_ena &= 0xFDFFFFFF; /* Disable tick timer 2 interrupt */
+ lcsr->intr_clear = 0x02000000; /* Clear tick timer 2 interrupt */
+ lcsr->intr_level[0] = /* Set tick timer 2 interrupt level */
+ (lcsr->intr_level[0] & 0xFFFFFF0F ) | (CLOCK_INT_LEVEL << 4);
+ lcsr->timer_cmp_2 = MS_COUNT; /* Period in compare register */
+ lcsr->timer_cnt_2 = 0; /* Clear tick timer 2 counter */
+ Old_ticker = /* Install C ISR */
+ (rtems_isr_entry) set_vector( VMEchip2_T2_isr, CLOCK_VECTOR, 1 );
+ lcsr->board_ctl |= 0x700; /* Start tick timer 2, reset-on-compare, */
+ /* and clear tick timer 2 overflow counter */
+ lcsr->intr_ena |= 0x02000000; /* Enable tick timer 2 interrupt */
+ lcsr->vector_base |= 0x00800000;/* Unmask VMEchip2 interrupts */
+ atexit( clock_exit ); /* Turn off T2 interrupts when we exit */
+ }
+}
+
+
+/*
+ * clock_exit
+ *
+ * This routine stops the VMEchip2 T2 timer, disables its interrupt, and
+ * re-install the old interrupt vectors.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values: NONE
+ *
+ */
+void clock_exit( void )
+{
+ if ( BSP_Configuration.ticks_per_timeslice ) {
+ lcsr->board_ctl &= 0xFFFFFEFF; /* Stop tick timer 2 */
+ lcsr->intr_ena &= 0xFDFFFFFF; /* Disable tick timer 2 interrupt */
+ lcsr->intr_clear = 0x02000000; /* Clear tick timer 2 interrupt */
+
+ set_vector( Old_ticker, CLOCK_VECTOR, 1 );
+ }
+}
+
+
+/*
+ * Clock_initialize()
+ * prototyped in rtems/c/src/lib/include/clockdrv.h.
+ *
+ * Input parameters:
+ * major - console device major number
+ * minor - console device minor number
+ * ALWAYS 0 IN VERSION 3.6.0 OF RTEMS!
+ * Probably provided for symmetry with the other I/O calls.
+ * arg - pointer to optional device driver arguments
+ * ALWAYS NULL IN VERSION 3.6.0 OF RTEMS!
+ *
+ * Output paremeters: NONE
+ *
+ * Return values:
+ * rtems_device_driver status code
+ */
+rtems_device_driver Clock_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ VMEchip2_T2_initialize();
+
+ /*
+ * Make major/minor avail to others such as shared memory driver
+ */
+ rtems_clock_major = major;
+ rtems_clock_minor = minor;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * Clock_control().
+ * Prototyped in rtems/c/src/lib/include/clockdrv.h
+ *
+ * Input parameters:
+ * major - clock device major number
+ * minor - clock device minor number
+ * parg - pointer to optional device driver arguments
+ *
+ * Output parameters: NONE
+ *
+ * Return values:
+ * rtems_device_driver status code
+ */
+rtems_device_driver Clock_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp)
+{
+ rtems_unsigned32 isrlevel;
+ rtems_libio_ioctl_args_t *args = pargp;
+
+ if ( args == 0 )
+ goto done;
+
+ /*
+ * This is hokey, but until we get a defined interface
+ * to do this, it will just be this simple...
+ */
+ if ( args->command == rtems_build_name('I', 'S', 'R', ' ') )
+ {
+ VMEchip2_T2_isr( CLOCK_VECTOR );
+ }
+ else if ( args->command == rtems_build_name('N', 'E', 'W', ' ') )
+ {
+ rtems_interrupt_disable( isrlevel );
+ set_vector( args->buffer, CLOCK_VECTOR, 1 );
+ rtems_interrupt_enable( isrlevel );
+ }
+
+done:
+ return RTEMS_SUCCESSFUL;
+}
+
diff --git a/c/src/lib/libbsp/m68k/mvme167/console/Makefile.in b/c/src/lib/libbsp/m68k/mvme167/console/Makefile.in
new file mode 100644
index 0000000000..fd05ddfedd
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/console/Makefile.in
@@ -0,0 +1,54 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+VPATH = @srcdir@
+RTEMS_ROOT = @top_srcdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+PGM=${ARCH}/console.rel
+
+# C source names, if any, go here -- minus the .c
+C_PIECES=console
+C_FILES=$(C_PIECES:%=%.c)
+C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
+
+H_FILES=
+
+SRCS=$(C_FILES) $(H_FILES)
+OBJS=$(C_O_FILES)
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+DEFINES +=
+CPPFLAGS +=
+CFLAGS +=
+
+LD_PATHS +=
+LD_LIBS +=
+LDFLAGS +=
+
+#
+# Add your list of files to delete here. The config files
+# already know how to delete some stuff, so you may want
+# to just run 'make clean' first to see what gets missed.
+# 'make clobber' already includes 'make clean'
+#
+
+CLEAN_ADDITIONS +=
+CLOBBER_ADDITIONS +=
+
+${PGM}: ${SRCS} ${OBJS}
+ $(make-rel)
+
+all: ${ARCH} $(SRCS) $(PGM)
+
+# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
+install: all
diff --git a/c/src/lib/libbsp/m68k/mvme167/console/console.c b/c/src/lib/libbsp/m68k/mvme167/console/console.c
new file mode 100644
index 0000000000..b1377aef38
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/console/console.c
@@ -0,0 +1,1297 @@
+/*
+ * console.c
+ *
+ * This file contains the MVME167 termios console package. Only asynchronous
+ * I/O is supported. Normal I/O uses DMA for output, interrupts for input.
+ * Very limited support is provided for polled I/O. Polled I/O is intended
+ * only for running the RTEMS test suites, and uses the 167Bug console only.
+ *
+ * /dev/tty0 is channel 0, Serial Port 1/Console on the MVME712M.
+ * /dev/tty1 is channel 1, Serial Port 2/TTY01 on the MVME712M.
+ * /dev/tty2 is channel 2, Serial Port 3 on the MVME712M.
+ * /dev/tty3 is channel 3, Serial Port 4 on the MVME712M.
+ *
+ * /dev/console is fixed to be /dev/tty01, Serial Port 2. 167Bug is given
+ * Serial Port 1/Console. Do not open /dev/tty00.
+ *
+ * Modern I/O chips often contain a number of I/O devices that can operate
+ * almost independently of each other. Typically, in RTEMS, all devices in
+ * an I/O chip are handled by a single device driver, but that need not be
+ * always the case. Each device driver must supply six entry points in the
+ * Device Driver Table: a device initialization function, as well as an open,
+ * close, read, write and a control function. RTEMS assigns a device major
+ * number to each device driver. This major device number is the index of the
+ * device driver entries in the Device Driver Table, and it used to identify
+ * a particular device driver. To distinguish multiple I/O sub-devices within
+ * an I/O chip, RTEMS supports device minor numbers. When a I/O device is
+ * initialized, the major number is supplied to the initialization function.
+ * That function must register each sub-device with a separate name and minor
+ * number (as well as the supplied major number). When an application opens a
+ * device by name, the corresponding major and minor numbers are returned to
+ * the caller to be used in subsequent I/O operations (although these details
+ * are typically hidden within the library functions).
+ *
+ * Such a scheme recognizes that the initialization of the individual
+ * sub-devices is generally not completely independent. For example, the
+ * four serial ports of the CD2401 can be configured almost independently
+ * from each other. One port could be configured to operate in asynchronous
+ * mode with interrupt-driven I/O, while another port could be configured to
+ * operate in HDLC mode with DMA I/O. However, a device reset command will
+ * reset all four channels, and the width of DMA transfers and the number of
+ * retries following bus errors selected applies to all four channels.
+ * Consequently, when initializing one channel, one must be careful not to
+ * destroy the configuration of other channels that are already configured.
+ *
+ * One problem with the RTEMS I/O initialization model is that no information
+ * other than a device major number is passed to the initialization function.
+ * Consequently, the sub-devices must be initialized with some pre-determined
+ * configuration. To change the configuration of a sub-device, it is
+ * necessary to either rewrite the initialization function, or to make a
+ * series of rtems_io_control() calls after initialization. The first
+ * approach is not very elegant. The second approach is acceptable if an
+ * application is simply changing baud rates, parity or other such
+ * asynchronous parameters (as supplied by the termios package). But what if
+ * an application requires one channel to run in HDLC or Bisync mode and
+ * another in async mode? With a single driver per I/O chip approach, the
+ * device driver must support multiple protocols. This is feasible, but it
+ * often means that an application that only does asynchronous I/O now links
+ * in code for other unused protocols, thus wasting precious ROM space.
+ * Worse, it requires that the sub-devices be initialized in some
+ * configuration, and that configuration then changed through a series of
+ * device driver control calls. There is no standard API in RTEMS to switch
+ * a serial line to some synchronous protocol.
+ *
+ * A better approach is to treat each channel as a separate device, each with
+ * its own device device driver. The application then supplies its own device
+ * driver table with only the required protocols (drivers) on each line. The
+ * problem with this approach is that the device drivers are not really
+ * independent, given that the I/O sub-devices within a common chip are not
+ * independent themselves. Consequently, the related device drivers must
+ * share some information. In RTEMS, there is no standard location in which
+ * to share information.
+ *
+ * This driver handles all four channels, i.e. it distinguishes the
+ * sub-devices using minor device numbers. Only asynchronous I/O is
+ * supported. The console is currently fixed to be channel 1 on the CD2401,
+ * which corresponds to the TTY01 port (Serial Port 2) on the MVME712M
+ * Transition Module.
+ *
+ * The CD2401 does either interrupt-driven or DMA I/O; it does not support
+ * polling. In interrupt-driven or DMA I/O modes, interrupts from the CD2401
+ * are routed to the MC68040, and the processor generates an interrupt
+ * acknowledge cycle directly to the CD2401 to obtain an interrupt vector.
+ * The PCCchip2 supports a pseudo-polling mode in which interrupts from the
+ * CD2401 are not routed to the MC68040, but can be detected by the processor
+ * by reading the appropriate CD2401 registers. In this mode, interrupt
+ * acknowledge cycles must be generated to the CD2401 by reading the
+ * appropriate PCCchip2 registers.
+ *
+ * Interrupts from the four channels cannot be routed independently; either
+ * all channels are used in the pseudo-polling mode, or all channels are used
+ * in interrupt-driven/DMA mode. There is no advantage in using the speudo-
+ * polling mode. Consenquently, this driver performs DMA input and output.
+ * Output is performed directly from the termios raw output buffer, while
+ * input is accumulated into a separate buffer.
+ *
+ * THIS MODULE IS NOT RE-ENTRANT! Simultaneous access to a device from
+ * multiple tasks is likely to cause significant problems! Concurrency
+ * control is implemented in the termios package.
+*
+ * THE INTERRUPT LEVEL IS SET TO 1 FOR ALL CHANNELS.
+ * If the CD2401 is to be used for high speed synchronous serial I/O, the
+ * interrupt priority might need to be increased.
+ *
+ * ALL INTERRUPT HANDLERS ARE SHARED.
+ * When adding extra device drivers, either rewrite the interrupt handlers
+ * to demultiplex the interrupts, or install separate vectors. Common vectors
+ * are currently used to catch spurious interrupts. We could already have
+ * installed separate vectors for each channel and used the spurious
+ * interrupt handler defined in some other BSPs, but handling spurious
+ * interrupts from the CD2401 in this device driver allows us to record more
+ * information on the source of the interrupts. Furthermore, we have observed
+ * the occasional spurious interrupt from channel 0. We definitely do not
+ * to call a debugger for those.
+ *
+ * All page references are to the MVME166/MVME167/MVME187 Single Board
+ * Computer Programmer's Reference Guide (MVME187PG/D2) with the April
+ * 1993 supplements/addenda (MVME187PG/D2A1).
+ *
+ * Copyright (c) 1998, National Research Council of Canada
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ */
+
+#define M167_INIT
+
+#include <termios.h>
+#include <bsp.h> /* Must be before libio.h */
+#include <rtems/libio.h>
+
+#define CD2401_INT_LEVEL 1 /* Interrupt level for the CD2401 */
+#define CD2401_POLLED_IO 0 /* 0 for interrupt-driven, 1 for polled I/O */
+
+
+/* Channel info */
+/* static */ struct {
+ void *tty; /* Really a struct rtems_termios_tty * */
+ int len; /* Record nb of chars being TX'ed */
+ const char *buf; /* Record where DMA is coming from */
+ rtems_unsigned16 used_buf_A; /* Nb of times we used output DMA channel A */
+ rtems_unsigned16 used_buf_B; /* Nb of times we used output DMA channel B */
+ rtems_unsigned16 wait_buf_A; /* Nb of times we waited for output DMA channel A */
+ rtems_unsigned16 wait_buf_B; /* Nb of times we waited for output DMA channel B */
+ rtems_unsigned32 spur_cnt; /* Nb of spurious ints so far */
+ rtems_unsigned32 spur_dev; /* Indo on last spurious int */
+ rtems_unsigned32 buserr_addr; /* Faulting address */
+ rtems_unsigned32 buserr_type; /* Reason of bus error during DMA */
+} CD2401_Channel_Info[4];
+
+/*
+ * The number of channels already opened. If zero, enable the interrupts. The
+ * initial value must be 0. If initialized explicitly, the variable ends up
+ * in the .data section. Its value is not re-initialized on system restart.
+ * Furthermore, because the variable is changed, the .data section would not
+ * be ROMable. We thus leave the variable uninitialized, which causes it to
+ * be allocated in the .bss section, and rely on RTEMS to zero the .bss
+ * section on every startup.
+ */
+rtems_unsigned8 Init_count;
+
+
+/* Record previous handlers */
+rtems_isr_entry Prev_re_isr; /* Previous rx exception isr */
+rtems_isr_entry Prev_rx_isr; /* Previous rx isr */
+rtems_isr_entry Prev_tx_isr; /* Previous tx isr */
+rtems_isr_entry Prev_modem_isr; /* Previous modem/timer isr */
+
+/* Utility functions */
+void cd2401_chan_cmd( rtems_unsigned8 channel, rtems_unsigned8 cmd, rtems_unsigned8 wait );
+rtems_unsigned16 cd2401_bitrate_divisor( rtems_unsigned32 clkrate, rtems_unsigned32* bitrate );
+void cd2401_initialize( void );
+void cd2401_interrupts_initialize( rtems_boolean enable );
+
+/* ISRs */
+rtems_isr cd2401_modem_isr( rtems_vector_number vector );
+rtems_isr cd2401_re_isr( rtems_vector_number vector );
+rtems_isr cd2401_rx_isr( rtems_vector_number vector );
+rtems_isr cd2401_tx_isr( rtems_vector_number vector );
+
+/* Termios callbacks */
+int cd2401_firstOpen( int major, int minor, void *arg );
+int cd2401_lastClose( int major, int minor, void *arg );
+int cd2401_setAttributes( int minor, const struct termios *t );
+int cd2401_startRemoteTx( int minor );
+int cd2401_stopRemoteTx( int minor );
+int cd2401_write( int minor, const char *buf, int len );
+int _167Bug_pollRead( int minor );
+int _167Bug_pollWrite( int minor, const char *buf, int len );
+
+
+/*
+ * Utility functions.
+ */
+
+/*
+ * cd2401_chan_cmd
+ *
+ * Sends a CCR command to the specified channel. Waits for any unfinished
+ * previous command to complete, then sends the specified command. Optionally
+ * wait for the current command to finish before returning.
+ *
+ * Input parameters:
+ * channel - CD2401 channel number
+ * cmd - command byte
+ * wait - if non-zero, wait for specified command to complete before
+ * returning.
+ *
+ * Output parameters: NONE
+ *
+ * Return values: NONE
+ */
+void cd2401_chan_cmd(
+ rtems_unsigned8 channel,
+ rtems_unsigned8 cmd,
+ rtems_unsigned8 wait
+)
+{
+ if ( channel < 4 ) {
+ cd2401->car = channel; /* Select channel */
+
+ while ( cd2401->ccr != 0 ); /* Wait for completion of any previous command */
+ cd2401->ccr = cmd; /* Send command */
+ if ( wait )
+ while( cd2401->ccr != 0 );/* Wait for completion */
+ }
+ else {
+ /* This may not be the best error message */
+ rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER );
+ }
+}
+
+
+/*
+ * cd2401_bitrate_divisor
+ *
+ * Compute the divisor and clock source to use to obtain the desired bitrate.
+ *
+ * Input parameters:
+ * clkrate - system clock rate (CLK input frequency)
+ * bitrate - the desired bitrate
+ *
+ * Output parameters:
+ * bitrate - The actual bitrate achievable, to the nearest bps.
+ *
+ * Return values:
+ * Returns divisor in lower byte and clock source in upper byte for the
+ * specified bitrate.
+ */
+rtems_unsigned16 cd2401_bitrate_divisor(
+ rtems_unsigned32 clkrate,
+ rtems_unsigned32* bitrate
+)
+{
+ rtems_unsigned32 divisor;
+ rtems_unsigned16 clksource;
+
+ divisor = *bitrate << 3; /* temporary; multiply by 8 for CLK/8 */
+ divisor = (clkrate + (divisor>>1)) / divisor; /* divisor for clk0 (CLK/8) */
+
+ /* Use highest speed clock source for best precision - try from clk0 to clk4: */
+ for( clksource = 0; clksource < 0x0400 && divisor > 0x100; clksource += 0x0100 )
+ divisor >>= 2;
+ divisor--; /* adjustment, see specs */
+ if( divisor < 1 )
+ divisor = 1;
+ else if( divisor > 0xFF )
+ divisor = 0xFF;
+ *bitrate = clkrate / (1 << ((clksource >> 7)+3)) / (divisor+1);
+ return( clksource | divisor );
+}
+
+
+/*
+ * cd2401_initialize
+ *
+ * Initializes the CD2401 device. Individual channels on the chip are left in
+ * their default reset state, and should be subsequently configured.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values: NONE
+ */
+void cd2401_initialize( void )
+{
+ int i;
+
+ for ( i = 3; i >= 0; i-- ) {
+ /*
+ * Paranoia -- Should already be blank because array should be in bss
+ * section, which is explicitly zeroed at boot time.
+ */
+ CD2401_Channel_Info[i].tty = NULL;
+ CD2401_Channel_Info[i].len = 0;
+ CD2401_Channel_Info[i].buf = NULL;
+ CD2401_Channel_Info[i].used_buf_A = 0;
+ CD2401_Channel_Info[i].used_buf_B = 0;
+ CD2401_Channel_Info[i].wait_buf_A = 0;
+ CD2401_Channel_Info[i].wait_buf_B = 0;
+ CD2401_Channel_Info[i].spur_cnt = 0;
+ CD2401_Channel_Info[i].spur_dev = 0;
+ CD2401_Channel_Info[i].buserr_type = 0;
+ CD2401_Channel_Info[i].buserr_addr = 0;
+ }
+
+ /*
+ * Normally, do a device reset here. If we do it, we will most likely clober
+ * the port settings for 167Bug on channel 0. So we just shut up all the
+ * ports by disabling their interrupts.
+ */
+#if 0
+ cd2401->gfrcr = 0; /* So we can detect that device init is done */
+ cd2401_chan_cmd( 0x10, 0); /* Reset all */
+ while(cd2401->gfrcr == 0); /* Wait for reset all */
+#endif
+
+ /*
+ * The CL-CD2400/2401 manual (part no 542400-003) states on page 87 that
+ * the LICR "contains the number of the interrupting channel being served.
+ * The channel number is always that of the current acknowledged interrupt."
+ * THE USER MUST PROGRAM CHANNEL NUMBER IN LICR! It is not set automatically
+ * by the hardware, as suggested by the manual.
+ *
+ * The updated manual (part no 542400-007) has the story strait. The CD2401
+ * automatically initializes the LICR to contain the channel number in bits
+ * 2 and 3. However, these bits are not preserved when the user defined bits
+ * are written.
+ *
+ * The same vector number is used for all four channels. Different vector
+ * numbers could be programmed for each channel, thus avoiding the need to
+ * demultiplex the interrupts in the ISR.
+ */
+ for ( i = 0; i < 4; i++ ) {
+ cd2401->car = i; /* Select channel */
+ cd2401->livr = 0x5C; /* Motorola suggested value p. 3-15 */
+ cd2401->licr = i << 2; /* Don't rely on reset value */
+ cd2401->ier = 0; /* Disable all interrupts */
+ }
+
+ /*
+ * The content of the CD2401 xpilr registers must match the A7-A0 addresses
+ * generated by the PCCchip2 during interrupt acknowledge cycles in order
+ * for the CD2401 to recognize the IACK cycle and clear its interrupt
+ * request.
+ */
+ cd2401->mpilr = 0x01; /* Match pccchip2->modem_piack p. 3-27 */
+ cd2401->tpilr = 0x02; /* Match pccchip2->tx_piack p. 3-28 */
+ cd2401->rpilr = 0x03; /* Match pccchip2->rx_piack p. 3-29 */
+
+ /* Global CD2401 registers */
+ cd2401->dmr = 0; /* 16-bit DMA transfers when possible */
+ cd2401->bercnt = 0; /* Do not retry DMA upon bus errors */
+
+ /*
+ * Setup timer prescaler period, which clocks timers 1 and 2 (or rx timeout
+ * and tx delay). The prescaler is clocked by the system clock) / 2048. The
+ * register must be in the range 0x0A..0xFF, ie. a rescaler period range of
+ * about 1ms..26ms for a nominal system clock rate of 20MHz.
+ */
+ cd2401->tpr = 0x0A; /* Same value as 167Bug */
+}
+
+
+/*
+ * cd2401_interrupts_initialize
+ *
+ * This routine enables or disables the CD2401 interrupts to the MC68040.
+ * Interrupts cannot be enabled/disabled on a per-channel basis.
+ *
+ * Input parameters:
+ * enable - if true, enable the interrupts, else disable them.
+ *
+ * Output parameters: NONE
+ *
+ * Return values: NONE
+ *
+ * THE FIRST CD2401 CHANNEL OPENED SHOULD ENABLE INTERRUPTS.
+ * THE LAST CD2401 CHANNEL CLOSED SHOULD DISABLE INTERRUPTS.
+ */
+void cd2401_interrupts_initialize(
+ rtems_boolean enable
+)
+{
+ if ( enable ) {
+ /*
+ * Enable interrupts from the CD2401 in the PCCchip2.
+ * During DMA transfers, the MC68040 supplies dirty data during read cycles
+ * from the CD2401 and leaves the data dirty in its data cache if there is
+ * a cache hit. The MC68040 updates the data cache during write cycles from
+ * the CD2401 if there is a cache hit.
+ */
+ pccchip2->SCC_error = 0x01;
+ pccchip2->SCC_modem_int_ctl = 0x10 | CD2401_INT_LEVEL;
+ pccchip2->SCC_tx_int_ctl = 0x10 | CD2401_INT_LEVEL;
+ pccchip2->SCC_rx_int_ctl = 0x50 | CD2401_INT_LEVEL;
+
+ pccchip2->gen_control |= 0x02; /* Enable pccchip2 interrupts */
+ }
+ else {
+ /* Disable interrupts */
+ pccchip2->SCC_modem_int_ctl &= 0xEF;
+ pccchip2->SCC_tx_int_ctl &= 0xEF;
+ pccchip2->SCC_rx_int_ctl &= 0xEF;
+ }
+}
+
+
+/* ISRs */
+
+/*
+ * cd2401_modem_isr
+ *
+ * Modem/timer interrupt (group 1) from CD2401. These are not used, and not
+ * expected. Record as spurious and clear.
+ *
+ * Input parameters:
+ * vector - vector number
+ *
+ * Output parameters: NONE
+ *
+ * Return values: NONE
+ */
+rtems_isr cd2401_modem_isr(
+ rtems_vector_number vector
+)
+{
+ rtems_unsigned8 ch;
+
+ /* Get interrupting channel ID */
+ ch = cd2401->licr >> 2;
+
+ /* Record interrupt info for debugging */
+ CD2401_Channel_Info[ch].spur_dev =
+ (vector << 24) | (cd2401->stk << 16) | (cd2401->mir << 8) | cd2401->misr;
+ CD2401_Channel_Info[ch].spur_cnt++;
+
+ cd2401->meoir = 0; /* EOI */
+}
+
+
+/*
+ * cd2401_re_isr
+ *
+ * RX exception interrupt (group 3, receiver exception) from CD2401. These are
+ * not used, and not expected. Record as spurious and clear.
+ *
+ * FIX THIS ISR TO DETECT BREAK CONDITIONS AND RAISE SIGINT
+ *
+ * Input parameters:
+ * vector - vector number
+ *
+ * Output parameters: NONE
+ *
+ * Return values: NONE
+ */
+rtems_isr cd2401_re_isr(
+ rtems_vector_number vector
+)
+{
+ rtems_unsigned8 ch;
+
+ /* Get interrupting channel ID */
+ ch = cd2401->licr >> 2;
+
+ /* Record interrupt info for debugging */
+ CD2401_Channel_Info[ch].spur_dev =
+ (vector << 24) | (cd2401->stk << 16) | (cd2401->rir << 8) | cd2401->u5.b.risrl;
+ CD2401_Channel_Info[ch].spur_cnt++;
+
+ if ( cd2401->u5.b.risrl & 0x80 ) /* Timeout interrupt? */
+ cd2401->ier &= 0xDF; /* Disable rx timeout interrupt */
+ cd2401->reoir = 0x08; /* EOI; exception char not read */
+}
+
+
+/*
+ * cd2401_rx_isr
+ *
+ * RX interrupt (group 3, receiver data) from CD2401.
+ *
+ * Input parameters:
+ * vector - vector number
+ *
+ * Output parameters: NONE
+ *
+ * Return values: NONE
+ */
+rtems_isr cd2401_rx_isr(
+ rtems_vector_number vector
+)
+{
+ char c;
+ rtems_unsigned8 ch, nchars;
+
+ ch = cd2401->licr >> 2;
+
+ /* Has this channel been initialized? */
+ if (CD2401_Channel_Info[ch].tty) {
+ /* Yes, read chars, enqueue them, and issue EOI */
+ nchars = cd2401->rfoc; /* Number of chars to retrieve from rx FIFO */
+ while ( nchars-- > 0 ) {
+ c = (char)cd2401->dr; /* Next char in rx FIFO */
+ rtems_termios_enqueue_raw_characters (
+ CD2401_Channel_Info[ch].tty,
+ &c,
+ 1 );
+ }
+ cd2401->reoir = 0; /* EOI */
+ } else {
+ /* No, record as spurious interrupt */
+ CD2401_Channel_Info[ch].spur_dev =
+ (vector << 24) | (cd2401->stk << 16) | (cd2401->rir << 8) | cd2401->u5.b.risrl;
+ CD2401_Channel_Info[ch].spur_cnt++;
+ cd2401->reoir = 0x04; /* EOI - character not read */
+ }
+}
+
+
+/*
+ * cd2401_tx_isr
+ *
+ * TX interrupt (group 2) from CD2401.
+ *
+ * Input parameters:
+ * vector - vector number
+ *
+ * Output parameters: NONE
+ *
+ * Return values: NONE
+ */
+rtems_isr cd2401_tx_isr(
+ rtems_vector_number vector
+)
+{
+ rtems_unsigned8 ch, status, buserr;
+
+ status = cd2401->tisr;
+ ch = cd2401->licr >> 2;
+
+ /* Has this channel been initialized? */
+ if ( !CD2401_Channel_Info[ch].tty ) {
+ /* No, record as spurious interrupt */
+ CD2401_Channel_Info[ch].spur_dev =
+ (vector << 24) | (cd2401->stk << 16) | (cd2401->tir << 8) | cd2401->tisr;
+ CD2401_Channel_Info[ch].spur_cnt++;
+ cd2401->ier &= 0xFC; /* Shut up, whoever you are */
+ cd2401->teoir = 0x88; /* EOI - Terminate buffer and no transfer */
+ return;
+ }
+
+ if ( status & 0x80 ) {
+ /*
+ * Bus error occurred during DMA transfer. For now, just record.
+ * Get reason for DMA bus error and clear the report for the next occurrence
+ */
+ buserr = pccchip2->SCC_error;
+ pccchip2->SCC_error = 0x01;
+ CD2401_Channel_Info[ch].buserr_type =
+ (vector << 24) | (buserr << 16) | (cd2401->tir << 8) | cd2401->tisr;
+ CD2401_Channel_Info[ch].buserr_addr =
+ (((rtems_unsigned32)cd2401->tcbadru) << 16) | cd2401->tcbadrl;
+
+ cd2401->teoir = 0x80; /* EOI - terminate bad buffer */
+ return;
+ }
+
+ if ( status & 0x20 ) {
+ /* DMA done */
+ cd2401->ier &= 0xFC; /* Shut up the interrupts */
+
+ /* This call can result in a call to cd2401_write() */
+ rtems_termios_dequeue_characters (
+ CD2401_Channel_Info[ch].tty,
+ CD2401_Channel_Info[ch].len );
+ cd2401->teoir = 0x08; /* EOI - no data transfered */
+ }
+ else {
+ /* Why did we get a Tx interrupt? */
+ CD2401_Channel_Info[ch].spur_dev =
+ (vector << 24) | (cd2401->stk << 16) | (cd2401->tir << 8) | cd2401->tisr;
+ CD2401_Channel_Info[ch].spur_cnt++;
+ cd2401->teoir = 0x08; /* EOI - no data transfered */
+ }
+}
+
+
+/*
+ * termios callbacks
+ */
+
+/*
+ * cd2401_firstOpen
+ *
+ * This is the first time that this minor device (channel) is opened.
+ * Complete the asynchronous initialization.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - channel number
+ * arg - pointer to a struct rtems_libio_open_close_args_t
+ *
+ * Output parameters: NONE
+ *
+ * Return value: IGNORED
+ */
+int cd2401_firstOpen(
+ int major,
+ int minor,
+ void *arg
+)
+{
+ rtems_libio_open_close_args_t *args = arg;
+ rtems_libio_ioctl_args_t newarg;
+ struct termios termios;
+ rtems_status_code sc;
+
+ /*
+ * Set up the line with the specified parameters. The difficulty is that
+ * the line parameters are stored in the struct termios field of a
+ * struct rtems_termios_tty that is not defined in a public header file.
+ * Therefore, we do not have direct access to the termios passed in with
+ * arg. So we make a rtems_termios_ioctl() call to get a pointer to the
+ * termios structure.
+ *
+ * THIS KLUDGE MAY BREAK IN THE FUTURE!
+ *
+ * We could have made a tcgetattr() call if we had our fd.
+ */
+ newarg.iop = args->iop;
+ newarg.command = RTEMS_IO_GET_ATTRIBUTES;
+ newarg.buffer = &termios;
+ sc = rtems_termios_ioctl (&newarg);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+
+ /*
+ * Turn off hardware flow control. It is a pain with 3-wire cables.
+ * The rtems_termios_ioctl() call below results in a call to
+ * cd2401_setAttributes to initialize the line. The caller will "wait"
+ * on the ttyMutex that it already owns; this is safe in RTEMS.
+ */
+ termios.c_cflag |= CLOCAL; /* Ignore modem status lines */
+ newarg.command = RTEMS_IO_SET_ATTRIBUTES;
+ sc = rtems_termios_ioctl (&newarg);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+
+ /* Mark that the channel as initialized */
+ CD2401_Channel_Info[minor].tty = args->iop->data1;
+
+ /* If the first of the four channels to open, set up the interrupts */
+ if ( !Init_count++ ) {
+ /* Install the interrupt handlers */
+ Prev_re_isr = (rtems_isr_entry) set_vector( cd2401_re_isr, 0x5C, 1 );
+ Prev_modem_isr = (rtems_isr_entry) set_vector( cd2401_modem_isr, 0x5D, 1 );
+ Prev_tx_isr = (rtems_isr_entry) set_vector( cd2401_tx_isr, 0x5E, 1 );
+ Prev_rx_isr = (rtems_isr_entry) set_vector( cd2401_rx_isr, 0x5F, 1 );
+
+ cd2401_interrupts_initialize( TRUE );
+ }
+
+ /* Return something */
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * cd2401_lastClose
+ *
+ * There are no more opened file descriptors to this device. Close it down.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - channel number
+ * arg - pointer to a struct rtems_libio_open_close_args_t
+ */
+int cd2401_lastClose(
+ int major,
+ int minor,
+ void *arg
+)
+{
+ /* Mark that the channel is no longer is use */
+ CD2401_Channel_Info[minor].tty = NULL;
+
+ /* If the last of the four channels to close, disable the interrupts */
+ if ( !--Init_count ) {
+ cd2401_interrupts_initialize( FALSE );
+
+ /* De-install the interrupt handlers */
+ set_vector( Prev_re_isr, 0x5C, 1 );
+ set_vector( Prev_modem_isr, 0x5D, 1 );
+ set_vector( Prev_tx_isr, 0x5E, 1 );
+ set_vector( Prev_rx_isr, 0x5F, 1 );
+ }
+
+ /* return something */
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * cd2401_setAttributes
+ *
+ * Set up the selected channel of the CD2401 chip for doing asynchronous
+ * I/O with DMA.
+ *
+ * The chip must already have been initialized by cd2401_initialize().
+ *
+ * This code was written for clarity. The code space it occupies could be
+ * reduced. The code could also be compiled with aggressive optimization
+ * turned on.
+ *
+ * Input parameters:
+ * minor - the selected channel
+ * t - the termios parameters
+ *
+ * Output parameters: NONE
+ *
+ * Return value: IGNORED
+ */
+int cd2401_setAttributes(
+ int minor,
+ const struct termios *t
+)
+{
+ rtems_unsigned8 csize, cstopb, parodd, parenb, ignpar, inpck;
+ rtems_unsigned8 hw_flow_ctl, sw_flow_ctl, extra_flow_ctl;
+ rtems_unsigned8 icrnl, igncr, inlcr, brkint, ignbrk, parmrk, istrip;
+ rtems_unsigned16 tx_period, rx_period;
+ rtems_unsigned32 out_baud, in_baud;
+
+ /* Set up the line parameters */
+
+ /* Output baud rate */
+ switch ( cfgetospeed (t) ) {
+ default: out_baud = 9600; break;
+ case B50: out_baud = 50; break;
+ case B75: out_baud = 75; break;
+ case B110: out_baud = 110; break;
+ case B134: out_baud = 134; break;
+ case B150: out_baud = 150; break;
+ case B200: out_baud = 200; break;
+ case B300: out_baud = 300; break;
+ case B600: out_baud = 600; break;
+ case B1200: out_baud = 1200; break;
+ case B1800: out_baud = 1800; break;
+ case B2400: out_baud = 2400; break;
+ case B4800: out_baud = 4800; break;
+ case B9600: out_baud = 9600; break;
+ case B19200: out_baud = 19200; break;
+ case B38400: out_baud = 38400; break;
+ case B57600: out_baud = 57600; break;
+ case B115200: out_baud = 115200; break;
+ case B230400: out_baud = 230400; break;
+ case B460800: out_baud = 460800; break;
+ }
+
+ /* Input baud rate */
+ switch ( cfgetispeed (t) ) {
+ default: in_baud = out_baud; break;
+ case B50: in_baud = 50; break;
+ case B75: in_baud = 75; break;
+ case B110: in_baud = 110; break;
+ case B134: in_baud = 134; break;
+ case B150: in_baud = 150; break;
+ case B200: in_baud = 200; break;
+ case B300: in_baud = 300; break;
+ case B600: in_baud = 600; break;
+ case B1200: in_baud = 1200; break;
+ case B1800: in_baud = 1800; break;
+ case B2400: in_baud = 2400; break;
+ case B4800: in_baud = 4800; break;
+ case B9600: in_baud = 9600; break;
+ case B19200: in_baud = 19200; break;
+ case B38400: in_baud = 38400; break;
+ case B57600: in_baud = 57600; break;
+ case B115200: in_baud = 115200; break;
+ case B230400: in_baud = 230400; break;
+ case B460800: in_baud = 460800; break;
+ }
+
+ /* Number of bits per char */
+ switch ( t->c_cflag & CSIZE ) {
+ case CS5: csize = 0x04; break;
+ case CS6: csize = 0x05; break;
+ case CS7: csize = 0x06; break;
+ case CS8: csize = 0x07; break;
+ }
+
+ /* Parity */
+ if ( t->c_cflag & PARODD )
+ parodd = 0x80; /* Odd parity */
+ else
+ parodd = 0;
+
+ if ( t->c_cflag & PARENB )
+ parenb = 0x40; /* Parity enabled on Tx and Rx */
+ else
+ parenb = 0x00; /* No parity on Tx and Rx */
+
+ /* CD2401 IGNPAR and INPCK bits are inverted wrt POSIX standard? */
+ if ( t->c_iflag & INPCK )
+ ignpar = 0; /* Check parity on input */
+ else
+ ignpar = 0x10; /* Do not check parity on input */
+ if ( t->c_iflag & IGNPAR ) {
+ inpck = 0x03; /* Discard error character */
+ parmrk = 0;
+ } else {
+ if ( t->c_iflag & PARMRK ) {
+ inpck = 0x01; /* Translate to 0xFF 0x00 <char> */
+ parmrk = 0x04;
+ } else {
+ inpck = 0x01; /* Translate to 0x00 */
+ parmrk = 0;
+ }
+ }
+
+ /* Stop bits */
+ if ( t->c_cflag & CSTOPB )
+ cstopb = 0x04; /* Two stop bits */
+ else
+ cstopb = 0x02; /* One stop bit */
+
+ /* Modem flow control */
+ if ( t->c_cflag & CLOCAL )
+ hw_flow_ctl = 0x04; /* Always assert RTS before Tx */
+ else
+ hw_flow_ctl = 0x07; /* Always assert RTS before Tx,
+ wait for CTS and DSR */
+
+ /* XON/XOFF Tx flow control */
+ if ( t->c_iflag & IXON ) {
+ sw_flow_ctl = 0x40; /* Tx in-band flow ctl enabled, wait for XON */
+ extra_flow_ctl = 0x30; /* Eat XON/XOFF, XON/XOFF in SCHR1, SCHR2 */
+ }
+ else {
+ sw_flow_ctl = 0; /* Tx in-band flow ctl disabled */
+ extra_flow_ctl = 0; /* Pass on XON/XOFF */
+ }
+
+ /* CL/LF translation */
+ if ( t->c_iflag & ICRNL )
+ icrnl = 0x40; /* Map CR to NL on input */
+ else
+ icrnl = 0; /* Pass on CR */
+ if ( t->c_iflag & INLCR )
+ inlcr = 0x20; /* Map NL to CR on input */
+ else
+ inlcr = 0; /* Pass on NL */
+ if ( t->c_iflag & IGNCR )
+ igncr = 0x80; /* CR discarded on input */
+ else
+ igncr = 0;
+
+ /* Break handling */
+ if ( t->c_iflag & IGNBRK ) {
+ ignbrk = 0x10; /* Ignore break on input */
+ brkint = 0x08;
+ } else {
+ if ( t->c_iflag & BRKINT ) {
+ ignbrk = 0; /* Generate SIGINT (interrupt ) */
+ brkint = 0;
+ } else {
+ ignbrk = 0; /* Convert to 0x00 */
+ brkint = 0x08;
+ }
+ }
+
+ /* Stripping */
+ if ( t->c_iflag & ISTRIP )
+ istrip = 0x80; /* Strip to 7 bits */
+ else
+ istrip = 0; /* Leave as 8 bits */
+
+
+ /* Clear channel and disable rx and tx */
+ cd2401_chan_cmd (minor, 0x40, 1);
+
+ /* Write to the ports */
+ cd2401->car = minor; /* Select channel */
+ cd2401->cmr = 0x42; /* Interrupt Rx, DMA Tx, async mode */
+ cd2401->cor1 = parodd | parenb | ignpar | csize;
+ cd2401->cor2 = sw_flow_ctl | hw_flow_ctl;
+ cd2401->cor3 = extra_flow_ctl | cstopb;
+ cd2401->cor4 = 0x0A; /* No DSR/DCD/CTS detect; FIFO threshold of 10 */
+ cd2401->cor5 = 0x0A; /* No DSR/DCD/CTS detect; DTR threshold of 10 */
+ cd2401->cor6 = igncr | icrnl | inlcr | ignbrk | brkint | parmrk | inpck;
+ cd2401->cor7 = istrip; /* No LNext; ignore XON/XOFF if frame error; no tx translations */
+ cd2401->u1.async.schr1 =
+ t->c_cc[VSTART]; /* Special char 1: XON character */
+ cd2401->u1.async.schr2 =
+ t->c_cc[VSTOP]; /* special char 2: XOFF character */
+ /* Special chars 3 and 4, char range, LNext, RFAR[1..4] and CRC are unused, left as is. */
+
+ /* Set baudrates for receiver and transmitter */
+ rx_period = cd2401_bitrate_divisor( 20000000Ul, &in_baud );
+ cd2401->rbpr = (unsigned char)rx_period;
+ cd2401->rcor = (unsigned char)(rx_period >> 8); /* no DPLL */
+ tx_period = cd2401_bitrate_divisor( 20000000Ul, &out_baud );
+ cd2401->tbpr = (unsigned char)tx_period;
+ cd2401->tcor = (tx_period >> 3) & 0xE0; /* no x1 ext clk, no loopback */
+
+ /* NEED TO LOOK AT THIS LINE! */
+ /* Timeout for 4 chars at 9600, 8 bits per char, 1 stop bit */
+ cd2401->u2.w.rtpr = 0x04;
+
+ /* And finally: */
+ if ( t->c_cflag & CREAD ) {
+ /* Re-initialize channel, enable rx and tx */
+ cd2401_chan_cmd (minor, 0x2A, 1);
+ /* Enable rx data ints */
+ cd2401->ier = 0x08;
+ } else {
+ /* Re-initialize channel, enable tx, disable rx */
+ cd2401_chan_cmd (minor, 0x29, 1);
+ }
+
+ /* Return something */
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * cd2401_startRemoreTx
+ *
+ * Defined as a callback, but it would appear that it is never called. The
+ * POSIX standard states that when the tcflow() function is called with the
+ * TCION action, the system wall transmit a START character. Presumably,
+ * tcflow() is called internally when IXOFF is set in the termios c_iflag
+ * field when the input buffer can accomodate enough characters. It should
+ * probably be called from fillBufferQueue(). Clearly, the function is also
+ * explicitly callable by user code. The action is clearly to send the START
+ * character, regardless of whether START/STOP flow control is in effect.
+ *
+ * Input parameters:
+ * minor - selected channel
+ *
+ * Output parameters: NONE
+ *
+ * Return value: IGNORED
+ *
+ * PROPER START CHARACTER MUST BE PROGRAMMED IN SCHR1.
+ */
+int cd2401_startRemoteTx(
+ int minor
+)
+{
+ cd2401->car = minor; /* Select channel */
+ cd2401->stcr = 0x01; /* Send SCHR1 ahead of chars in FIFO */
+
+ /* Return something */
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * cd2401_stopRemoreTx
+ *
+ * Defined as a callback, but it would appear that it is never called. The
+ * POSIX standard states that when the tcflow() function is called with the
+ * TCIOFF function, the system wall transmit a STOP character. Presumably,
+ * tcflow() is called internally when IXOFF is set in the termios c_iflag
+ * field as the input buffer is about to overflow. It should probably be
+ * called from rtems_termios_enqueue_raw_characters(). Clearly, the function
+ * is also explicitly callable by user code. The action is clearly to send
+ * the STOP character, regardless of whether START/STOP flow control is in
+ * effect.
+ *
+ * Input parameters:
+ * minor - selected channel
+ *
+ * Output parameters: NONE
+ *
+ * Return value: IGNORED
+ *
+ * PROPER STOP CHARACTER MUST BE PROGRAMMED IN SCHR2.
+ */
+int cd2401_stopRemoteTx(
+ int minor
+)
+{
+ cd2401->car = minor; /* Select channel */
+ cd2401->stcr = 0x02; /* Send SCHR2 ahead of chars in FIFO */
+
+ /* Return something */
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * cd2401_write
+ *
+ * Initiate DMA output. Termios guarantees that the buffer does not wrap
+ * around, so we can do DMA strait from the supplied buffer.
+ *
+ * Input parameters:
+ * minor - selected channel
+ * buf - output buffer
+ * len - number of chars to output
+ *
+ * Output parameters: NONE
+ *
+ * Return value: IGNORED
+ *
+ * MUST BE EXECUTED WITH THE CD2401 INTERRUPTS DISABLED!
+ * The processor is placed at interrupt level CD2401_INT_LEVEL explicitly in
+ * console_write(). The processor is necessarily at interrupt level 1 in
+ * cd2401_tx_isr().
+ */
+int cd2401_write(
+ int minor,
+ const char *buf,
+ int len
+)
+{
+ cd2401->car = minor; /* Select channel */
+
+ if ( (cd2401->dmabsts & 0x08) == 0 ) {
+ /* Next buffer is A. Wait for it to be ours. */
+ if ( cd2401->atbsts & 0x01 ) {
+ CD2401_Channel_Info[minor].wait_buf_A++;
+ while ( cd2401->atbsts & 0x01 );
+ }
+ CD2401_Channel_Info[minor].used_buf_A++;
+ CD2401_Channel_Info[minor].len = len;
+ CD2401_Channel_Info[minor].buf = buf;
+ cd2401->atbadru = (rtems_unsigned16)( ( (rtems_unsigned32) buf ) >> 16 );
+ cd2401->atbadrl = (rtems_unsigned16)( (rtems_unsigned32) buf );
+ cd2401->atbcnt = len;
+ cd2401->atbsts = 0x03; /* CD2401 owns buffer, int when empty */
+ }
+ else {
+ /* Next buffer is B. Wait for it to be ours. */
+ if ( cd2401->btbsts & 0x01 ) {
+ CD2401_Channel_Info[minor].wait_buf_B++;
+ while ( cd2401->btbsts & 0x01 );
+ }
+ CD2401_Channel_Info[minor].used_buf_B++;
+ CD2401_Channel_Info[minor].len = len;
+ CD2401_Channel_Info[minor].buf = buf;
+ cd2401->btbadru = (rtems_unsigned16)( ( (rtems_unsigned32) buf ) >> 16 );
+ cd2401->btbadrl = (rtems_unsigned16)( (rtems_unsigned32) buf );
+ cd2401->btbcnt = len;
+ cd2401->btbsts = 0x03; /* CD2401 owns buffer, int when empty */
+ }
+ /* Should TxD interrupts be enabled before I set up the DMA transfer? */
+ cd2401->ier |= 0x01; /* enable TxD ints */
+
+ /* Return something */
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * _167Bug_pollRead
+ *
+ * Read a character from the 167Bug console, and return it. Return -1
+ * if there is no character in the input FIFO.
+ *
+ * Input parameters:
+ * minor - selected channel
+ *
+ * Output parameters: NONE
+ *
+ * Return value: char returned as positive signed int
+ * -1 if no character is present in the input FIFO.
+ *
+ * CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O!
+ * This function is invoked when the device driver is compiled with
+ * CD2401_POLLED_IO set to 1 above. All I/O is then done through 167Bug.
+ */
+int _167Bug_pollRead(
+ int minor
+)
+{
+ int char_not_available;
+ unsigned char c;
+
+ /* Check for a char in the input FIFO */
+ asm volatile( "trap #15 /* Trap to 167Bug (.INSTAT) */
+ .short 0x01
+ move %%cc, %0 /* Get condition codes */
+ andil #4, %0"
+ : "=d" (char_not_available) :: "%%cc" );
+
+ if (char_not_available)
+ return -1;
+
+ /* Read the char and return it */
+ asm volatile( "subq.l #2,%%a7 /* Space for result */
+ trap #15 /* Trap to 167 Bug (.INCHR) */
+ .short 0x00
+ moveb (%%a7)+, %0"
+ : "=d" (c) );
+
+ return (int)c;
+}
+
+
+/*
+ * _167Bug_pollWrite
+ *
+ * Output buffer through 167Bug. Returns only once every character has been
+ * sent (polled output).
+ *
+ * Input parameters:
+ * minor - selected channel
+ * buf - output buffer
+ * len - number of chars to output
+ *
+ * Output parameters: NONE
+ *
+ * Return value: IGNORED
+ *
+ * CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O!
+ * This function is invoked when the device driver is compiled with
+ * CD2401_POLLED_IO set to 1 above. All I/O is then done through 167Bug.
+ */
+int _167Bug_pollWrite(
+ int minor,
+ const char *buf,
+ int len
+)
+{
+ const char *endbuf = buf + len;
+
+ asm volatile( "pea (%0)
+ pea (%1)
+ trap #15 /* trap to 167Bug (.OUTSTR) */
+ .short 0x21"
+ :: "a" (endbuf), "a" (buf) );
+
+ /* Return something */
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ ***************
+ * BOILERPLATE *
+ ***************
+ *
+ * All these functions are prototyped in rtems/c/src/lib/include/console.h,
+ * except console_reserve_resources(), which is prototyped in
+ * rtems/c/src/lib/libbsp/m68k/mvme167/include/bsp.h
+ */
+
+/*
+ * Reserve resources consumed by this driver. Allocate enough space in the
+ * object table to hold semaphores for 4 minor devices.
+ */
+void console_reserve_resources(
+ rtems_configuration_table *configuration
+)
+{
+ rtems_termios_reserve_resources (configuration, 4);
+}
+
+/*
+ * Initialize and register the device
+ */
+rtems_device_driver console_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ rtems_status_code status;
+
+ /*
+ * Set up TERMIOS
+ */
+ rtems_termios_initialize ();
+
+ /*
+ * Do device-specific initialization
+ */
+ cd2401_initialize ();
+
+ /*
+ * Register the devices
+ */
+ status = rtems_io_register_name ("/dev/tty0", major, 0);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (status);
+
+ status = rtems_io_register_name ("/dev/tty1", major, 1);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (status);
+
+ status = rtems_io_register_name ("/dev/console", major, 1);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (status);
+
+ status = rtems_io_register_name ("/dev/tty2", major, 2);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (status);
+
+ status = rtems_io_register_name ("/dev/tty3", major, 3);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (status);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Open the device
+ */
+rtems_device_driver console_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+#if CD2401_POLLED_IO
+
+ /* I/O is limited to 167Bug console. minor is ignored! */
+ static const rtems_termios_callbacks callbacks = {
+ NULL, /* firstOpen */
+ NULL, /* lastClose */
+ _167Bug_pollRead, /* pollRead */
+ _167Bug_pollWrite, /* write */
+ NULL, /* setAttributes */
+ NULL, /* stopRemoteTx */
+ NULL, /* startRemoteTx */
+ 0 /* outputUsesInterrupts */
+ };
+
+#else
+
+ static const rtems_termios_callbacks callbacks = {
+ cd2401_firstOpen, /* firstOpen */
+ cd2401_lastClose, /* lastClose */
+ NULL, /* pollRead */
+ cd2401_write, /* write */
+ cd2401_setAttributes, /* setAttributes */
+ cd2401_stopRemoteTx, /* stopRemoteTx */
+ cd2401_startRemoteTx, /* startRemoteTx */
+ 1 /* outputUsesInterrupts */
+ };
+
+#endif
+
+ return rtems_termios_open (major, minor, arg, &callbacks);
+}
+
+/*
+ * Close the device
+ */
+rtems_device_driver console_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_close (arg);
+}
+
+/*
+ * Read from the device
+ */
+rtems_device_driver console_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_read (arg);
+}
+
+/*
+ * Write to the device
+ */
+rtems_device_driver console_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_write (arg);
+}
+
+/*
+ * Handle ioctl request.
+ */
+rtems_device_driver console_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_ioctl (arg);
+}
diff --git a/c/src/lib/libbsp/m68k/mvme167/fatal/Makefile.in b/c/src/lib/libbsp/m68k/mvme167/fatal/Makefile.in
new file mode 100644
index 0000000000..6c8b9e1355
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/fatal/Makefile.in
@@ -0,0 +1,54 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+VPATH = @srcdir@
+RTEMS_ROOT = @top_srcdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+PGM=${ARCH}/fatal.rel
+
+# C source names, if any, go here -- minus the .c
+C_PIECES=fatal
+C_FILES=$(C_PIECES:%=%.c)
+C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
+
+H_FILES=
+
+SRCS=$(C_FILES) $(H_FILES)
+OBJS=$(C_O_FILES)
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+DEFINES +=
+CPPFLAGS +=
+CFLAGS +=
+
+LD_PATHS +=
+LD_LIBS +=
+LDFLAGS +=
+
+#
+# Add your list of files to delete here. The config files
+# already know how to delete some stuff, so you may want
+# to just run 'make clean' first to see what gets missed.
+# 'make clobber' already includes 'make clean'
+#
+
+CLEAN_ADDITIONS +=
+CLOBBER_ADDITIONS +=
+
+${PGM}: ${SRCS} ${OBJS}
+ $(make-rel)
+
+all: ${ARCH} $(SRCS) $(PGM)
+
+# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
+install: all
diff --git a/c/src/lib/libbsp/m68k/mvme167/fatal/bspfatal.c b/c/src/lib/libbsp/m68k/mvme167/fatal/bspfatal.c
new file mode 100644
index 0000000000..8f1f69f999
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/fatal/bspfatal.c
@@ -0,0 +1,127 @@
+/* fatal.c
+ *
+ * User-define fatal error handler.
+ *
+ * Copyright (c) 1998, National Research Council of Canada
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <bsp.h>
+#include <fatal.h>
+
+/*
+ * mystrcat
+ *
+ * Can't rely on libc being operational. So we provide our own strcat-like
+ * function.
+ *
+ * Input parameters:
+ * destination - string (buffer) to append to
+ * source - string to append to the end of destination
+ *
+ * Output parameters:
+ * destination - source is appended to the end
+ *
+ * Return values:
+ * Number of characters appended.
+ */
+static int mystrcat(
+ char *destination,
+ const char *source
+)
+{
+ int i;
+
+ for ( i = 0; ( *destination++ = *source++) != '\0'; i++ );
+ return i;
+}
+
+
+/*
+ * bsp_fatal_error_occurred
+ *
+ * Called when rtems_fatal_error_occurred() is called. Returns control to
+ * 167Bug. The _Internal_error_Occurred() function has already saved the
+ * parameters in Internal_errors_What_happened. If the function returns,
+ * RTEMS will halt the CPU.
+ *
+ * Make sure the CPU is
+ *
+ * Input parameters:
+ * the_source - what subsystem the error originated in
+ * is_internal - if the error was internally generated
+ * the_error - fatal error status code
+ *
+ * Output parameters:
+ * output to the 167Bug console
+ *
+ * Return values: NONE.
+ */
+User_extensions_routine bsp_fatal_error_occurred(
+ Internal_errors_Source the_source,
+ rtems_boolean is_internal,
+ rtems_unsigned32 the_error
+)
+{
+ struct {
+ char index; /* First byte is number of chars in strbuf */
+ char strbuf[254]; /* In case count is bumped up by one by 167Bug */
+ } my_p_str;
+
+ my_p_str.index = 0;
+ my_p_str.index += mystrcat(
+ my_p_str.strbuf + my_p_str.index,
+ "\r\nRTEMS Fatal Error Occurred:\r\n the_source = " );
+
+ switch ( the_source ) {
+ case INTERNAL_ERROR_CORE:
+ my_p_str.index += mystrcat(
+ my_p_str.strbuf + my_p_str.index,
+ "INTERNAL_ERROR_CORE\r\n is_internal = " );
+ break;
+
+ case INTERNAL_ERROR_RTEMS_API:
+ my_p_str.index += mystrcat(
+ my_p_str.strbuf + my_p_str.index,
+ "INTERNAL_ERROR_RTEMS_API\r\n is_internal = " );
+ break;
+
+ case INTERNAL_ERROR_POSIX_API:
+ my_p_str.index += mystrcat(
+ my_p_str.strbuf + my_p_str.index,
+ "INTERNAL_ERROR_POSIX_API\r\n is_internal = " );
+ break;
+
+ default:
+ my_p_str.index += mystrcat(
+ my_p_str.strbuf + my_p_str.index,
+ "UNKNOWN\r\n is_internal = " );
+ break;
+ }
+
+ if ( is_internal )
+ my_p_str.index += mystrcat(
+ my_p_str.strbuf + my_p_str.index,
+ "TRUE\r\n the_error = 0x|10,8|\r\n" );
+ else
+ my_p_str.index += mystrcat(
+ my_p_str.strbuf + my_p_str.index,
+ "FALSE\r\n the_error = 0x|10,8|\r\n" );
+
+ lcsr->intr_ena = 0; /* disable interrupts */
+ m68k_set_vbr(0xFFE00000); /* restore 167Bug vectors */
+
+ asm volatile( "movel %0, -(%%a7)
+ pea (%%a7)
+ pea (%1)
+ trap #15 /* trap to 167Bug (.WRITDLN) */
+ .short 0x25
+ trap #15
+ .short 0x63"
+ :: "d" (the_error), "a" (&my_p_str) );
+}
diff --git a/c/src/lib/libbsp/m68k/mvme167/fatal/fatal.c b/c/src/lib/libbsp/m68k/mvme167/fatal/fatal.c
new file mode 100644
index 0000000000..8f1f69f999
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/fatal/fatal.c
@@ -0,0 +1,127 @@
+/* fatal.c
+ *
+ * User-define fatal error handler.
+ *
+ * Copyright (c) 1998, National Research Council of Canada
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <bsp.h>
+#include <fatal.h>
+
+/*
+ * mystrcat
+ *
+ * Can't rely on libc being operational. So we provide our own strcat-like
+ * function.
+ *
+ * Input parameters:
+ * destination - string (buffer) to append to
+ * source - string to append to the end of destination
+ *
+ * Output parameters:
+ * destination - source is appended to the end
+ *
+ * Return values:
+ * Number of characters appended.
+ */
+static int mystrcat(
+ char *destination,
+ const char *source
+)
+{
+ int i;
+
+ for ( i = 0; ( *destination++ = *source++) != '\0'; i++ );
+ return i;
+}
+
+
+/*
+ * bsp_fatal_error_occurred
+ *
+ * Called when rtems_fatal_error_occurred() is called. Returns control to
+ * 167Bug. The _Internal_error_Occurred() function has already saved the
+ * parameters in Internal_errors_What_happened. If the function returns,
+ * RTEMS will halt the CPU.
+ *
+ * Make sure the CPU is
+ *
+ * Input parameters:
+ * the_source - what subsystem the error originated in
+ * is_internal - if the error was internally generated
+ * the_error - fatal error status code
+ *
+ * Output parameters:
+ * output to the 167Bug console
+ *
+ * Return values: NONE.
+ */
+User_extensions_routine bsp_fatal_error_occurred(
+ Internal_errors_Source the_source,
+ rtems_boolean is_internal,
+ rtems_unsigned32 the_error
+)
+{
+ struct {
+ char index; /* First byte is number of chars in strbuf */
+ char strbuf[254]; /* In case count is bumped up by one by 167Bug */
+ } my_p_str;
+
+ my_p_str.index = 0;
+ my_p_str.index += mystrcat(
+ my_p_str.strbuf + my_p_str.index,
+ "\r\nRTEMS Fatal Error Occurred:\r\n the_source = " );
+
+ switch ( the_source ) {
+ case INTERNAL_ERROR_CORE:
+ my_p_str.index += mystrcat(
+ my_p_str.strbuf + my_p_str.index,
+ "INTERNAL_ERROR_CORE\r\n is_internal = " );
+ break;
+
+ case INTERNAL_ERROR_RTEMS_API:
+ my_p_str.index += mystrcat(
+ my_p_str.strbuf + my_p_str.index,
+ "INTERNAL_ERROR_RTEMS_API\r\n is_internal = " );
+ break;
+
+ case INTERNAL_ERROR_POSIX_API:
+ my_p_str.index += mystrcat(
+ my_p_str.strbuf + my_p_str.index,
+ "INTERNAL_ERROR_POSIX_API\r\n is_internal = " );
+ break;
+
+ default:
+ my_p_str.index += mystrcat(
+ my_p_str.strbuf + my_p_str.index,
+ "UNKNOWN\r\n is_internal = " );
+ break;
+ }
+
+ if ( is_internal )
+ my_p_str.index += mystrcat(
+ my_p_str.strbuf + my_p_str.index,
+ "TRUE\r\n the_error = 0x|10,8|\r\n" );
+ else
+ my_p_str.index += mystrcat(
+ my_p_str.strbuf + my_p_str.index,
+ "FALSE\r\n the_error = 0x|10,8|\r\n" );
+
+ lcsr->intr_ena = 0; /* disable interrupts */
+ m68k_set_vbr(0xFFE00000); /* restore 167Bug vectors */
+
+ asm volatile( "movel %0, -(%%a7)
+ pea (%%a7)
+ pea (%1)
+ trap #15 /* trap to 167Bug (.WRITDLN) */
+ .short 0x25
+ trap #15
+ .short 0x63"
+ :: "d" (the_error), "a" (&my_p_str) );
+}
diff --git a/c/src/lib/libbsp/m68k/mvme167/include/Makefile.in b/c/src/lib/libbsp/m68k/mvme167/include/Makefile.in
new file mode 100644
index 0000000000..cb7fbd4511
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/include/Makefile.in
@@ -0,0 +1,34 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+VPATH = @srcdir@
+RTEMS_ROOT = @top_srcdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+H_FILES = $(srcdir)/bsp.h $(srcdir)/coverhd.h $(srcdir)/page_table.h \
+ $(srcdir)/fatal.h
+
+#
+# Equate files are for including from assembly preprocessed by
+# gm4 or gasp. No examples are provided except for those for
+# other CPUs. The best way to generate them would be to
+# provide a program which generates the constants used based
+# on the C equivalents.
+#
+
+EQ_FILES =
+
+SRCS=$(H_FILES) $(EQ_FILES)
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+
+CLEAN_ADDITIONS +=
+CLOBBER_ADDITIONS +=
+
+all: $(SRCS)
+ $(INSTALL) -m 444 $(H_FILES) $(PROJECT_INCLUDE)
+ $(INSTALL) -m 444 $(EQ_FILES) $(PROJECT_INCLUDE)
diff --git a/c/src/lib/libbsp/m68k/mvme167/include/bsp.h b/c/src/lib/libbsp/m68k/mvme167/include/bsp.h
new file mode 100644
index 0000000000..ee66acd6cb
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/include/bsp.h
@@ -0,0 +1,478 @@
+/* bsp.h
+ *
+ * Following defines must reflect the setup of the particular MVME167.
+ * All page references are to the MVME166/MVME167/MVME187 Single Board
+ * Computer Programmer's Reference Guide (MVME187PG/D2) with the April
+ * 1993 supplements/addenda (MVME187PG/D2A1).
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * Modifications of respective RTEMS file:
+ * Copyright (c) 1998, National Research Council of Canada
+ *
+ * $Id$
+ */
+
+#ifndef __MVME167_H
+#define __MVME167_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <clockdrv.h>
+#include <console.h>
+#include <iosupp.h>
+
+
+/*
+ * This is NOT the base address of local RAM!
+ * This is the base local address of the VMEbus short I/O space. A local
+ * access to this space results in a A16 VMEbus I/O cycle. This base address
+ * is NOT configurable on the MVME167, although the types of VMEbus short I/O
+ * cycles generated when a cycle in the local 0xFFFF0000-0xFFFFFFFF address
+ * range is generated is under control of bits 8-15 of LCSR 0xFFF4002C. The
+ * GCSRs of other boards are accessible only through the VMEbus short I/O
+ * space. See pages 2-45 and 2-7.
+ */
+#define BOARD_BASE_ADDRESS 0xFFFF0000
+
+
+/*
+ * This address must be added to the BOARD_BASE_ADDRESS to access the GCSR of
+ * other MVMEs in the group, i.e. it represents the offset of the GCSRs in the
+ * VMEbus short I/O space. It also should represent the group address of this
+ * MVME167! The group address is configurable, and must match the address
+ * programmed into the MVME167 through the 167Bug monitor. 0xCC is the address
+ * recommended by Motorola. It is arbitrary.
+ * See pages 2-42 and 2-97 to 2-104.
+ */
+#define GROUP_BASE_ADDRESS 0x0000CC00
+
+
+/*
+ * Representation of the GCSR
+ */
+typedef volatile struct gcsr_regs_ {
+ unsigned char chip_revision;
+ unsigned char chip_id;
+ unsigned char lmsig;
+ unsigned char board_scr;
+ unsigned short gpr[6];
+} gcsr_regs;
+
+/* Address of GCSR in VMEbus space */
+#define gcsr_vme ((gcsr_regs * const) (GROUP_BASE_ADDRESS + BOARD_BASE_ADDRESS))
+
+/* Address of GCSR in local space */
+#define gcsr ((gcsr_regs * const) 0xFFF40100)
+
+/*
+ * Representation of the VMEchip2 LCSR.
+ * Could be made more detailed.
+ */
+typedef volatile struct lcsr_regs_ {
+ unsigned long slave_adr[2]; /* 0xFFF40000 */
+ unsigned long slave_trn[2]; /* 0xFFF40008 */
+ unsigned long slave_ctl; /* 0xFFF40010 */
+ unsigned long mastr_adr[4]; /* 0xFFF40014 */
+ unsigned long mastr_trn; /* 0xFFF40024 */
+ unsigned long mastr_att; /* 0xFFF40028 */
+ unsigned long mastr_ctl; /* 0xFFF4002C */
+ unsigned long dma_ctl_1; /* 0xFFF40030 */
+ unsigned long dma_ctl_2; /* 0xFFF40034 */
+ unsigned long dma_loc_cnt; /* 0xFFF40038 */
+ unsigned long dma_vme_cnt; /* 0xFFF4003C */
+ unsigned long dma_byte_cnt; /* 0xFFF40040 */
+ unsigned long dma_adr_cnt; /* 0xFFF40044 */
+ unsigned long dma_status; /* 0xFFF40048 */
+ unsigned long to_ctl; /* 0xFFF4004C */
+ unsigned long timer_cmp_1; /* 0xFFF40050 */
+ unsigned long timer_cnt_1; /* 0xFFF40054 */
+ unsigned long timer_cmp_2; /* 0xFFF40058 */
+ unsigned long timer_cnt_2; /* 0xFFF4005C */
+ unsigned long board_ctl; /* 0xFFF40060 */
+ unsigned long prescaler_cnt; /* 0xFFF40064 */
+ unsigned long intr_stat; /* 0xFFF40068 */
+ unsigned long intr_ena; /* 0xFFF4006C */
+ unsigned long intr_soft_set; /* 0xFFF40070 */
+ unsigned long intr_clear; /* 0xFFF40074 */
+ unsigned long intr_level[4]; /* 0xFFF40078 */
+ unsigned long vector_base; /* 0xFFF40088 */
+} lcsr_regs;
+
+/*
+ * Base address of VMEchip2 LCSR
+ * Not configurable on the MVME167.
+ */
+#define lcsr ((lcsr_regs * const) 0xFFF40000)
+
+/*
+ * Vector numbers for the interrupts from the VMEchip2. Use the values
+ * "recommended" by Motorola.
+ * See pages 2-70 to 2-92, and table 2-3.
+ */
+
+/* MIEN (Master Interrupt Enable) bit in LCSR 0xFFF40088. */
+#define MASK_INT 0x00800000
+
+/* The content of VBR0 corresponds to "X" in table 2-3 */
+#define VBR0 0x6
+
+/* The content of VBR1 corresponds to "Y" in table 2-3 */
+#define VBR1 0x7
+
+
+/*
+ * Representation of the PCCchip2
+ */
+typedef volatile struct pccchip2_regs_ {
+ unsigned char chip_id; /* 0xFFF42000 */
+ unsigned char chip_revision; /* 0xFFF42001 */
+ unsigned char gen_control; /* 0xFFF42002 */
+ unsigned char vector_base; /* 0xFFF42003 */
+ unsigned long timer_cmp_1; /* 0xFFF42004 */
+ unsigned long timer_cnt_1; /* 0xFFF42008 */
+ unsigned long timer_cmp_2; /* 0xFFF4200C */
+ unsigned long timer_cnt_2; /* 0xFFF42010 */
+ unsigned char LSB_prescaler_count;/* 0xFFF42014 */
+ unsigned char prescaler_clock_adjust; /* 0xFFF42015 */
+ unsigned char timer_ctl_2; /* 0xFFF42016 */
+ unsigned char timer_ctl_1; /* 0xFFF42017 */
+ unsigned char gpi_int_ctl; /* 0xFFF42018 */
+ unsigned char gpio_ctl; /* 0xFFF42019 */
+ unsigned char timer_int_ctl_2; /* 0xFFF4201A */
+ unsigned char timer_int_ctl_1; /* 0xFFF4201B */
+ unsigned char SCC_error; /* 0xFFF4201C */
+ unsigned char SCC_modem_int_ctl; /* 0xFFF4201D */
+ unsigned char SCC_tx_int_ctl; /* 0xFFF4201E */
+ unsigned char SCC_rx_int_ctl; /* 0xFFF4201F */
+ unsigned char reserved1[3];
+ unsigned char modem_piack; /* 0xFFF42023 */
+ unsigned char reserved2;
+ unsigned char tx_piack; /* 0xFFF42025 */
+ unsigned char reserved3;
+ unsigned char rx_piack; /* 0xFFF42027 */
+ unsigned char LANC_error; /* 0xFFF42028 */
+ unsigned char reserved4;
+ unsigned char LANC_int_ctl; /* 0xFFF4202A */
+ unsigned char LANC_berr_ctl; /* 0xFFF4202B */
+ unsigned char SCSI_error; /* 0xFFF4202C */
+ unsigned char reserved5[2];
+ unsigned char SCSI_int_ctl; /* 0xFFF4202F */
+ unsigned char print_ack_int_ctl; /* 0xFFF42030 */
+ unsigned char print_fault_int_ctl;/* 0xFFF42031 */
+ unsigned char print_sel_int_ctl; /* 0xFFF42032 */
+ unsigned char print_pe_int_ctl; /* 0xFFF42033 */
+ unsigned char print_busy_int_ctl; /* 0xFFF42034 */
+ unsigned char reserved6;
+ unsigned char print_input_status; /* 0xFFF42036 */
+ unsigned char print_ctl; /* 0xFFF42037 */
+ unsigned char chip_speed; /* 0xFFF42038 */
+ unsigned char reserved7;
+ unsigned char print_data; /* 0xFFF4203A */
+ unsigned char reserved8[3];
+ unsigned char int_level; /* 0xFFF4203E */
+ unsigned char int_mask; /* 0xFFF4203F */
+} pccchip2_regs;
+
+/*
+ * Base address of the PCCchip2.
+ * This is not configurable in the MVME167.
+ */
+#define pccchip2 ((pccchip2_regs * const) 0xFFF42000)
+
+/*
+ * Vector numbers for the interrupts from the PCCchip2. Use the values
+ * "recommended" by Motorola.
+ * See page 3-15.
+ */
+#define PCCCHIP2_VBR 0x5
+
+
+/*
+ * The MVME167 is equiped with one or two MEMC040 memory controllers at
+ * 0xFFF43000 and 0xFFF43100. This port assumes that the controllers
+ * were initialized by 167Bug.
+ */
+typedef volatile struct memc040_regs_ {
+ unsigned char chip_id; /* 0xFFF43000/0xFFF43100 */
+ unsigned char reserved1[3];
+ unsigned char chip_revision; /* 0xFFF43004/0xFFF43104 */
+ unsigned char reserved2[3];
+ unsigned char mem_config; /* 0xFFF43008/0xFFF43108 */
+ unsigned char reserved3[3];
+ unsigned char alt_status; /* 0xFFF4300C/0xFFF4310C */
+ unsigned char reserved4[3];
+ unsigned char alt_ctl; /* 0xFFF43010/0xFFF43110 */
+ unsigned char reserved5[3];
+ unsigned char base_addr; /* 0xFFF43014/0xFFF43114 */
+ unsigned char reserved6[3];
+ unsigned char ram_ctl; /* 0xFFF43018/0xFFF43118 */
+ unsigned char reserved7[3];
+ unsigned char bus_clk; /* 0xFFF4301C/0xFFF4311C */
+} memc040_regs;
+
+/*
+ * Base address of the MEMC040s.
+ * This is not configurable in the MVME167.
+ */
+#define memc040_1 ((memc040_regs * const) 0xFFF43000)
+#define memc040_2 ((memc040_regs * const) 0xFFF43100)
+
+
+/*
+ * The MVME167 may be equiped with error-correcting RAM cards. In this case,
+ * each MEMC040 is replaced by two MCECC ECC DRAM controllers. This port
+ * assumes that these controllers, if present, are initialized by 167Bug.
+ * They do not appear to hold information of interest at this time, so they
+ * are not described. However, each MCECC pair lives at the same address as
+ * the MEMC040 is replaces. The first eight registers of the MCECC are
+ * nearly identical to the ones of the MEMC040, and the memc040_X structures
+ * can be used to read those first eight registers.
+ */
+
+
+/*
+ * Representation of the Cirrus Logic CL-CD2401 Multi-Protocol Controller
+ */
+typedef volatile struct cd2401_regs_ {
+ unsigned char reserved1[7];
+ unsigned char cor7; /* 0xFFF45007 - Channel Option 7 */
+ unsigned char reserved2;
+ unsigned char livr; /* 0xFFF45009 - Local Interrupt Vector */
+ unsigned char reserved3[6];
+ unsigned char cor1; /* 0xFFF45010 - Channel Option 1 */
+ unsigned char ier; /* 0xFFF45011 - Interrupt Enable */
+ unsigned char stcr; /* 0xFFF45012 - Special Transmit Command */
+ unsigned char ccr; /* 0xFFF45013 - Channel Command */
+ unsigned char cor5; /* 0xFFF45014 - Channel Option 5 */
+ unsigned char cor4; /* 0xFFF45015 - Channel Option 4 */
+ unsigned char cor3; /* 0xFFF45016 - Channel Option 3 */
+ unsigned char cor2; /* 0xFFF45017 - Channel Option 2 */
+ unsigned char cor6; /* 0xFFF45018 - Channel Option 6 */
+ unsigned char dmabsts; /* 0xFFF45019 - DMA Buffer Status */
+ unsigned char csr; /* 0xFFF4501A - Channel Status */
+ unsigned char cmr; /* 0xFFF4501B - Channel Mode */
+ union {
+ struct {
+ unsigned char schr4; /* 0xFFF4501C - Special Character 4 */
+ unsigned char schr3; /* 0xFFF4501D - Special Character 3 */
+ unsigned char schr2; /* 0xFFF4501E - Special Character 2 */
+ unsigned char schr1; /* 0xFFF4501F - Special Character 1 */
+ } async;
+ struct {
+ unsigned char rfar4; /* 0xFFF4501C - Receive Frame Address 4 */
+ unsigned char rfar3; /* 0xFFF4501D - Receive Frame Address 3 */
+ unsigned char rfar2; /* 0xFFF4501E - Receive Frame Address 2 */
+ unsigned char rfar1; /* 0xFFF4501F - Receive Frame Address 1 */
+ } sync;
+ } u1;
+ unsigned char reserved4[2];
+ unsigned char scrh; /* 0xFFF45022 - Special Character Range High */
+ unsigned char scrl; /* 0xFFF45023 - Special Character Range Low */
+ union {
+ struct {
+ unsigned short rtpr; /* 0xFFF45024 - Receive Timeout Period */
+ } w;
+ struct {
+ unsigned char rtprh; /* 0xFFF45024 - Receive Timeout Period High */
+ unsigned char rtprl; /* 0xFFF45025 - Receive Timeout Period Low */
+ } b;
+ } u2;
+ unsigned char licr; /* 0xFFF45026 - Local Interrupt Channel */
+ unsigned char reserved5[2];
+ union {
+ struct {
+ unsigned char ttr; /* 0xFFF45029 - Transmit Timer */
+ } async;
+ struct {
+ unsigned char gt2; /* 0xFFF45029 - General Timer 2 */
+ } sync;
+ } u3;
+ union {
+ struct {
+ unsigned short gt1; /* 0xFFF4502A - General Timer 1 */
+ } w;
+ struct {
+ unsigned char gt1h; /* 0xFFF4502A - General Timer 2 High */
+ unsigned char gt1l; /* 0xFFF4502B - General Timer 1 Low */
+ } b;
+ } u4;
+ unsigned char reserved6[2];
+ unsigned char lnxt; /* 0xFF4502E - LNext Character */
+ unsigned char reserved7;
+ unsigned char rfoc; /* 0xFFF45030 - Receive FIFO Output Count */
+ unsigned char reserved8[7];
+ unsigned short tcbadru; /* 0xFF45038 - Transmit Current Buffer Address Upper */
+ unsigned short tcbadrl; /* 0xFF4503A - Transmit Current Buffer Address Lower */
+ unsigned short rcbadru; /* 0xFF4503C - Receive Current Buffer Address Upper */
+ unsigned short rcbadrl; /* 0xFF4503E - Receive Current Buffer Address Lower */
+ unsigned short arbadru; /* 0xFF45040 - A Receive Buffer Address Upper */
+ unsigned short arbardl; /* 0xFF45042 - A Receive Buffer Address Lower */
+ unsigned short brbadru; /* 0xFF45044 - B Receive Buffer Address Upper */
+ unsigned short brbadrl; /* 0xFF45046 - B Receive Buffer Address Lower */
+ unsigned short brbcnt; /* 0xFF45048 - B Receive Buffer Byte Count */
+ unsigned short arbcnt; /* 0xFF4504A - A Receive Buffer Byte Count */
+ unsigned short reserved9;
+ unsigned char brbsts; /* 0xFF4504E - B Receive Buffer Status */
+ unsigned char arbsts; /* 0xFF4504F - A Receive Buffer Status */
+ unsigned short atbadru; /* 0xFF45050 - A Transmit Buffer Address Upper */
+ unsigned short atbadrl; /* 0xFF45052 - A Transmit Buffer Address Lower */
+ unsigned short btbadru; /* 0xFF45054 - B Transmit Buffer Address Upper */
+ unsigned short btbadrl; /* 0xFF45056 - B Transmit Buffer Address Lower */
+ unsigned short btbcnt; /* 0xFF45058 - B Transmit Buffer Byte Count */
+ unsigned short atbcnt; /* 0xFF4505A - A Transmit Buffer Byte Count */
+ unsigned short reserved10;
+ unsigned char btbsts; /* 0xFF4505E - B Transmit Buffer Status */
+ unsigned char atbsts; /* 0xFF4505F - A Transmit Buffer Status */
+ unsigned char reserved11[32];
+ unsigned char tftc; /* 0xFFF45080 - Transmit FIFO Transfer Count */
+ unsigned char gfrcr; /* 0xFFF45081 - Global Firmware Revision Code */
+ unsigned char reserved12[2];
+ unsigned char reoir; /* 0xFFF45084 - Receive End Of Interrupt */
+ unsigned char teoir; /* 0xFFF45085 - Transmit End Of Interrupt */
+ unsigned char meoir; /* 0xFFF45086 - Modem End Of Interrupt */
+ union {
+ struct {
+ unsigned short risr; /* 0xFFF45088 - Receive Interrupt Status */
+ } w;
+ struct {
+ unsigned char risrh; /* 0xFFF45088 - Receive Interrupt Status High */
+ unsigned char risrl; /* 0xFFF45089 - Receive Interrupt Status Low */
+ } b;
+ } u5;
+ unsigned char tisr; /* 0xFFF4508A - Transmit Interrupt Status */
+ unsigned char misr; /* 0xFFF4508B - Modem/Timer Interrupt Status */
+ unsigned char reserved13[2];
+ unsigned char bercnt; /* 0xFFF4508E - Bus Error Retry Count */
+ unsigned char reserved14[49];
+ unsigned char tcor; /* 0xFFF450C0 - Transmit Clock Option */
+ unsigned char reserved15[2];
+ unsigned char tbpr; /* 0xFFF450C3 - Transmit Baud Rate Period */
+ unsigned char reserved16[4];
+ unsigned char rcor; /* 0xFFF450C8 - Receive Clock Option */
+ unsigned char reserved17[2];
+ unsigned char rbpr; /* 0xFFF450CB - Receive Baud Rate Period */
+ unsigned char reserved18[10];
+ unsigned char cpsr; /* 0xFFF450D6 - CRC Polynomial Select */
+ unsigned char reserved19[3];
+ unsigned char tpr; /* 0xFFF450DA - Timer Period */
+ unsigned char reserved20[3];
+ unsigned char msvr_rts; /* 0xFFF450DE - Modem Signal Value - RTS */
+ unsigned char msvr_dtr; /* 0xFFF450DF - Modem Signal Value - DTR */
+ unsigned char tpilr; /* 0xFFF450E0 - Transmit Priority Interrupt Level */
+ unsigned char rpilr; /* 0xFFF450E1 - Receive Priority Interrupt Level */
+ unsigned char stk; /* 0xFFF450E2 - Stack */
+ unsigned char mpilr; /* 0xFFF450E3 - Modem Priority Interrupt Level */
+ unsigned char reserved21[8];
+ unsigned char tir; /* 0xFFF450EC - Transmit Interrupt */
+ unsigned char rir; /* 0xFFF450ED - Receive Interrupt */
+ unsigned char car; /* 0xFFF450EE - Channel Access */
+ unsigned char mir; /* 0xFFF450EF - Model Interrupt */
+ unsigned char reserved22[6];
+ unsigned char dmr; /* 0xFFF450F6 - DMA Mode */
+ unsigned char reserved23;
+ unsigned char dr; /* 0xFFF450F8 - Receive/Transmit Data */
+} cd2401_regs;
+
+
+/*
+ * Base address of the CD2401.
+ * This is not configurable in the MVME167.
+ */
+#define cd2401 ((cd2401_regs * const) 0xFFF45000)
+
+
+/* CD2401 is clocked at 20 MHz */
+#define CD2401_CLK_RATE 20000000
+
+void console_reserve_resources( rtems_configuration_table *configuration );
+
+/* BSP-wide functions */
+
+void bsp_cleanup( void );
+
+m68k_isr_entry set_vector(
+ rtems_isr_entry handler,
+ rtems_vector_number vector,
+ int type
+);
+
+#ifdef M167_INIT
+#undef EXTERN
+#define EXTERN
+#else
+#undef EXTERN
+#define EXTERN extern
+#endif
+
+/*
+ * Device Driver Table Entries
+ */
+
+/*
+ * NOTE: Use the standard Console driver entry
+ */
+
+/*
+ * NOTE: Use the standard Clock driver entry
+ */
+
+/*
+ * How many libio files we want
+ */
+
+#define BSP_LIBIO_MAX_FDS 20
+
+
+/* miscellaneous stuff assumed to exist */
+
+extern rtems_configuration_table BSP_Configuration;
+
+extern m68k_isr_entry M68Kvec[]; /* vector table address */
+
+
+/*
+ * Define the time limits for RTEMS Test Suite test durations.
+ * Long test and short test duration limits are provided. These
+ * values are in seconds and need to be converted to ticks for the
+ * application.
+ *
+ */
+
+#define MAX_LONG_TEST_DURATION 300 /* 5 minutes = 300 seconds */
+#define MAX_SHORT_TEST_DURATION 3 /* 3 seconds */
+
+/*
+ * Define the interrupt mechanism for Time Test 27
+ *
+ * NOTE: We use software interrupt 0
+ */
+#define MUST_WAIT_FOR_INTERRUPT 0
+
+#define Install_tm27_vector( handler ) \
+ set_vector( (handler), VBR1 * 0x10 + 0x8, 1 ); \
+ lcsr->intr_level[2] |= 3; \
+ lcsr->intr_ena |= 0x100
+
+#define Cause_tm27_intr() lcsr->intr_soft_set |= 0x100
+
+#define Clear_tm27_intr() lcsr->intr_clear |= 0x100
+
+#define Lower_tm27_intr()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/c/src/lib/libbsp/m68k/mvme167/include/coverhd.h b/c/src/lib/libbsp/m68k/mvme167/include/coverhd.h
new file mode 100644
index 0000000000..8c1f1a9e7f
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/include/coverhd.h
@@ -0,0 +1,104 @@
+/* coverhd.h
+ *
+ * This include file has defines to represent the overhead associated
+ * with calling a particular directive from C on this target.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#ifndef __COVERHD_h
+#define __COVERHD_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#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 1
+#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 1
+#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 1
+#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 1
+#define CALLING_OVERHEAD_REGION_RETURN_SEGMENT 0
+#define CALLING_OVERHEAD_PORT_CREATE 1
+#define CALLING_OVERHEAD_PORT_IDENT 0
+#define CALLING_OVERHEAD_PORT_DELETE 0
+#define CALLING_OVERHEAD_PORT_EXTERNAL_TO_INTERNAL 1
+#define CALLING_OVERHEAD_PORT_INTERNAL_TO_EXTERNAL 1
+
+#define CALLING_OVERHEAD_IO_INITIALIZE 1
+#define CALLING_OVERHEAD_IO_OPEN 1
+#define CALLING_OVERHEAD_IO_CLOSE 1
+#define CALLING_OVERHEAD_IO_READ 1
+#define CALLING_OVERHEAD_IO_WRITE 1
+#define CALLING_OVERHEAD_IO_CONTROL 1
+#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
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/c/src/lib/libbsp/m68k/mvme167/include/fatal.h b/c/src/lib/libbsp/m68k/mvme167/include/fatal.h
new file mode 100644
index 0000000000..9b90587bbc
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/include/fatal.h
@@ -0,0 +1,19 @@
+/* fatal.h
+ *
+ * Copyright (c) 1998, National Research Council of Canada
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems/score/interr.h>
+#include <rtems/score/userext.h>
+
+User_extensions_routine bsp_fatal_error_occurred(
+ Internal_errors_Source the_source,
+ rtems_boolean is_internal,
+ rtems_unsigned32 the_error
+);
diff --git a/c/src/lib/libbsp/m68k/mvme167/include/page_table.h b/c/src/lib/libbsp/m68k/mvme167/include/page_table.h
new file mode 100644
index 0000000000..5a44933958
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/include/page_table.h
@@ -0,0 +1,46 @@
+/* page_table.h
+ *
+ * This file was submitted by Eric Vaitl <vaitl@viasat.com> and
+ * supports page table initialization.
+ *
+ * For now, we only use the transparent translation registers. Page tables
+ * may be set up in the future.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * Modifications of respective RTEMS files:
+ * Copyright (c) 1998, National Research Council of Canada
+ *
+ * $Id$
+ */
+
+#ifndef __PAGE_TABLE_H
+#define __PAGE_TABLE_H
+
+#include <rtems.h>
+
+void page_table_teardown( void );
+void page_table_init( rtems_configuration_table *config_table );
+
+enum {
+ CACHE_WRITE_THROUGH,
+ CACHE_COPYBACK,
+ CACHE_NONE_SERIALIZED,
+ CACHE_NONE
+};
+
+enum {
+ PTM_SUCCESS,
+ PTM_BAD_ADDR,
+ PTM_BAD_SIZE,
+ PTM_BAD_CACHE,
+ PTM_NO_TABLE_SPACE
+};
+
+#endif
diff --git a/c/src/lib/libbsp/m68k/mvme167/startup/Makefile.in b/c/src/lib/libbsp/m68k/mvme167/startup/Makefile.in
new file mode 100644
index 0000000000..2d24607aaa
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/startup/Makefile.in
@@ -0,0 +1,53 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+VPATH = @srcdir@:@srcdir@/../../shared:@srcdir@/../../../shared
+RTEMS_ROOT = @top_srcdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+PGM=${ARCH}/startup.rel
+
+# C source names, if any, go here -- minus the .c
+C_PIECES=bspclean bsplibc bsppost bspstart main page_table sbrk setvec
+C_FILES=$(C_PIECES:%=%.c)
+C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
+
+H_FILES=
+
+SRCS=$(srcdir)/linkcmds $(C_FILES) $(H_FILES)
+OBJS=$(C_O_FILES)
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+DEFINES +=
+CPPFLAGS +=
+CFLAGS +=
+
+LD_PATHS +=
+LD_LIBS +=
+LDFLAGS +=
+
+#
+# Add your list of files to delete here. The config files
+# already know how to delete some stuff, so you may want
+# to just run 'make clean' first to see what gets missed.
+# 'make clobber' already includes 'make clean'
+#
+
+CLEAN_ADDITIONS +=
+CLOBBER_ADDITIONS +=
+
+${PGM}: ${SRCS} ${OBJS}
+ $(make-rel)
+
+all: ${ARCH} $(SRCS) $(PGM)
+ $(INSTALL) $(srcdir)/linkcmds ${PROJECT_RELEASE}/lib
+
diff --git a/c/src/lib/libbsp/m68k/mvme167/startup/bspclean.c b/c/src/lib/libbsp/m68k/mvme167/startup/bspclean.c
new file mode 100644
index 0000000000..753c378cae
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/startup/bspclean.c
@@ -0,0 +1,81 @@
+/* bspclean.c
+ *
+ * These routines return control to 167Bug after a normal exit from the
+ * application.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * Modifications of respective RTEMS files:
+ * Copyright (c) 1998, National Research Council of Canada
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <bsp.h>
+#include <page_table.h>
+
+/*
+ * bsp_return_to_monitor_trap
+ *
+ * Switch the VBR back to ROM and make a .RETURN syscall to return control to
+ * 167 Bug. If 167Bug ever returns, restart the application.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values: NONE
+ */
+static void bsp_return_to_monitor_trap( void )
+{
+ extern void start( void );
+
+ register volatile void *start_addr;
+
+ page_table_teardown();
+
+ lcsr->intr_ena = 0; /* disable interrupts */
+ m68k_set_vbr(0xFFE00000); /* restore 167Bug vectors */
+ asm volatile( "trap #15 /* trap to 167Bug */
+ .short 0x63" ); /* return to 167Bug (.RETURN) */
+
+ /* restart program */
+ start_addr = start;
+ asm volatile( "jmp %0@" : "=a" (start_addr) : "0" (start_addr) );
+}
+
+/*
+ * bsp_cleanup
+ *
+ * This code was copied from other MC680x0 MVME BSPs.
+ * Our guess is that someone was concerned about the CPU no longer being in
+ * supervisor mode when they got here. This function forces the CPU back to
+ * supervisor mode so the VBR may be changed. It places the address of the
+ * function that makes a 167Bug .RETURN syscall in the trap 13 entry in the
+ * exception vector, and then issues a trap 13 call. It is also possible that
+ * the code was copied from some other OS that does run tasks in user mode.
+ * In any case, it appears to be a bit of paranoia, and could lead to
+ * problems if 167Bug is invoked before we get to switch the VBR back to
+ * 167Bug because trap 13 is documented as being reserved for the internal
+ * use of the debugger.
+ *
+ * Prototyped in rtems/c/src/lib/libbsp/m68k/mvme167/include/bsp.h
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values: DOES NOT RETURN
+ */
+void bsp_cleanup( void )
+{
+ M68Kvec[ 45 ] = bsp_return_to_monitor_trap;
+ asm volatile( "trap #13" );
+}
diff --git a/c/src/lib/libbsp/m68k/mvme167/startup/bspstart.c b/c/src/lib/libbsp/m68k/mvme167/startup/bspstart.c
new file mode 100644
index 0000000000..e4630e808e
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/startup/bspstart.c
@@ -0,0 +1,201 @@
+/* bspstart.c
+ *
+ * This set of routines starts the application. It includes application,
+ * board, and monitor specific initialization and configuration. The generic
+ * CPU dependent initialization has been performed before any of these are
+ * invoked.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * Modifications of respective RTEMS files:
+ * Copyright (c) 1998, National Research Council of Canada
+ *
+ * $Id$
+ */
+
+
+#include <bsp.h>
+#include <page_table.h>
+#include <fatal.h>
+#include <rtems/libio.h>
+
+#include <libcsupport.h>
+
+#include <string.h>
+
+
+/*
+ * The original table from the application (in ROM) and our copy of it with
+ * some changes. Configuration is defined in <confdefs.h>. Make sure that
+ * our configuration tables are uninitialized so that they get allocated in
+ * the .bss section (RAM).
+ */
+extern rtems_configuration_table Configuration;
+rtems_configuration_table BSP_Configuration;
+rtems_extensions_table user_extension_table;
+
+rtems_cpu_table Cpu_table;
+
+/*
+ * Use the shared implementations of the following routines.
+ * Look in rtems/c/src/lib/libbsp/shared/bsppost.c and
+ * rtems/c/src/lib/libbsp/shared/bsplibc.c.
+ */
+void bsp_postdriver_hook( void );
+void bsp_libc_init( void *, unsigned32, int );
+
+
+/*
+ * bsp_pretasking_hook
+ *
+ * Called when RTEMS initialization is complete but before interrupts and
+ * tasking are enabled. Used to setup libc and install any BSP extensions.
+ *
+ * Must not use libc (to do io) from here, since drivers are not yet
+ * initialized.
+ *
+ * Installed in the rtems_cpu_table defined in
+ * rtems/c/src/exec/score/cpu/m68k/cpu.h in main() below. Called from
+ * rtems_initialize_executive() defined in rtems/c/src/exec/sapi/src/init.c
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values: NONE
+ */
+void bsp_pretasking_hook( void )
+{
+ /*
+ * These are assigned addresses in the linkcmds file for the BSP. This
+ * approach is better than having these defined as manifest constants and
+ * compiled into the kernel, but it is still not ideal when dealing with
+ * multiprocessor configuration in which each board as a different memory
+ * map. A better place for defining these symbols might be the makefiles.
+ * Consideration should also be given to developing an approach in which
+ * the kernel and the application can be linked and burned into ROM
+ * independently of each other.
+ */
+ extern unsigned char _HeapStart, _HeapEnd;
+
+ bsp_libc_init(&_HeapStart, &_HeapEnd - &_HeapStart, 0);
+
+#ifdef RTEMS_DEBUG
+ rtems_debug_enable( RTEMS_DEBUG_ALL_MASK );
+#endif
+}
+
+
+/*
+ * bsp_start()
+ *
+ * Board-specific initialization code. Called from the generic boot_card()
+ * function defined in rtems/c/src/lib/libbsp/shared/main.c. That function
+ * does some of the board independent initialization. It is called from the
+ * generic MC680x0 entry point _start() defined in
+ * rtems/c/src/lib/start/m68k/start.s
+ *
+ * _start() has set up a stack, has zeroed the .bss section, has turned off
+ * interrupts, and placed the processor in the supervisor mode. boot_card()
+ * has left the processor in that state when bsp_start() was called.
+ *
+ * RUNS WITH ADDRESS TRANSLATION AND CACHING TURNED OFF!
+ * ASSUMES THAT THE VIRTUAL ADDRESSES WILL BE IDENTICAL TO THE PHYSICAL
+ * ADDRESSES. Software-controlled address translation would be required
+ * otherwise.
+ *
+ * ASSUMES THAT 167BUG IS PRESENT TO CATCH ANY EXCEPTIONS DURING
+ * INITIALIZATION.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values: NONE
+ */
+void bsp_start( void )
+{
+ extern void *_WorkspaceBase;
+ extern m68k_isr_entry M68Kvec[];
+
+ m68k_isr_entry *rom_monitor_vector_table;
+ int index;
+
+ /*
+ * 167Bug Vectors are at 0xFFE00000
+ */
+ rom_monitor_vector_table = (m68k_isr_entry *)0xFFE00000;
+ m68k_set_vbr( rom_monitor_vector_table );
+
+
+ /*
+ * Copy 167Bug Bus Error handler into our exception vector. All 167Bug
+ * exception vectors are the same and point to the generalized exception
+ * handler. The bus error handler is the one that Motorola says to copy
+ * (p. 2-13, Debugging Package for Motorola 68K CISC CPUs User's Manual
+ * 68KBUG/D1A3, October 1993).
+ */
+ for ( index=2 ; index<=255 ; index++ )
+ M68Kvec[ index ] = rom_monitor_vector_table[ 2 ];
+
+ /* Any exceptions during initialization should be trapped by 167Bug */
+ m68k_set_vbr( &M68Kvec );
+
+ /*
+ * You may wish to make the VME arbitration round-robin here, currently
+ * we leave it as it is.
+ */
+
+ /* Set the Interrupt Base Vectors */
+ lcsr->vector_base = (VBR0 << 28) | (VBR1 << 24);
+
+ /*
+ * Initialize address translation
+ * May need to pass the multiprocessor configuration table.
+ */
+ page_table_init( &Configuration );
+
+ /* We only use a hook to get the C library initialized. */
+ Cpu_table.pretasking_hook = bsp_pretasking_hook; /* init libc, etc. */
+ Cpu_table.postdriver_hook = bsp_postdriver_hook;
+ Cpu_table.interrupt_vector_table = (m68k_isr_entry *) &M68Kvec;
+ Cpu_table.interrupt_stack_size = 4096; /* Must match value in start.s */
+
+ /*
+ * If the application has not overriden the default User_extension_table,
+ * supply one with our own fatal error handler that returns control to
+ * 167Bug.
+ */
+ if ( BSP_Configuration.User_extension_table == NULL ) {
+ user_extension_table.fatal = bsp_fatal_error_occurred;
+ BSP_Configuration.User_extension_table = &user_extension_table;
+ }
+
+ /*
+ * Need to "allocate" the memory for the RTEMS Workspace and
+ * tell the RTEMS configuration where it is. This memory is
+ * not malloc'ed. It is just "pulled from the air".
+ */
+ BSP_Configuration.work_space_start = (void *)&_WorkspaceBase;
+
+ /*
+ * Increase the number of semaphores that can be created on this node. The
+ * termios package requires one semaphore to protect the list of termios-
+ * capable terminals, and up to four semaphores per termios-capable
+ * terminal (add calls here as required). The maximum number of semaphores
+ * must be set before returning to boot_card(), which will call
+ * rtems_initialize_executive_early(). This latter function eventually
+ * calls _RTEMS_API_Initialize(), which in turn calls
+ * _Semaphore_Manager_initialization(), which allocates the space for the
+ * maximum number of semaphores in the object table. These calls occur
+ * before the call to the predriver hook and the calls to the device
+ * initialization callbacks. Hence, we must do this here.
+ */
+ console_reserve_resources( &BSP_Configuration );
+}
diff --git a/c/src/lib/libbsp/m68k/mvme167/startup/linkcmds b/c/src/lib/libbsp/m68k/mvme167/startup/linkcmds
new file mode 100644
index 0000000000..a1f285a09d
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/startup/linkcmds
@@ -0,0 +1,103 @@
+/*
+ * This file contains directives for the GNU linker which are specific
+ * to the Motorola MVME167 board.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * Modifications of respective RTEMS file:
+ * Copyright (c) 1998, National Research Council of Canada
+ *
+ * $Id$
+ */
+
+/* Base address and size of RAM on the MVME167 */
+
+RAM_SIZE = 4M;
+RAM_START = 0x00800000;
+RAM_END = RAM_START + RAM_SIZE;
+
+/*
+ * Declare some sizes.
+ * XXX: The assignment of ". += XyzSize;" fails in older gld's if the
+ * number used there is not constant. If this happens to you, edit
+ * the lines marked XXX below to use a constant value.
+ */
+HeapSize = DEFINED(HeapSize) ? HeapSize : 0x10000;
+StackSize = DEFINED(StackSize) ? StackSize : 0x1000;
+
+MEMORY
+{
+ ram : org = 0x00800000, l = 4M
+}
+
+SECTIONS
+{
+ .text 0x00800000 :
+ {
+ text_start = . ;
+ *(.text)
+ . = ALIGN (16);
+
+ *(.eh_fram)
+ . = ALIGN (16);
+
+ *(.gcc_exc)
+ . = ALIGN (16);
+
+ /*
+ * C++ constructors
+ */
+ __CTOR_LIST__ = .;
+ LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
+ *(.ctors)
+ LONG(0)
+ __CTOR_END__ = .;
+ __DTOR_LIST__ = .;
+ LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
+ *(.dtors)
+ LONG(0)
+ __DTOR_END__ = .;
+ etext = ALIGN( 0x10 ) ;
+ } >ram
+
+ .data ADDR( .text ) + SIZEOF( .text ):
+ {
+ data_start = . ;
+ *(.data)
+ edata = ALIGN( 0x10 ) ;
+ } >ram
+
+ .bss ADDR( .data ) + SIZEOF( .data ):
+ {
+ bss_start = . ;
+ *(.bss)
+ *(COMMON)
+ end = . ;
+ _end = . ;
+
+ _HeapStart = .;
+ __HeapStart = .;
+ . += HeapSize; /* XXX -- Old gld can't handle this */
+ _HeapEnd = .;
+ __HeapEnd = .;
+ _StackStart = .;
+ __StackStart = .;
+ . += StackSize; /* XXX -- Old gld can't handle this */
+ /* . += 0x10000; */ /* HeapSize for old gld */
+ /* . += 0x1000; */ /* StackSize for old gld */
+ . = ALIGN (16);
+ _StackEnd = .;
+ __StackEnd = .;
+ stack_init = .;
+ clear_end = .;
+
+ _WorkspaceBase = .;
+ __WorkspaceBase = .;
+ } >ram
+}
diff --git a/c/src/lib/libbsp/m68k/mvme167/startup/page_table.c b/c/src/lib/libbsp/m68k/mvme167/startup/page_table.c
new file mode 100644
index 0000000000..5d44f3159b
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/startup/page_table.c
@@ -0,0 +1,139 @@
+/* page_table.c
+ *
+ * The code submitted by Eric Vaitl <vaitl@viasat.com> for the MVME162 appears
+ * to be for a uniprocessor implementation. The function that sets up the
+ * page tables, page_table_init(), is not data driven. For all processors, it
+ * sets up page tables to map virtual addresses from 0x20000 to 0x3FFFFF to
+ * physical addresses 0x20000 to 0x3FFFFF. This presumably maps a subset of
+ * a local 4 MB space, which is probably the amount of RAM on Eric Vailt's
+ * MVME162.
+ *
+ * It is possible to set up the various bus bridges in the MVME167s to create
+ * a flat physical address space across multiple boards, i.e., it is possible
+ * for each MVME167 in a multiprocessor system to access a given memory
+ * location using the same physical address, whether that location is in local
+ * or VME space. Addres translation can be set up so that each virtual address
+ * maps to its corresponding physical address, e.g. virtual address 0x12345678
+ * is mapped to physical address 0x12345678. With this mapping, the MMU is
+ * only used to control the caching modes for the various regions of memory.
+ * Mapping the virtual addresses to their corresponding physical address makes
+ * it unnecessary to map addresses under software control during the
+ * initialization of RTEMS, before address translation is turned on.
+ *
+ * With the above approach, address translation may be set up either with the
+ * transparent address translation registers, or with page tables. If page
+ * tables are used, a more efficient use of page table space can be achieved
+ * by sharing the page tables between processors. The entire page table tree
+ * can be shared, or each processor can hold a private copy of the top nodes
+ * which point to leaf nodes stored on individual processors.
+ *
+ * In this port, only the transparent address translation registers are used.
+ * We map the entire virtual range from 0x0 to 0x7FFFFFFF to the identical
+ * physical range 0x0 to 0x7FFFFFFF. We rely on the hardware to signal bus
+ * errors if we address non-existent memory within this range. Our two
+ * MVME167s are configured to exist at physical addresses 0x00800000 to
+ * 0x00BFFFFF and 0x00C00000 to 0x00FFFFFF respectively. We map the space
+ * from 0x0 to 0x7FFFFFFF as copyback, unless jumper J1-5 is removed, in
+ * which case we map as writethrough. If jumper J1-7 is removed, the data
+ * cache is NOT enabled. If jumper J1-6 is removed, the instruction cache
+ * is not enabled.
+ *
+ * Copyright (c) 1998, National Research Council of Canada
+ *
+ * $Id$
+ */
+
+#include <bsp.h>
+#include <page_table.h> /* Nothing in here for us */
+
+/*
+ * page_table_init
+ *
+ * Map the virtual range 0x00000000--0x7FFFFFFF to the physical range
+ * 0x00000000--0x7FFFFFFF. Rely on the hardware to raise exceptions when
+ * addressing non-existent memory. Use only the transparent translation
+ * registers (for now).
+ *
+ * On all processors, the local virtual address range 0xFF000000--0xFFFFFFFF
+ * is mapped to the physical address range 0xFF000000--0xFFFFFFFF as
+ * caching disabled, serialized access.
+ *
+ * Input parameters:
+ * config_table - ignored for now
+ *
+ * Output parameters: NONE
+ *
+ * Return values: NONE
+ */
+void page_table_init(
+ rtems_configuration_table *config_table
+)
+{
+ unsigned char j1; /* State of J1 jumpers */
+ register unsigned long dtt0; /* Content of dtt0 */
+ register unsigned long cacr; /* Content of cacr */
+
+ /*
+ * Logical base addr = 0x00 map starting at 0x00000000
+ * Logical address mask = 0x7F map up to 0x7FFFFFFF
+ * E = 0b1 enable address translation
+ * S-Field = 0b1X ignore FC2 when matching
+ * U1, U0 = 0b00 user page attributes not used
+ * CM = 0b01 cachable, writethrough
+ * W = 0b0 read/write access allowed
+ */
+ dtt0 = 0x007FC020;
+
+ cacr = 0x80008000; /* Data and instruction cache on */
+
+ /* Read the J1 header */
+ j1 = (unsigned char)(lcsr->vector_base & 0xFF);
+
+ if ( j1 & 0x80 )
+ /* Jumper J1-7 if off, disable data caching */
+ cacr &= 0x7FFFFFFF;
+
+ if ( j1 & 0x40 )
+ /* Jumper J1-6 if off, disable instruction caching */
+ cacr &= 0xFFFF7FFF;
+
+ if ( j1 & 0x20 )
+ /* Jumper J1-5 is off, enable writethrough caching */
+ dtt0 &= 0xFFFFFF9F;
+
+ /* do it ! */
+ asm volatile("movec %0, %%tc /* turn off paged address translation */
+ movec %0, %%cacr /* disable both caches */
+ cinva %%bc /* clear both caches */
+ movec %1,%%dtt0 /* block address translation on */
+ movec %1,%%itt0
+ movec %2,%%dtt1
+ movec %2,%%itt1
+ movec %3,%%cacr" /* data cache on */
+ :: "d" (0), "d" (dtt0), "d" (0xFF00C040), "d" (cacr));
+}
+
+
+/*
+ * page_table_teardown
+ *
+ * Turn off paging. Turn off the cache. Flush the cache. Tear down
+ * the transparent translations.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values: NONE
+ */
+void page_table_teardown( void )
+{
+ asm volatile ("movec %0,%%tc
+ movec %0,%%cacr
+ cpusha %%bc
+ movec %0,%%dtt0
+ movec %0,%%itt0
+ movec %0,%%dtt1
+ movec %0,%%itt1"
+ :: "d" (0) );
+}
diff --git a/c/src/lib/libbsp/m68k/mvme167/timer/Makefile.in b/c/src/lib/libbsp/m68k/mvme167/timer/Makefile.in
new file mode 100644
index 0000000000..24809cbed8
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/timer/Makefile.in
@@ -0,0 +1,59 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+VPATH = @srcdir@
+RTEMS_ROOT = @top_srcdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+PGM=${ARCH}/timer.rel
+
+# C source names, if any, go here -- minus the .c
+C_PIECES=timer
+C_FILES=$(C_PIECES:%=%.c)
+C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
+
+H_FILES=
+
+# Assembly source names, if any, go here -- minus the .s
+S_PIECES=timerisr
+S_FILES=$(S_PIECES:%=%.s)
+S_O_FILES=$(S_FILES:%.s=${ARCH}/%.o)
+
+SRCS=$(C_FILES) $(H_FILES) $(S_FILES)
+OBJS=$(C_O_FILES) $(S_O_FILES)
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+DEFINES +=
+CPPFLAGS +=
+CFLAGS +=
+
+LD_PATHS +=
+LD_LIBS +=
+LDFLAGS +=
+
+#
+# Add your list of files to delete here. The config files
+# already know how to delete some stuff, so you may want
+# to just run 'make clean' first to see what gets missed.
+# 'make clobber' already includes 'make clean'
+#
+
+CLEAN_ADDITIONS +=
+CLOBBER_ADDITIONS +=
+
+${PGM}: ${SRCS} ${OBJS}
+ $(make-rel)
+
+all: ${ARCH} $(SRCS) $(PGM)
+
+# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
+install: all
diff --git a/c/src/lib/libbsp/m68k/mvme167/timer/timer.c b/c/src/lib/libbsp/m68k/mvme167/timer/timer.c
new file mode 100644
index 0000000000..37cb269ae1
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/timer/timer.c
@@ -0,0 +1,153 @@
+/* timer.c
+ *
+ * This file manages the benchmark timer used by the RTEMS Timing Test Suite.
+ * Each measured time period is demarcated by calls to Timer_initialize() and
+ * Read_timer(). Read_timer() usually returns the number of microseconds
+ * since Timer_initialize() exitted.
+ *
+ * These functions are prototyped in rtems/c/src/lib/include/timerdrv.h and
+ * must be implemented as part of the BSP.
+ *
+ * This port does not allow the application to select which timer on the
+ * MVME167 to use for the timer, nor does it allow the application to
+ * configure the timer. The timer uses the VMEchip2 Tick Timer #1. This timer
+ * is distinct from the clock, which uses Tick Timer #2 in the VMEchip2.
+ *
+ * All page references are to the MVME166/MVME167/MVME187 Single Board
+ * Computer Programmer's Reference Guide (MVME187PG/D2) with the April 1993
+ * supplements/addenda (MVME187PG/D2A1).
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * Modifications of respective RTEMS file:
+ * Copyright (c) 1998, National Research Council of Canada
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <bsp.h>
+
+/* Periodic tick interval */
+#define TICK_INTERVAL 10000UL /* T1's countdown constant (10 ms) */
+#define TIMER_INT_LEVEL 6 /* T1's interrupt level */
+#define TIMER_VECTOR (VBR0 * 0x10 + 0x8) /* T1 is vector $X8 (p. 2-71)*/
+
+/* Number of interrupts since timer was re-initialized */
+rtems_unsigned32 Ttimer_val;
+
+/*
+ * Set to TRUE to return raw value. Normally zero. Depends on being allocated
+ * in the .bss section and on that section being explicitly zeroed at boot
+ * time.
+ */
+rtems_boolean Timer_driver_Find_average_overhead;
+
+rtems_isr timerisr();
+
+/*
+ * This routine initializes the Tick Timer 1 on the MVME167 board.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * NOTE: This routine may not work if the optimizer is enabled for some
+ * compilers. The multiple writes may be optimized away.
+ *
+ * It is important that the timer start/stop overhead be
+ * determined when porting or modifying this code.
+ *
+ * THE VMECHIP2 PRESCALER REGISTER IS ASSUMED TO BE SET!
+ * The prescaler is used by all VMEchip2 timers, including the VMEbus grant
+ * timeout counter, the DMAC time off timer, the DMAC timer on timer, and the
+ * VMEbus global timeout timer. The prescaler value is normally set by the
+ * boot ROM to provide a 1 MHz clock to the timers. For a 25 MHz MVME167, the
+ * prescaler value should be 0xE7 (page 2-63).
+ */
+void Timer_initialize()
+{
+ (void) set_vector( timerisr, TIMER_VECTOR, 0 );
+
+ Ttimer_val = 0; /* clear timer ISR count */
+ lcsr->intr_ena &= 0xFEFFFFFF; /* disable tick timer 1 interrupt */
+ lcsr->intr_clear |= 0x01000000; /* clear tick timer 1 interrupt */
+ lcsr->intr_level[0] = /* set int level */
+ (lcsr->intr_level[0] & 0xFFFFFFF0) | TIMER_INT_LEVEL;
+ lcsr->timer_cmp_1 = TICK_INTERVAL; /* period in compare register */
+ lcsr->timer_cnt_1 = 0; /* clear tick timer 1 counter */
+ lcsr->board_ctl |= 7; /* start tick timer 1, reset-on-compare, */
+ /* and clear overflow counter */
+
+ lcsr->intr_ena |= 0x01000000; /* enable tick timer 1 interrupt */
+ lcsr->vector_base |= MASK_INT; /* unmask VMEchip2 interrupts */
+}
+
+#define AVG_OVERHEAD 3UL /* It typically takes 3.0 microseconds */
+ /* (3 countdowns) to start/stop the timer. */
+#define LEAST_VALID 3UL /* Don't trust a value lower than this */
+
+
+/*
+ * This routine reads the Tick Timer 1 on the MVME167 board.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: time in microseconds
+ *
+ * AVG_OVEREHAD is the overhead for starting and stopping the timer. It
+ * is usually deducted from the number returned.
+ *
+ * LEAST_VALID is the lowest number this routine should trust. Numbers
+ * below this are "noise" and zero is returned.
+ */
+int Read_timer()
+{
+ rtems_unsigned32 total;
+
+ total = (Ttimer_val * TICK_INTERVAL) + lcsr->timer_cnt_1;
+
+ if ( Timer_driver_Find_average_overhead )
+ return total; /* in one microsecond units */
+
+ if ( total < LEAST_VALID )
+ return 0; /* below timer resolution */
+
+ return total - AVG_OVERHEAD;
+}
+
+
+/*
+ * Empty function call used in loops to measure basic cost of looping
+ * in Timing Test Suite.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: time in microseconds
+ */
+rtems_status_code Empty_function( void )
+{
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * This routine sets the Timer_driver_Find_average_overhead flag in this
+ * module.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: time in microseconds
+ */
+void Set_find_average_overhead(
+ rtems_boolean find_flag
+)
+{
+ Timer_driver_Find_average_overhead = find_flag;
+}
diff --git a/c/src/lib/libbsp/m68k/mvme167/timer/timerisr.s b/c/src/lib/libbsp/m68k/mvme167/timer/timerisr.s
new file mode 100644
index 0000000000..505e4b896a
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/timer/timerisr.s
@@ -0,0 +1,54 @@
+/* timer_isr()
+ *
+ * This ISR is used to bump a count of interval "overflow" interrupts which
+ * have occurred since the timer was started. The number of overflows is taken
+ * into account in the Read_timer() routine.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * Modifications of respective RTEMS file: COPYRIGHT (c) 1994.
+ * Copyright (c) 1998, National Research Council of Canada
+ *
+ * $Id$
+ */
+
+#include "asm.h"
+
+BEGIN_CODE
+
+.set INTR_CLEAR_REG, 0xfff40074 | interrupt clear register
+.set T1_CNTRL_REG, 0xfff40060 | tick timer 1 control register
+.set CLEAR_INT, 0x01000000 | clear tick 1 interrupt
+.set CLEAR_OVF, 0x00000004 | clear tick 1 overflow counter
+
+ PUBLIC (Ttimer_val)
+ PUBLIC (timerisr)
+SYM (timerisr):
+ move.l a0, -(a7) | save a0
+ move.l d0, -(a7) | save d0
+ move.w sr, -(a7) | save ccr
+ movea.l #INTR_CLEAR_REG, a0 | a0 = addr of intr clr reg
+ ori.l #CLEAR_INT, (a0) | clear tick timer 1 intr
+ movea.l #T1_CNTRL_REG, a0 | a0 = addr of t1 cntrl reg
+ move.l (a0), d0 | read overflow counter
+ lsr.l #4, d0 | put overflow in low order bits
+ andi.l #0xF, d0 | keep only overflow
+ add.l d0, SYM (Ttimer_val) | increment timer value
+ ori.l #CLEAR_OVF, (a0) | clear overflow counter
+ move.w (a7)+, sr | restore ccr
+ move.l (a7)+, d0 | restore d0
+ move.l (a7)+, a0 | restore a0
+ rte
+
+END_CODE
+END
diff --git a/c/src/lib/libbsp/m68k/mvme167/wrapup/Makefile.in b/c/src/lib/libbsp/m68k/mvme167/wrapup/Makefile.in
new file mode 100644
index 0000000000..0521903b9e
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme167/wrapup/Makefile.in
@@ -0,0 +1,49 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+VPATH = @srcdir@
+RTEMS_ROOT = @top_srcdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+BSP_PIECES=clock console fatal startup timer
+GENERIC_PIECES=
+
+# bummer; have to use $foreach since % pattern subst rules only replace 1x
+OBJS=$(foreach piece, $(BSP_PIECES), ../$(piece)/$(ARCH)/$(piece).rel) \
+ $(foreach piece, $(GENERIC_PIECES), ../../../$(piece)/$(ARCH)/$(piece).rel)
+LIB=$(ARCH)/libbsp.a
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/lib.cfg
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+DEFINES +=
+CPPFLAGS +=
+CFLAGS +=
+
+LD_PATHS +=
+LD_LIBS +=
+LDFLAGS +=
+
+#
+# Add your list of files to delete here. The config files
+# already know how to delete some stuff, so you may want
+# to just run 'make clean' first to see what gets missed.
+# 'make clobber' already includes 'make clean'
+#
+
+CLEAN_ADDITIONS +=
+CLOBBER_ADDITIONS +=
+
+$(LIB): ${OBJS}
+ $(make-library)
+
+all: ${ARCH} $(SRCS) $(LIB)
+ $(INSTALL_VARIANT) -m 644 $(LIB) ${PROJECT_RELEASE}/lib
+
diff --git a/make/custom/mvme167.cfg b/make/custom/mvme167.cfg
new file mode 100644
index 0000000000..616dab8a83
--- /dev/null
+++ b/make/custom/mvme167.cfg
@@ -0,0 +1,74 @@
+#
+# Config file for the mvme167 BSP
+#
+# $Id$
+#
+
+include $(RTEMS_ROOT)/make/custom/default.cfg
+
+RTEMS_CPU=m68k
+RTEMS_CPU_MODEL=m68040
+
+# This is the actual bsp directory used during the build process.
+RTEMS_BSP_FAMILY=mvme167
+
+#
+# This contains the compiler options necessary to select the CPU model
+# and (hopefully) optimize for it.
+#
+
+CPU_CFLAGS = -m68040
+
+# optimize flag: typically -O, could use -O4 or -fast
+# -O4 is ok for RTEMS
+CFLAGS_OPTIMIZE_V=-O4 -fomit-frame-pointer
+
+# This target does NOT support the TCP/IP stack so ignore requests
+# to enable it.
+HAS_NETWORKING=no
+
+# This section makes the target dependent options file.
+# NDEBUG (C library)
+# if defined asserts do not generate code. This is commonly used
+# as a command line option.
+#
+# RTEMS_TEST_NO_PAUSE (RTEMS tests)
+# do not pause between screens of output in the rtems tests
+#
+# RTEMS_DEBUG (RTEMS)
+# If defined, debug checks in RTEMS and support library code are enabled.
+
+define make-target-options
+ @echo "/* #define NDEBUG 1 */ " >>$@
+ @echo "#define RTEMS_TEST_NO_PAUSE 1" >>$@
+ @echo "/* #define RTEMS_DEBUG 1 */" >>$@
+endef
+
+# Here is the rule to actually build a $(ARCH)/foo.exe
+# It also builds $(ARCH)/foo.nm
+# Usage ref: src/tests/sptest/sp1/Makefile
+#
+# We use TFTP to transfer files to the MVME167. We generate binary files
+# rather than S-records. We skip the header during downloads.
+
+# The following are definitions of make-exe which will work using ld as
+# is currently required. It is expected that as of gcc 2.8, the end user
+# will be able to override parts of the compilers specs and link using gcc.
+
+ifeq ($(RTEMS_USE_GCC272),yes)
+define make-exe
+ $(LD) $(LDFLAGS) -N -T $(LINKCMDS) -o $(basename $@).exe \
+ $(START_FILE) $(LINK_OBJS) --start-group $(LINK_LIBS) --end-group
+ $(NM) -g -n $(basename $@).exe > $(basename $@).nm
+ $(SIZE) $(basename $@).exe
+endef
+else
+define make-exe
+ $(CC) $(CFLAGS) $(CFLAGS_LD) -o $(basename $@).exe \
+ $(LINK_OBJS) $(LINK_LIBS)
+ $(NM) -g -n $(basename $@).exe > $(basename $@).nm
+ $(SIZE) $(basename $@).exe
+endef
+endif
+
+# Miscellaneous additions go here