From 5d024595a7cbb8a04fad883fd89b42d61d72acf7 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Thu, 18 Feb 1999 19:23:28 +0000 Subject: MVME167 BSP submitted by Charles Gauthier . --- c/src/lib/libbsp/m68k/mvme167/Makefile.in | 18 + c/src/lib/libbsp/m68k/mvme167/README | 395 ++++++ c/src/lib/libbsp/m68k/mvme167/bsp_specs | 23 + c/src/lib/libbsp/m68k/mvme167/clock/Makefile.in | 54 + c/src/lib/libbsp/m68k/mvme167/clock/ckinit.c | 281 +++++ c/src/lib/libbsp/m68k/mvme167/console/Makefile.in | 54 + c/src/lib/libbsp/m68k/mvme167/console/console.c | 1297 ++++++++++++++++++++ c/src/lib/libbsp/m68k/mvme167/fatal/Makefile.in | 54 + c/src/lib/libbsp/m68k/mvme167/fatal/bspfatal.c | 127 ++ c/src/lib/libbsp/m68k/mvme167/fatal/fatal.c | 127 ++ c/src/lib/libbsp/m68k/mvme167/include/Makefile.in | 34 + c/src/lib/libbsp/m68k/mvme167/include/bsp.h | 478 ++++++++ c/src/lib/libbsp/m68k/mvme167/include/coverhd.h | 104 ++ c/src/lib/libbsp/m68k/mvme167/include/fatal.h | 19 + c/src/lib/libbsp/m68k/mvme167/include/page_table.h | 46 + c/src/lib/libbsp/m68k/mvme167/startup/Makefile.in | 53 + c/src/lib/libbsp/m68k/mvme167/startup/bspclean.c | 81 ++ c/src/lib/libbsp/m68k/mvme167/startup/bspstart.c | 201 +++ c/src/lib/libbsp/m68k/mvme167/startup/linkcmds | 103 ++ c/src/lib/libbsp/m68k/mvme167/startup/page_table.c | 139 +++ c/src/lib/libbsp/m68k/mvme167/timer/Makefile.in | 59 + c/src/lib/libbsp/m68k/mvme167/timer/timer.c | 153 +++ c/src/lib/libbsp/m68k/mvme167/timer/timerisr.s | 54 + c/src/lib/libbsp/m68k/mvme167/wrapup/Makefile.in | 49 + make/custom/mvme167.cfg | 74 ++ 25 files changed, 4077 insertions(+) create mode 100644 c/src/lib/libbsp/m68k/mvme167/Makefile.in create mode 100644 c/src/lib/libbsp/m68k/mvme167/README create mode 100644 c/src/lib/libbsp/m68k/mvme167/bsp_specs create mode 100644 c/src/lib/libbsp/m68k/mvme167/clock/Makefile.in create mode 100644 c/src/lib/libbsp/m68k/mvme167/clock/ckinit.c create mode 100644 c/src/lib/libbsp/m68k/mvme167/console/Makefile.in create mode 100644 c/src/lib/libbsp/m68k/mvme167/console/console.c create mode 100644 c/src/lib/libbsp/m68k/mvme167/fatal/Makefile.in create mode 100644 c/src/lib/libbsp/m68k/mvme167/fatal/bspfatal.c create mode 100644 c/src/lib/libbsp/m68k/mvme167/fatal/fatal.c create mode 100644 c/src/lib/libbsp/m68k/mvme167/include/Makefile.in create mode 100644 c/src/lib/libbsp/m68k/mvme167/include/bsp.h create mode 100644 c/src/lib/libbsp/m68k/mvme167/include/coverhd.h create mode 100644 c/src/lib/libbsp/m68k/mvme167/include/fatal.h create mode 100644 c/src/lib/libbsp/m68k/mvme167/include/page_table.h create mode 100644 c/src/lib/libbsp/m68k/mvme167/startup/Makefile.in create mode 100644 c/src/lib/libbsp/m68k/mvme167/startup/bspclean.c create mode 100644 c/src/lib/libbsp/m68k/mvme167/startup/bspstart.c create mode 100644 c/src/lib/libbsp/m68k/mvme167/startup/linkcmds create mode 100644 c/src/lib/libbsp/m68k/mvme167/startup/page_table.c create mode 100644 c/src/lib/libbsp/m68k/mvme167/timer/Makefile.in create mode 100644 c/src/lib/libbsp/m68k/mvme167/timer/timer.c create mode 100644 c/src/lib/libbsp/m68k/mvme167/timer/timerisr.s create mode 100644 c/src/lib/libbsp/m68k/mvme167/wrapup/Makefile.in create mode 100644 make/custom/mvme167.cfg 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 +#include +#include + +#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 +#include /* Must be before libio.h */ +#include + +#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 */ + 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 +#include + +/* + * 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 +#include + +/* + * 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 +#include +#include +#include + + +/* + * 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 +#include + +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 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 + +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 +#include +#include + +/* + * 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 +#include +#include +#include + +#include + +#include + + +/* + * The original table from the application (in ROM) and our copy of it with + * some changes. Configuration is defined in . 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 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 +#include /* 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 +#include + +/* 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 -- cgit v1.2.3