From 5edbffe3f64131c582839e0bbd389fda5eeb407c Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Mon, 22 Oct 2001 14:46:02 +0000 Subject: 01-10-22 Andy Dachs * mpc8260ads added as new BSP. tm27 reported not to run at this time. * ChangeLog, Makefile.am, README, aclocal.m4, bsp_specs, clock/.cvsignore, clock/Makefile.am, clock/p_clock.c, configure.in, console/Makefile.am, console/console.c, include/Makefile.am, include/bsp.h, include/coverhd.h, irq/.cvsignore, irq/Makefile.am, irq/irq.c, irq/irq.h, irq/irq_asm.S, irq/irq_init.c, network/Makefile.am, network/README, network/if_hdlcsubr.c, network/if_hdlcsubr.h, network/network.c, start/Makefile.am, start/start.S, startup/Makefile.am, startup/bspstart.c, startup/cpuinit.c, startup/linkcmds, startup/setvec.c, times, vectors/.cvsignore, vectors/Makefile.am, vectors/vectors.S, vectors/vectors.h, vectors/vectors_init.c, wrapup/Makefile.am: New files. --- c/src/lib/libbsp/powerpc/mpc8260ads/ChangeLog | 17 + c/src/lib/libbsp/powerpc/mpc8260ads/Makefile.am | 17 + c/src/lib/libbsp/powerpc/mpc8260ads/README | 337 +++++++ c/src/lib/libbsp/powerpc/mpc8260ads/aclocal.m4 | 1041 ++++++++++++++++++++ c/src/lib/libbsp/powerpc/mpc8260ads/bsp_specs | 26 + .../lib/libbsp/powerpc/mpc8260ads/clock/.cvsignore | 2 + .../libbsp/powerpc/mpc8260ads/clock/Makefile.am | 26 + .../lib/libbsp/powerpc/mpc8260ads/clock/p_clock.c | 71 ++ .../libbsp/powerpc/mpc8260ads/console/Makefile.am | 33 + .../libbsp/powerpc/mpc8260ads/console/console.c | 478 +++++++++ .../libbsp/powerpc/mpc8260ads/include/Makefile.am | 31 + c/src/lib/libbsp/powerpc/mpc8260ads/include/bsp.h | 157 +++ .../libbsp/powerpc/mpc8260ads/include/coverhd.h | 114 +++ c/src/lib/libbsp/powerpc/mpc8260ads/irq/.cvsignore | 2 + .../lib/libbsp/powerpc/mpc8260ads/irq/Makefile.am | 46 + c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq.c | 453 +++++++++ c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq.h | 347 +++++++ c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq_asm.S | 339 +++++++ c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq_init.c | 150 +++ .../libbsp/powerpc/mpc8260ads/network/Makefile.am | 37 + c/src/lib/libbsp/powerpc/mpc8260ads/network/README | 55 ++ .../powerpc/mpc8260ads/network/if_hdlcsubr.c | 346 +++++++ .../powerpc/mpc8260ads/network/if_hdlcsubr.h | 40 + .../libbsp/powerpc/mpc8260ads/network/network.c | 1016 +++++++++++++++++++ .../libbsp/powerpc/mpc8260ads/start/Makefile.am | 33 + c/src/lib/libbsp/powerpc/mpc8260ads/start/start.S | 191 ++++ .../libbsp/powerpc/mpc8260ads/startup/Makefile.am | 43 + .../libbsp/powerpc/mpc8260ads/startup/bspstart.c | 370 +++++++ .../libbsp/powerpc/mpc8260ads/startup/cpuinit.c | 51 + .../lib/libbsp/powerpc/mpc8260ads/startup/linkcmds | 285 ++++++ .../lib/libbsp/powerpc/mpc8260ads/startup/setvec.c | 43 + c/src/lib/libbsp/powerpc/mpc8260ads/times | 196 ++++ .../libbsp/powerpc/mpc8260ads/vectors/.cvsignore | 2 + .../libbsp/powerpc/mpc8260ads/vectors/Makefile.am | 40 + .../libbsp/powerpc/mpc8260ads/vectors/vectors.S | 145 +++ .../libbsp/powerpc/mpc8260ads/vectors/vectors.h | 144 +++ .../powerpc/mpc8260ads/vectors/vectors_init.c | 151 +++ .../libbsp/powerpc/mpc8260ads/wrapup/Makefile.am | 44 + 38 files changed, 6919 insertions(+) create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/ChangeLog create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/Makefile.am create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/README create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/aclocal.m4 create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/bsp_specs create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/clock/.cvsignore create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/clock/Makefile.am create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/clock/p_clock.c create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/console/Makefile.am create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/console/console.c create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/include/Makefile.am create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/include/bsp.h create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/include/coverhd.h create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/irq/.cvsignore create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/irq/Makefile.am create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq.c create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq.h create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq_asm.S create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq_init.c create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/network/Makefile.am create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/network/README create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/network/if_hdlcsubr.c create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/network/if_hdlcsubr.h create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/network/network.c create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/start/Makefile.am create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/start/start.S create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/startup/Makefile.am create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/startup/bspstart.c create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/startup/cpuinit.c create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/startup/linkcmds create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/startup/setvec.c create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/times create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/vectors/.cvsignore create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/vectors/Makefile.am create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/vectors/vectors.S create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/vectors/vectors.h create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/vectors/vectors_init.c create mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/wrapup/Makefile.am diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/ChangeLog b/c/src/lib/libbsp/powerpc/mpc8260ads/ChangeLog new file mode 100644 index 0000000000..fcf604f372 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/ChangeLog @@ -0,0 +1,17 @@ +01-10-22 Andy Dachs + + * mpc8260ads added as new BSP. tm27 reported not to run + at this time. + * ChangeLog, Makefile.am, README, aclocal.m4, bsp_specs, + clock/.cvsignore, clock/Makefile.am, clock/p_clock.c, configure.in, + console/Makefile.am, console/console.c, include/Makefile.am, + include/bsp.h, include/coverhd.h, irq/.cvsignore, irq/Makefile.am, + irq/irq.c, irq/irq.h, irq/irq_asm.S, irq/irq_init.c, + network/Makefile.am, network/README, network/if_hdlcsubr.c, + network/if_hdlcsubr.h, network/network.c, start/Makefile.am, + start/start.S, startup/Makefile.am, startup/bspstart.c, + startup/cpuinit.c, startup/linkcmds, startup/setvec.c, times, + vectors/.cvsignore, vectors/Makefile.am, vectors/vectors.S, + vectors/vectors.h, vectors/vectors_init.c, wrapup/Makefile.am: + New files. + diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/Makefile.am b/c/src/lib/libbsp/powerpc/mpc8260ads/Makefile.am new file mode 100644 index 0000000000..f4d4d10dd0 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/Makefile.am @@ -0,0 +1,17 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 +ACLOCAL_AMFLAGS = -I ../../../../../../aclocal + +# wrapup is the one that actually builds and installs the library +# from the individual .rel files built in other directories +SUBDIRS = clock console include vectors irq network start startup wrapup + +include $(top_srcdir)/../../bsp.am + +EXTRA_DIST = README bsp_specs times + +include $(top_srcdir)/../../../../../../automake/subdirs.am +include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/README b/c/src/lib/libbsp/powerpc/mpc8260ads/README new file mode 100644 index 0000000000..8fb1cf8271 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/README @@ -0,0 +1,337 @@ +# +# $Id$ +# + +BSP NAME: mpc8260ads +BOARD: Motorola MPC8260 ADS Evaluation board +BUS: N/A +CPU FAMILY: ppc +CPU: PowerPC MPC8260 +COPROCESSORS: Hardware FPU (except on revision 2J24M) +MODE: 32 bit mode, I and D cache disabled +DEBUG MONITOR: None + +PERIPHERALS +=========== +TIMERS: Decrementer +RESOLUTION: 0.1 microsecond +SERIAL PORTS: 4 SCCs (SSC1 and 2 are connectd to RS232 drivers) + SCC3 is used in HDLC mode to transport IP frames. + SMCs, FCCs, SPI, I2C are unused. +REAL-TIME CLOCK: +DMA: Each serial port +VIDEO: none +SCSI: none +NETWORKING: IP over HDLC (8 Mbps) on SCC3 (MPC8260) + +DRIVER INFORMATION +================== +CLOCK DRIVER: Decrementer +IOSUPP DRIVER: SCC1, SCC2 +SHMSUPP: none +TIMER DRIVER: Timebase register (lower 32 bits only) + +STDIO +===== +PORT: SCC2 +ELECTRICAL: RS-232 +BAUD: 9600 +BITS PER CHARACTER: 8 +PARITY: None +STOP BITS: 1 + +NOTES +===== +On-chip resources: + SCC1 console + SCC2 console + SCC3 network + SCC4 + CLK1 + CLK2 + CLK3 + CLK4 + CLK5 network + CLK6 + CLK7 + CLK8 + BRG1 console + BRG2 console + BRG3 console + BRG4 network + RTC + PIT + TB timer + DEC clock + SWT + *CS0 8M FLASH + *CS1 Config registers + *CS2 60X SDRAM + *CS3 + *CS4 LCL SDRAM + *CS5 ATM + *CS6 + *CS7 + *CS8 + *CS9 + *CS10 + *CS11 + UPMA + UPMB + IRQ0 + IRQ1 + IRQ2 + IRQ3 + IRQ4 + IRQ5 + IRQ6 + IRQ7 + + +Board description +----------------- + +Clock rate: 40MHz (board can run up 66MHz with alternate OSC) +Bus width: 32 bit Flash, 64 bit SDRAM +FLASH: 8M SIMM +RAM: 16M SDRAM DIMM + +The board is marked with "Rev PILOT" +U17 is marked with "MPC8260ADS Pilot 00" +The processor is marked with "XPC8260ZU166 166/133/66 MHz" + + +Board Configuration: +-------------------- + +The evaluation board has a number of configurable options: + +DIP switch settings used: +DS1: 1-"off", 2-"on", 3-"off", 4-"on", 5-"off", 6-"off", 7-"off", 8-"off" +DS2: all "on" +DS3: all "on" + +A 40MHz oscillator is fitted to U16. + + +Board Connections: +------------------ + +Connect a serial terminal to PA3 (SCC2) configured for 9600,n,8,1 to +get console I/O. A 9way male-female straight-through cable is required to +connect to a PC. + +If you require the network connections (see README in network directory) +you need to connect 3VTTL - RS422 level convertors to the CPM expansion +connector, P4. The signals, as numbered on the connector itself +(beware: the numbering on the PCB does not agree): + +TX Data (SCC3 TXD) (output) Pin a25 +TX Clock (BRG4O) (output) Pin a11 +Rx Data (SCC3 RXD) (input) Pin c15 +Rx Clock (CLK5) (input) Pin d28 +Ground (GND) (n/a) Pin c1 + + +Debugging/ Code loading: +------------------------ + +Tested using the Metrowerks debugger and Macraigor OCDemon (Raven). +The OCD connects via the parallel port and allows you to download code +to the board. It may be possible to use some other debugger if you +don't already have Metrowerks CodeWarrior. + + + +Verification +------------------------------- + +*** TESTING IN PROGRESS - DO NOT BELIEVE THESE RESULTS *** + +Single processor tests: Passed +Multi-processort tests: not applicable +Timing tests: + Context Switch + + context switch: self 9 + context switch: to another task 10 + context switch: no floating point contexts 23 + fp context switch: restore 1st FP task 24 + fp context switch: save initialized, restore initialized 11 + fp context switch: save idle, restore initialized 11 + fp context switch: save idle, restore idle 23 + + Task Manager + + rtems_task_create 83 + rtems_task_ident 84 + rtems_task_start 30 + rtems_task_restart: calling task 48 + rtems_task_restart: suspended task -- returns to caller 36 + rtems_task_restart: blocked task -- returns to caller 47 + rtems_task_restart: ready task -- returns to caller 35 + rtems_task_restart: suspended task -- preempts caller 56 + rtems_task_restart: blocked task -- preempts caller 116 + rtems_task_restart: ready task -- preempts caller 93 + rtems_task_delete: calling task 102 + rtems_task_delete: suspended task 74 + rtems_task_delete: blocked task 76 + rtems_task_delete: ready task 80 + rtems_task_suspend: calling task 37 + rtems_task_suspend: returns to caller 14 + rtems_task_resume: task readied -- returns to caller 16 + rtems_task_resume: task readied -- preempts caller 30 + rtems_task_set_priority: obtain current priority 12 + rtems_task_set_priority: returns to caller 23 + rtems_task_set_priority: preempts caller 52 + rtems_task_mode: obtain current mode 5 + rtems_task_mode: no reschedule 6 + rtems_task_mode: reschedule -- returns to caller 15 + rtems_task_mode: reschedule -- preempts caller 43 + rtems_task_get_note 13 + rtems_task_set_note 12 + rtems_task_wake_after: yield -- returns to caller 8 + rtems_task_wake_after: yields -- preempts caller 30 + rtems_task_wake_when: 49 + + Interrupt Manager + + interrupt entry overhead: returns to nested interrupt 7 + interrupt entry overhead: returns to interrupted task 31 + interrupt entry overhead: returns to preempting task 14 + interrupt exit overhead: returns to nested interrupt 10 + interrupt exit overhead: returns to interrupted task 8 + interrupt exit overhead: returns to preempting task 45 + + Clock Manager + + rtems_clock_set 28 + rtems_clock_get 0 + rtems_clock_tick 36 + + Timer Manager + + rtems_timer_create 11 + rtems_timer_ident 82 + rtems_timer_delete: inactive 14 + rtems_timer_delete: active 16 + rtems_timer_fire_after: inactive 20 + rtems_timer_fire_after: active 22 + rtems_timer_fire_when: inactive 24 + rtems_timer_fire_when: active 24 + rtems_timer_reset: inactive 18 + rtems_timer_reset: active 21 + rtems_timer_cancel: inactive 11 + rtems_timer_cancel: active 12 + + Semaphore Manager + + rtems_semaphore_create 56 + rtems_semaphore_ident 94 + rtems_semaphore_delete 34 + rtems_semaphore_obtain: available 13 + rtems_semaphore_obtain: not available -- NO_WAIT 13 + rtems_semaphore_obtain: not available -- caller blocks 48 + rtems_semaphore_release: no waiting tasks 16 + rtems_semaphore_release: task readied -- returns to caller 36 + rtems_semaphore_release: task readied -- preempts caller 36 + + Message Queue Manager + + rtems_message_queue_create 110 + rtems_message_queue_ident 82 + rtems_message_queue_delete 43 + rtems_message_queue_send: no waiting tasks 28 + rtems_message_queue_send: task readied -- returns to caller 31 + rtems_message_queue_send: task readied -- preempts caller 46 + rtems_message_queue_urgent: no waiting tasks 28 + rtems_message_queue_urgent: task readied -- returns to caller 31 + rtems_message_queue_urgent: task readied -- preempts caller 46 + rtems_message_queue_broadcast: no waiting tasks 22 + rtems_message_queue_broadcast: task readied -- returns to caller 81 + rtems_message_queue_broadcast: task readied -- preempts caller 75 + rtems_message_queue_receive: available 26 + rtems_message_queue_receive: not available -- NO_WAIT 15 + rtems_message_queue_receive: not available -- caller blocks 48 + rtems_message_queue_flush: no messages flushed 14 + rtems_message_queue_flush: messages flushed 14 + + Event Manager + + rtems_event_send: no task readied 12 + rtems_event_send: task readied -- returns to caller 38 + rtems_event_send: task readied -- preempts caller 21 + rtems_event_receive: obtain current events 1 + rtems_event_receive: available 19 + rtems_event_receive: not available -- NO_WAIT 11 + rtems_event_receive: not available -- caller blocks 36 + + Signal Manager + + rtems_signal_catch: 31 + rtems_signal_send: returns to caller 21 + rtems_signal_send: signal to self 39 + exit ASR overhead: returns to calling task 30 + exit ASR overhead: returns to preempting task 33 + + Partition Manager + + rtems_partition_create 59 + rtems_partition_ident 82 + rtems_partition_delete 20 + rtems_partition_get_buffer: available 19 + rtems_partition_get_buffer: not available 13 + rtems_partition_return_buffer 20 + + Region Manager + + rtems_region_create 37 + rtems_region_ident 84 + rtems_region_delete 20 + rtems_region_get_segment: available 19 + rtems_region_get_segment: not available -- NO_WAIT 23 + rtems_region_get_segment: not available -- caller blocks 75 + rtems_region_return_segment: no waiting tasks 21 + rtems_region_return_segment: task readied -- returns to caller 55 + rtems_region_return_segment: task readied -- preempts caller 82 + + Dual-Ported Memory Manager + + rtems_port_create 23 + rtems_port_ident 82 + rtems_port_delete 21 + rtems_port_internal_to_external 10 + rtems_port_external_to_internal 11 + + 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 43 + rtems_rate_monotonic_ident 82 + rtems_rate_monotonic_cancel 23 + rtems_rate_monotonic_delete: active 28 + rtems_rate_monotonic_delete: inactive 25 + rtems_rate_monotonic_period: obtain status 17 + rtems_rate_monotonic_period: initiate period -- returns to caller 32 + rtems_rate_monotonic_period: conclude periods -- caller blocks 30 + +Network tests: + TCP throughput (as measured by ttcp): + Receive: 1324 kbytes/sec + Transmit: 1037 kbytes/sec + + + + + + + + diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/aclocal.m4 b/c/src/lib/libbsp/powerpc/mpc8260ads/aclocal.m4 new file mode 100644 index 0000000000..bee4d5b3a9 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/aclocal.m4 @@ -0,0 +1,1041 @@ +# aclocal.m4 generated automatically by aclocal 1.5 + +# Copyright 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +dnl $Id$ + +dnl +dnl RTEMS_TOP($1) +dnl +dnl $1 .. relative path from this configure.in to the toplevel configure.in +dnl +AC_DEFUN(RTEMS_TOP, +[dnl +AC_CHECK_PROGS(MAKE, gmake make) +AC_BEFORE([$0], [AC_CONFIG_AUX_DIR])dnl +AC_BEFORE([$0], [AM_INIT_AUTOMAKE])dnl + +AC_PREFIX_DEFAULT([/opt/rtems]) + +ENDIF=endif +AC_SUBST(ENDIF) + +RTEMS_TOPdir="$1"; +AC_SUBST(RTEMS_TOPdir) + +test -n "$with_target_subdir" || with_target_subdir="." + +if test "$with_target_subdir" = "." ; then +# Native +PROJECT_TOPdir=${RTEMS_TOPdir}/'$(top_builddir)' +else +# Cross +dots=`echo $with_target_subdir|\ +sed -e 's%^\./%%' -e 's%[[^/]]$%&/%' -e 's%[[^/]]*/%../%g'` +PROJECT_TOPdir=${dots}${RTEMS_TOPdir}/'$(top_builddir)' +fi +AC_SUBST(PROJECT_TOPdir) + +if test "$with_target_subdir" = "." ; then +# Native +PROJECT_ROOT=${RTEMS_TOPdir}/'$(top_builddir)'; +else +# Cross +PROJECT_ROOT=${RTEMS_TOPdir}/'$(top_builddir)' +fi +AC_SUBST(PROJECT_ROOT) + +dnl Determine RTEMS Version string from the VERSION file +dnl Hopefully, Joel never changes its format ;- +AC_MSG_CHECKING([for RTEMS Version]) +if test -r "${srcdir}/${RTEMS_TOPdir}/VERSION"; then +RTEMS_VERSION=`grep 'RTEMS Version' ${srcdir}/${RTEMS_TOPdir}/VERSION | \ +sed -e 's%RTEMS[[ ]]*Version[[ ]]*\(.*\)[[ ]]*%\1%g'` +else +AC_MSG_ERROR(Unable to find ${RTEMS_TOPdir}/VERSION) +fi +if test -z "$RTEMS_VERSION"; then +AC_MSG_ERROR(Unable to determine version) +fi +AC_MSG_RESULT($RTEMS_VERSION) +])dnl + +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 5 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# We require 2.13 because we rely on SHELL being computed by configure. +AC_PREREQ([2.13]) + +# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) +# ----------------------------------------------------------- +# If MACRO-NAME is provided do IF-PROVIDED, else IF-NOT-PROVIDED. +# The purpose of this macro is to provide the user with a means to +# check macros which are provided without letting her know how the +# information is coded. +# If this macro is not defined by Autoconf, define it here. +ifdef([AC_PROVIDE_IFELSE], + [], + [define([AC_PROVIDE_IFELSE], + [ifdef([AC_PROVIDE_$1], + [$2], [$3])])]) + + +# AM_INIT_AUTOMAKE(PACKAGE,VERSION, [NO-DEFINE]) +# ---------------------------------------------- +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_REQUIRE([AC_PROG_INSTALL])dnl +# test to see if srcdir already configured +if test "`CDPATH=:; cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run \"make distclean\" there first]) +fi + +# Define the identity of the package. +PACKAGE=$1 +AC_SUBST(PACKAGE)dnl +VERSION=$2 +AC_SUBST(VERSION)dnl +ifelse([$3],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])]) + +# Autoconf 2.50 wants to disallow AM_ names. We explicitly allow +# the ones we care about. +ifdef([m4_pattern_allow], + [m4_pattern_allow([^AM_[A-Z]+FLAGS])])dnl + +# Autoconf 2.50 always computes EXEEXT. However we need to be +# compatible with 2.13, for now. So we always define EXEEXT, but we +# don't compute it. +AC_SUBST(EXEEXT) +# Similar for OBJEXT -- only we only use OBJEXT if the user actually +# requests that it be used. This is a bit dumb. +: ${OBJEXT=o} +AC_SUBST(OBJEXT) + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AM_MISSING_PROG(AMTAR, tar) +AM_PROG_INSTALL_SH +AM_PROG_INSTALL_STRIP +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl +AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_PROVIDE_IFELSE([AC_PROG_][CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_][CC], + defn([AC_PROG_][CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_][CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_][CXX], + defn([AC_PROG_][CXX])[_AM_DEPENDENCIES(CXX)])])dnl +]) + +# +# Check to make sure that the build environment is sane. +# + +# serial 3 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + + +# serial 2 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + am_backtick='`' + AC_MSG_WARN([${am_backtick}missing' script is too old or missing]) +fi +]) + +# AM_AUX_DIR_EXPAND + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], [ +# expand $ac_aux_dir to an absolute path +am_aux_dir=`CDPATH=:; cd $ac_aux_dir && pwd` +]) + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +install_sh=${install_sh-"$am_aux_dir/install-sh"} +AC_SUBST(install_sh)]) + +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# serial 4 -*- Autoconf -*- + + + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + + +# _AM_DEPENDENCIES(NAME) +# --------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX" or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'] + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + for depmode in $am_compiler_list; do + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + echo '#include "conftest.h"' > conftest.c + echo 'int i;' > conftest.h + echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=conftest.c object=conftest.o \ + depfile=conftest.Po tmpdepfile=conftest.TPo \ + $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 && + grep conftest.h conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +$1DEPMODE="depmode=$am_cv_$1_dependencies_compiler_type" +AC_SUBST([$1DEPMODE]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[rm -f .deps 2>/dev/null +mkdir .deps 2>/dev/null +if test -d .deps; then + DEPDIR=.deps +else + # MS-DOS does not allow filenames that begin with a dot. + DEPDIR=_deps +fi +rmdir .deps 2>/dev/null +AC_SUBST(DEPDIR) +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking Speeds up one-time builds + --enable-dependency-tracking Do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +pushdef([subst], defn([AC_SUBST])) +subst(AMDEPBACKSLASH) +popdef([subst]) +]) + +# Generate code to set up dependency tracking. +# This macro should only be invoked once -- use via AC_REQUIRE. +# Usage: +# AM_OUTPUT_DEPENDENCY_COMMANDS + +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],[ +AC_OUTPUT_COMMANDS([ +test x"$AMDEP_TRUE" != x"" || +for mf in $CONFIG_FILES; do + case "$mf" in + Makefile) dirpart=.;; + */Makefile) dirpart=`echo "$mf" | sed -e 's|/[^/]*$||'`;; + *) continue;; + esac + grep '^DEP_FILES *= *[^ #]' < "$mf" > /dev/null || continue + # Extract the definition of DEP_FILES from the Makefile without + # running `make'. + DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"` + test -z "$DEPDIR" && continue + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n -e '/^U = / s///p' < "$mf"` + test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" + # We invoke sed twice because it is the simplest approach to + # changing $(DEPDIR) to its actual value in the expansion. + for file in `sed -n -e ' + /^DEP_FILES = .*\\\\$/ { + s/^DEP_FILES = // + :loop + s/\\\\$// + p + n + /\\\\$/ b loop + p + } + /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`echo "$file" | sed -e 's|/[^/]*$||'` + $ac_aux_dir/mkinstalldirs "$dirpart/$fdir" > /dev/null 2>&1 + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done +], [AMDEP_TRUE="$AMDEP_TRUE" +ac_aux_dir="$ac_aux_dir"])]) + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +doit: + @echo done +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include='#' +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | fgrep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote='"' + _am_result=BSD + fi +fi +AC_SUBST(am__include) +AC_SUBST(am__quote) +AC_MSG_RESULT($_am_result) +rm -f confinc confmf +]) + +# serial 3 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +# +# FIXME: Once using 2.50, use this: +# m4_match([$1], [^TRUE\|FALSE$], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_DEFUN([AM_CONDITIONAL], +[ifelse([$1], [TRUE], + [errprint(__file__:__line__: [$0: invalid condition: $1 +])dnl +m4exit(1)])dnl +ifelse([$1], [FALSE], + [errprint(__file__:__line__: [$0: invalid condition: $1 +])dnl +m4exit(1)])dnl +AC_SUBST([$1_TRUE]) +AC_SUBST([$1_FALSE]) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi]) + +dnl +dnl $Id$ +dnl + +dnl canonicalize target cpu +dnl NOTE: Most rtems targets do not fullfil autoconf's +dnl target naming conventions "processor-vendor-os" +dnl Therefore autoconf's AC_CANONICAL_TARGET will fail for them +dnl and we have to fix it for rtems ourselves + +AC_DEFUN(RTEMS_CANONICAL_TARGET_CPU, +[ +AC_CANONICAL_TARGET +AC_MSG_CHECKING(rtems target cpu) +case "${target}" in + # hpux unix port should go here + i[[34567]]86-*linux*) # unix "simulator" port + RTEMS_CPU=unix + ;; + i[[34567]]86-*freebsd*) # unix "simulator" port + RTEMS_CPU=unix + ;; + i[[34567]]86-pc-cygwin*) # Cygwin is just enough unix like :) + RTEMS_CPU=unix + ;; + no_cpu-*rtems*) + RTEMS_CPU=no_cpu + ;; + sparc-sun-solaris*) # unix "simulator" port + RTEMS_CPU=unix + ;; + *) + RTEMS_CPU=`echo $target | sed 's%^\([[^-]]*\)-\(.*\)$%\1%'` + ;; +esac +AC_SUBST(RTEMS_CPU) +AC_MSG_RESULT($RTEMS_CPU) +]) + +# Add --enable-maintainer-mode option to configure. +# From Jim Meyering + +# serial 1 + +AC_DEFUN([AM_MAINTAINER_MODE], +[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode is disabled by default + AC_ARG_ENABLE(maintainer-mode, +[ --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer], + USE_MAINTAINER_MODE=$enableval, + USE_MAINTAINER_MODE=no) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL(MAINTAINER_MODE, [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST(MAINT)dnl +] +) + +dnl +dnl $Id$ +dnl +dnl Check for target gcc +dnl + +AC_DEFUN(RTEMS_PROG_CC, +[ +AC_BEFORE([$0], [AC_PROG_CPP])dnl +AC_BEFORE([$0], [AC_PROG_CC])dnl +AC_BEFORE([$0], [RTEMS_CANONICALIZE_TOOLS])dnl +AC_REQUIRE([RTEMS_ENABLE_LIBCDIR])dnl +AC_REQUIRE([RTEMS_ENABLE_GCC28])dnl + +RTEMS_CHECK_TOOL(CC,gcc) +test -z "$CC" && \ + AC_MSG_ERROR([no acceptable cc found in \$PATH]) +AC_PROG_CC +AC_PROG_CPP + +AM_CONDITIONAL(RTEMS_USE_GCC,test x"$GCC" = x"yes") +]) + +AC_DEFUN(RTEMS_PROG_CC_FOR_TARGET, +[ +dnl check target cc +RTEMS_PROG_CC +dnl check if the compiler supports --specs +RTEMS_GCC_SPECS +dnl check if the target compiler may use --pipe +RTEMS_GCC_PIPE +dnl check if the compiler supports --specs if gcc28 is requested +if test "$RTEMS_USE_GCC272" != "yes" ; then + if test "$rtems_cv_gcc_specs" = "no"; then + AC_MSG_WARN([*** disabling --enable-gcc28]) + RTEMS_USE_GCC272=yes + fi +fi +test "$rtems_cv_gcc_pipe" = "yes" && CC="$CC --pipe" + +if test "$GCC" = yes; then +] +ifelse([$1],,[],[CPPFLAGS="$CPPFLAGS $1"]) +[ +CFLAGS="-g -Wall" +fi +AM_CONDITIONAL(RTEMS_USE_GCC272, test x"$RTEMS_USE_GCC272" = x"yes") +AC_SUBST(RTEMS_USE_GCC272) + +dnl FIXME: HACK for egcs/cygwin mixing '\\' and '/' in gcc -print-* +case $build_os in +*cygwin*) GCCSED="| sed 's%\\\\%/%g'" ;; +*) ;; +esac +AC_SUBST(GCCSED) +]) + +dnl +dnl $Id$ +dnl +dnl Set target tools +dnl + +AC_DEFUN(RTEMS_GCC_PRINT, +[ + $1=`$CC --print-prog-name=$2` +]) + +AC_DEFUN(RTEMS_CANONICALIZE_TOOLS, +[AC_REQUIRE([RTEMS_PROG_CC])dnl + +dnl FIXME: What shall be done if these tools are not available? + RTEMS_CHECK_TOOL(AR,ar,no) + RTEMS_CHECK_TOOL(AS,as,no) + RTEMS_CHECK_TOOL(LD,ld,no) + RTEMS_CHECK_TOOL(NM,nm,no) + +dnl special treatment of ranlib + RTEMS_CHECK_TOOL(RANLIB,ranlib,:) + +dnl NOTE: These may not be available if not using gnutools + RTEMS_CHECK_TOOL(OBJCOPY,objcopy,no) + RTEMS_CHECK_TOOL(SIZE,size,no) + RTEMS_CHECK_TOOL(STRIP,strip,:) +]) + +dnl $Id$ + +dnl RTEMS_CHECK_TOOL(VARIABLE, PROG-TO-CHECK-FOR[, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN(RTEMS_CHECK_TOOL, +[AC_REQUIRE([AC_CHECK_TOOL_PREFIX])dnl +AC_CHECK_PROG($1, ${ac_tool_prefix}$2, ${ac_tool_prefix}$2, $3, $4) +]) + +dnl $Id$ + +AC_DEFUN(RTEMS_ENABLE_LIBCDIR, +[ +AC_ARG_ENABLE(libcdir, +AC_HELP_STRING([--enable-libcdir=directory], +[set the directory for the C library]), +[ RTEMS_LIBC_DIR="${enableval}" ; \ +test -d ${enableval} || AC_MSG_ERROR("$enableval is not a directory" ) ] ) +AC_SUBST(RTEMS_LIBC_DIR)dnl +]) + + +dnl $Id$ + +AC_DEFUN(RTEMS_ENABLE_GCC28, +[ +AC_ARG_ENABLE(gcc28, +AC_HELP_STRING([--enable-gcc28],[enable use of gcc 2.8.x features]), +[case "${enableval}" in + yes) RTEMS_USE_GCC272=no ;; + no) RTEMS_USE_GCC272=yes ;; + *) AC_MSG_ERROR(bad value ${enableval} for gcc-28 option) ;; +esac],[RTEMS_USE_GCC272=no]) +]) + +dnl +dnl $Id$ +dnl +dnl Check whether the target compiler accepts -specs +dnl + +AC_DEFUN(RTEMS_GCC_SPECS, +[AC_REQUIRE([RTEMS_PROG_CC]) +AC_CACHE_CHECK(whether $CC accepts -specs,rtems_cv_gcc_specs, +[ +rtems_cv_gcc_specs=no +if test x"$GCC" = x"yes"; then + touch confspec + echo 'void f(){}' >conftest.c + if test -z "`${CC} -specs confspec -c conftest.c 2>&1`";then + rtems_cv_gcc_specs=yes + fi +fi +rm -f confspec conftest* +])]) + +dnl +dnl $Id$ +dnl +dnl Check whether the target compiler accepts -pipe +dnl + +AC_DEFUN(RTEMS_GCC_PIPE, +[AC_REQUIRE([RTEMS_PROG_CC]) +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_CACHE_CHECK(whether $CC accepts --pipe,rtems_cv_gcc_pipe, +[ +rtems_cv_gcc_pipe=no +if test x"$GCC" = x"yes"; then + echo 'void f(){}' >conftest.c + if test -z "`${CC} --pipe -c conftest.c 2>&1`";then + rtems_cv_gcc_pipe=yes + fi + rm -f conftest* +fi +]) +]) + +dnl $Id$ + +AC_DEFUN(RTEMS_ENABLE_NETWORKING, +[ + +AC_ARG_ENABLE(networking, +AC_HELP_STRING([--enable-networking],[enable TCP/IP stack]), +[case "${enableval}" in + yes) RTEMS_HAS_NETWORKING=yes ;; + no) RTEMS_HAS_NETWORKING=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for enable-networking option) ;; +esac],[RTEMS_HAS_NETWORKING=yes]) +AC_SUBST(RTEMS_HAS_NETWORKING)dnl +]) + +dnl $Id$ + +dnl Pass a single BSP via an environment variable +dnl used by per BSP configure scripts +AC_DEFUN(RTEMS_ENV_RTEMSBSP, +[dnl +AC_BEFORE([$0], [RTEMS_ENABLE_RTEMSBSP])dnl +AC_BEFORE([$0], [RTEMS_PROJECT_ROOT])dnl +AC_BEFORE([$0], [RTEMS_CHECK_CUSTOM_BSP])dnl + +AC_ARG_VAR([RTEMS_BSP],[RTEMS_BSP to build]) +AC_MSG_CHECKING([for RTEMS_BSP]) +AC_CACHE_VAL(rtems_cv_RTEMS_BSP, +[dnl + test -n "${RTEMS_BSP}" && rtems_cv_RTEMS_BSP="$RTEMS_BSP"; +])dnl +if test -z "$rtems_cv_RTEMS_BSP"; then + AC_MSG_ERROR([Missing RTEMS_BSP]) +fi +RTEMS_BSP="$rtems_cv_RTEMS_BSP" +AC_MSG_RESULT(${RTEMS_BSP}) +AC_SUBST(RTEMS_BSP) + +RTEMS_BSP_SPECS="-specs bsp_specs -qrtems" +AC_SUBST(RTEMS_BSP_SPECS) + +GCC_SPECS="-B\$(PROJECT_ROOT)/ -B\$(PROJECT_ROOT)/$RTEMS_BSP/lib/" +AC_SUBST(GCC_SPECS) + +RTEMS_ROOT=$PROJECT_ROOT/c/$RTEMS_BSP +AC_SUBST(RTEMS_ROOT) + +RTEMS_ENABLE_BARE +AC_SUBST(BARE_CPU_MODEL) +AC_SUBST(BARE_CPU_CFLAGS) + +AM_CONDITIONAL(RTEMS_CONFIG_PER_BSP, true); + +includedir="\${exec_prefix}/\$(RTEMS_BSP)/lib/include" +]) + +dnl $Id$ + +dnl Override the set of BSPs to be built. +dnl used by the toplevel configure script +dnl RTEMS_ENABLE_RTEMSBSP(rtems_bsp_list) +AC_DEFUN(RTEMS_ENABLE_RTEMSBSP, +[ +AC_BEFORE([$0], [RTEMS_ENV_RTEMSBSP])dnl +AC_ARG_ENABLE(rtemsbsp, +AC_HELP_STRING([--enable-rtemsbsp="bsp1 bsp2 .."], +[BSPs to include in build]), +[case "${enableval}" in + yes|no) AC_MSG_ERROR([missing argument to --enable-rtemsbsp=\"bsp1 bsp2\"]);; + *) $1=$enableval;; +esac],[$1=""]) +]) + +dnl +dnl $Id$ +dnl + +dnl +dnl PROJECT_TOPdir .. relative path to the top of the build-tree +dnl PROJECT_ROOT .. relative path to the top of the temporary +dnl installation directory inside the build-tree +dnl RTEMS_TOPdir .. relative path of a subpackage's configure.in to the +dnl toplevel configure.in of the source-tree +dnl RTEMS_ROOT .. path to the top of a bsp's build directory +dnl [Applied by custom/*.cfg, depredicated otherwise] +dnl + +AC_DEFUN(RTEMS_PROJECT_ROOT, +[dnl +AC_REQUIRE([RTEMS_TOP]) + +PACKHEX="\$(PROJECT_TOPdir)/tools/build/packhex" +AC_SUBST(PACKHEX) + +PROJECT_INCLUDE="\$(PROJECT_ROOT)/$RTEMS_BSP/lib/include" +AC_SUBST(PROJECT_INCLUDE) + +PROJECT_RELEASE="\$(PROJECT_ROOT)/$RTEMS_BSP" +AC_SUBST(PROJECT_RELEASE) +]) + + +dnl $Id$ + +dnl Report all available bsps for a target, +dnl check if a bsp-subdirectory is present for all bsps found +dnl +dnl RTEMS_CHECK_BSPS(bsp_list) +AC_DEFUN(RTEMS_CHECK_BSPS, +[ +AC_REQUIRE([RTEMS_CHECK_CPU])dnl sets RTEMS_CPU, target +AC_REQUIRE([RTEMS_TOP])dnl sets RTEMS_TOPdir +AC_MSG_CHECKING([for bsps]) + files=`ls $srcdir/$RTEMS_TOPdir/c/src/lib/libbsp/$RTEMS_CPU` + for file in $files; do + case $file in + ChangeLog*);; + shared*);; + Makefile*);; + READ*);; + CVS*);; + pxfl*);; + ac*);; + config*);; + # Now account for BSPs with build variants + c4xsim) rtems_bsp="$rtems_bsp c4xsim c3xsim";; + gen68360) rtems_bsp="$rtems_bsp gen68360 gen68360_040";; + p4000) rtems_bsp="$rtems_bsp p4600 p4650";; + mvme162) rtems_bsp="$rtems_bsp mvme162 mvme162lx";; + mbx8xx) rtems_bsp="$rtems_bsp mbx821_001 mbx860_002";; + motorola_powerpc) rtems_bsp="$rtems_bsp mvme2307 mcp750";; + pc386) rtems_bsp="$rtems_bsp pc386 pc386dx pc486 pc586 pc686 pck6";; + erc32) rtems_bsp="$rtems_bsp erc32 erc32nfp";; + leon) rtems_bsp="$rtems_bsp leon1 leon2";; + sim68000) rtems_bsp="$rtems_bsp sim68000 simcpu32";; + shsim) rtems_bsp="$rtems_bsp simsh7032 simsh7045";; + *) if test -d $srcdir/$RTEMS_TOPdir/c/src/lib/libbsp/$RTEMS_CPU/$file; then + $1="[$]$1 $file" + fi;; + esac; + done +AC_MSG_RESULT([[$]$1 .. done]) +])dnl + +AC_DEFUN(RTEMS_CHECK_CUSTOM_BSP, +[dnl +AC_REQUIRE([RTEMS_TOP]) + +AC_MSG_CHECKING([for make/custom/[$]$1.cfg]) +if test -r "$srcdir/$RTEMS_TOPdir/make/custom/[$]$1.cfg"; then + AC_MSG_RESULT([yes]) +else + AC_MSG_ERROR([no]) +fi +])dnl + +dnl $Id$ + +dnl check if RTEMS support a cpu +AC_DEFUN(RTEMS_CHECK_CPU, +[dnl +AC_REQUIRE([RTEMS_TOP]) +AC_REQUIRE([RTEMS_CANONICAL_TARGET_CPU]) + +# Is this a supported CPU? +AC_MSG_CHECKING([if cpu $RTEMS_CPU is supported]) +if test -d "$srcdir/$RTEMS_TOPdir/c/src/exec/score/cpu/$RTEMS_CPU"; then + AC_MSG_RESULT(yes) +else + AC_MSG_ERROR(no) +fi +])dnl + + +AC_DEFUN(RTEMS_ENABLE_BARE, +[ +AC_ARG_ENABLE(bare-cpu-cflags, +AC_HELP_STRING([--enable-bare-cpu-cflags],[specify a particular cpu cflag (bare bsp specific)]), +[case "${enableval}" in + no) BARE_CPU_CFLAGS="" ;; + *) BARE_CPU_CFLAGS="${enableval}" ;; +esac], +[BARE_CPU_CFLAGS=""]) + +AC_ARG_ENABLE(bare-cpu-model, +AC_HELP_STRING([--enable-bare-cpu-model],[specify a particular cpu model (bare bsp specific)]), +[case "${enableval}" in + no) BARE_CPU_MODEL="" ;; + *) BARE_CPU_MODEL="${enableval}" ;; +esac], +[BARE_CPU_MODEL=""]) +]) + + +dnl $Id$ + +dnl RTEMS_CHECK_BSP_CACHE(RTEMS_BSP) +AC_DEFUN(RTEMS_CHECK_BSP_CACHE, +[ +AC_REQUIRE([RTEMS_CHECK_CPU])dnl sets RTEMS_CPU, target +AC_REQUIRE([RTEMS_ENV_RTEMSBSP])dnl set RTEMS_BSP +AC_REQUIRE([RTEMS_TOP])dnl sets RTEMS_TOPdir +AC_CACHE_CHECK([for RTEMS_CPU_MODEL], rtems_cv_RTEMS_CPU_MODEL, +. $RTEMS_TOPdir/c/[$]$1/make/[$]$1.cache) +RTEMS_CPU_MODEL=$rtems_cv_RTEMS_CPU_MODEL +AC_SUBST(RTEMS_CPU_MODEL) +AC_CACHE_CHECK([for RTEMS_BSP_FAMILY], rtems_cv_RTEMS_BSP_FAMILY, +. $RTEMS_TOPdir/c/[$]$1/make/[$]$1.cache) +RTEMS_BSP_FAMILY=$rtems_cv_RTEMS_BSP_FAMILY +AC_SUBST(RTEMS_BSP_FAMILY) +])dnl + +dnl $Id$ +dnl +AC_DEFUN(RTEMS_CHECK_NETWORKING, +[dnl +AC_REQUIRE([RTEMS_CHECK_CPU])dnl +AC_REQUIRE([RTEMS_ENABLE_NETWORKING])dnl + +AC_CACHE_CHECK([whether BSP supports networking], + rtems_cv_HAS_NETWORKING, + [dnl + case "$RTEMS_CPU" in + unix*) + rtems_cv_HAS_NETWORKING="no" + ;; + *) + if test "${RTEMS_HAS_NETWORKING}" = "yes"; then + rtems_cv_HAS_NETWORKING="yes"; + else + rtems_cv_HAS_NETWORKING="disabled"; + fi + ;; + esac]) +if test "$rtems_cv_HAS_NETWORKING" = "yes"; then + HAS_NETWORKING="yes"; +else + HAS_NETWORKING="no"; +fi +AC_SUBST(HAS_NETWORKING)dnl +]) + +dnl $Id$ + +AC_DEFUN(RTEMS_CANONICAL_HOST, +[dnl +AC_REQUIRE([AC_CANONICAL_HOST]) +RTEMS_HOST=$host_os +case "${target}" in + # hpux unix port should go here + i[[34567]]86-*linux*) # unix "simulator" port + RTEMS_HOST=Linux + ;; + i[[34567]]86-*freebsd*) # unix "simulator" port + RTEMS_HOST=FreeBSD + ;; + i[[34567]]86-pc-cygwin*) # Cygwin is just enough unix like :) + RTEMS_HOST=Cygwin + ;; + sparc-sun-solaris*) # unix "simulator" port + RTEMS_HOST=Solaris + ;; + *) + ;; +esac +AC_SUBST(RTEMS_HOST) +])dnl + diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/bsp_specs b/c/src/lib/libbsp/powerpc/mpc8260ads/bsp_specs new file mode 100644 index 0000000000..1190a2c0eb --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/bsp_specs @@ -0,0 +1,26 @@ +%rename cpp old_cpp +%rename lib old_lib +%rename endfile old_endfile +%rename startfile old_startfile +%rename link old_link + +*cpp: +%(old_cpp) %{qrtems: -D__embedded__} -Asystem(embedded) + +*lib: +%{!qrtems: %(old_lib)} %{qrtems: --start-group \ +%{!qrtems_debug: -lrtemsall} %{qrtems_debug: -lrtemsall_g} \ +-lc -lgcc --end-group \ +%{!qnolinkcmds: -T linkcmds%s}} + +*startfile: +%{!qrtems: %(old_startfile)} %{qrtems: ecrti%O%s \ +%{!qrtems_debug: start.o%s} \ +%{qrtems_debug: start_g.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: ecrtn%O%s} + +*link: +%{!qrtems: %(old_link)} %{qrtems: -dc -dp -u __vectors -N -u start -e start} + diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/clock/.cvsignore b/c/src/lib/libbsp/powerpc/mpc8260ads/clock/.cvsignore new file mode 100644 index 0000000000..282522db03 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/clock/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/clock/Makefile.am b/c/src/lib/libbsp/powerpc/mpc8260ads/clock/Makefile.am new file mode 100644 index 0000000000..c41be0decc --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/clock/Makefile.am @@ -0,0 +1,26 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 + +VPATH = @srcdir@:@srcdir@/../../shared/clock + +C_FILES = p_clock.c +C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) + +OBJS = $(C_O_FILES) + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../../../../automake/compile.am +include $(top_srcdir)/../../../../../../automake/lib.am + +# +# (OPTIONAL) Add local stuff here using += +# + +# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile + +all-local: $(ARCH) $(OBJS) + +include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/clock/p_clock.c b/c/src/lib/libbsp/powerpc/mpc8260ads/clock/p_clock.c new file mode 100644 index 0000000000..5b514cab4b --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/clock/p_clock.c @@ -0,0 +1,71 @@ +/* + * Clock Tick interrupt conexion code. + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * Modified to support the MPC750. + * Modifications Copyright (c) 1999 Eric Valette valette@crf.canon.fr + * + * $Id$ + */ + +#include +#include +#include + +extern void clockOn(void*); +extern void clockOff (void*); +extern int clockIsOn(void*); +extern void Clock_isr(); + +static rtems_irq_connect_data clockIrqData = {BSP_PERIODIC_TIMER, + (rtems_irq_hdl)Clock_isr, + (rtems_irq_enable)clockOn, + (rtems_irq_disable)clockOff, + (rtems_irq_is_enabled)clockIsOn}; + +int BSP_get_clock_irq_level() +{ + /* + * Caution : if you change this, you must change the + * definition of BSP_PERIODIC_TIMER accordingly + */ + return BSP_PERIODIC_TIMER; +} + +int BSP_disconnect_clock_handler (void) +{ + if (!BSP_get_current_rtems_irq_handler(&clockIrqData)) { + printk("Unable to stop system clock\n"); + rtems_fatal_error_occurred(1); + } + return BSP_remove_rtems_irq_handler (&clockIrqData); +} + +int BSP_connect_clock_handler (rtems_irq_hdl hdl) +{ + if (!BSP_get_current_rtems_irq_handler(&clockIrqData)) { + printk("Unable to get system clock handler\n"); + rtems_fatal_error_occurred(1); + } + if (!BSP_remove_rtems_irq_handler (&clockIrqData)) { + printk("Unable to remove current system clock handler\n"); + rtems_fatal_error_occurred(1); + } + /* + * Reinit structure + */ + clockIrqData.name = BSP_PERIODIC_TIMER; + clockIrqData.hdl = (rtems_irq_hdl) hdl; + clockIrqData.on = (rtems_irq_enable)clockOn; + clockIrqData.off = (rtems_irq_enable)clockOff; + clockIrqData.isOn = (rtems_irq_is_enabled)clockIsOn; + + return BSP_install_rtems_irq_handler (&clockIrqData); +} diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/console/Makefile.am b/c/src/lib/libbsp/powerpc/mpc8260ads/console/Makefile.am new file mode 100644 index 0000000000..26f76d08b9 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/console/Makefile.am @@ -0,0 +1,33 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 + +PGM = $(ARCH)/console.rel + +C_FILES = console.c +C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) + +OBJS = $(C_O_FILES) + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../../../../automake/compile.am +include $(top_srcdir)/../../../../../../automake/lib.am + +# +# (OPTIONAL) Add local stuff here using += +# + +$(PGM): $(OBJS) + $(make-rel) + +# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile + +all-local: $(ARCH) $(OBJS) $(PGM) + +.PRECIOUS: $(PGM) + +EXTRA_DIST = console.c + +include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/console/console.c b/c/src/lib/libbsp/powerpc/mpc8260ads/console/console.c new file mode 100644 index 0000000000..476408e3ee --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/console/console.c @@ -0,0 +1,478 @@ +/* + * console.c + * + * This file contains the MBX8xx termios serial I/O package. + * Only asynchronous I/O is supported. + * + * The SCCs and SMCs are assigned as follows + * + * Channel Device Minor Note + * SMC1 /dev/tty0 0 + * SMC2 /dev/tty1 1 + * SCC1 2 N/A. Hardwired as ethernet port + * SCC2 /dev/tty2 3 + * SCC3 /dev/tty3 4 + * SCC4 /dev/tty4 5 + * + * All ports support termios. The use of termios is recommended for real-time + * applications. Termios provides buffering and input processing. When not + * using termios, processing is limited to the substitution of LF for CR on + * input, and the output of a CR following the output of a LF character. + * Note that the terminal should not send CR/LF pairs when the return key + * is pressed, and that output lines are terminated with LF/CR, not CR/LF + * (although that would be easy to change). + * + * I/O may be interrupt-driven (recommended for real-time applications) or + * polled. Polled I/O may be performed by this device driver entirely, or + * in part by EPPCBug. With EPPCBug 1.1, polled I/O is limited to the + * EPPCBug debug console. This is a limitation of the firmware. Later + * firmware may be able to do I/O through any port. This code assumes + * that the EPPCBug console is the default: SMC1. If the console and + * printk ports are set to anything else with EPPCBug polled I/O, the + * system will hang. Only port SMC1 is usable with EPPCBug polled I/O. + * + * LIMITATIONS: + * + * It is not possible to use different I/O modes on the different ports. The + * exception is with printk. The printk port can use a different mode from + * the other ports. If this is done, it is important not to open the printk + * port from an RTEMS application. + * + * Currently, the I/O modes are determined at build time. It would be much + * better to have the mode selected at boot time based on parameters in + * NVRAM. + * + * Interrupt-driven I/O requires termios. + * + * TESTS: + * + * TO RUN THE TESTS, USE POLLED I/O WITHOUT TERMIOS SUPPORT. Some tests + * play with the interrupt masks and turn off I/O. Those tests will hang + * when interrupt-driven I/O is used. Other tests, such as cdtest, do I/O + * from the static constructors before the console is open. This test + * will not work with interrupt-driven I/O. Because of the buffering + * performed in termios, test output may not be in sequence.The tests + * should all be fixed to work with interrupt-driven I/O and to + * produce output in the expected sequence. Obviously, the termios test + * requires termios support in the driver. + * + * Set CONSOLE_MINOR to the appropriate device minor number in the + * config file. This allows the RTEMS application console to be different + * from the EPPBug debug console or the GDB port. + * + * This driver handles all five available serial ports: it distinguishes + * the sub-devices using minor device numbers. It is not possible to have + * other protocols running on the other ports when this driver is used as + * currently written. + * + * Based on code (alloc860.c in eth_comm port) by + * Jay Monkman (jmonkman@frasca.com), + * Copyright (C) 1998 by Frasca International, Inc. + * + * Modifications by Darlene Stewart + * and Charles-Antoine Gauthier . + * Copyright (c) 2000, National Research Council of Canada + * + * Modifications by Andy Dachs for MPC8260 + * support. + * + * The SCCs and SMCs on the eval board are assigned as follows + * + * Channel Device Minor Termios + * SMC1 /dev/tty3 4 no + * SMC2 /dev/tty4 5 no + * SCC1 /dev/tty0 0 no + * SCC2 /dev/console 1 yes + * SCC3 /dev/tty1 2 no * USED FOR NETWORK I/F + * SCC4 /dev/tty2 3 no * USED FOR NETWORK I/F + * + */ +#include +#include +#include /* Must be before libio.h */ +#include +#include +#include + +static void _BSP_output_char( char c ); +static rtems_status_code do_poll_read( rtems_device_major_number major, rtems_device_minor_number minor, void * arg); +static rtems_status_code do_poll_write( rtems_device_major_number major, rtems_device_minor_number minor, void * arg); + + +BSP_output_char_function_type BSP_output_char = _BSP_output_char; + + + + +/* + * do_poll_read + * + * Input characters through polled I/O. Returns has soon as a character has + * been received. Otherwise, if we wait for the number of requested characters, + * we could be here forever! + * + * CR is converted to LF on input. The terminal should not send a CR/LF pair + * when the return or enter key is pressed. + * + * Input parameters: + * major - ignored. Should be the major number for this driver. + * minor - selected channel. + * arg->buffer - where to put the received characters. + * arg->count - number of characters to receive before returning--Ignored. + * + * Output parameters: + * arg->bytes_moved - the number of characters read. Always 1. + * + * Return value: RTEMS_SUCCESSFUL + * + * CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O! + */ +static rtems_status_code do_poll_read( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + rtems_libio_rw_args_t *rw_args = arg; + int c; + +#define BSP_READ m8xx_uart_pollRead + + while( (c = BSP_READ(minor)) == -1 ); + rw_args->buffer[0] = (unsigned8)c; + if( rw_args->buffer[0] == '\r' ) + rw_args->buffer[0] = '\n'; + rw_args->bytes_moved = 1; + return RTEMS_SUCCESSFUL; +} + + +/* + * do_poll_write + * + * Output characters through polled I/O. Returns only once every character has + * been sent. + * + * CR is transmitted AFTER a LF on output. + * + * Input parameters: + * major - ignored. Should be the major number for this driver. + * minor - selected channel + * arg->buffer - where to get the characters to transmit. + * arg->count - the number of characters to transmit before returning. + * + * Output parameters: + * arg->bytes_moved - the number of characters read + * + * Return value: RTEMS_SUCCESSFUL + * + * CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O! + */ +static rtems_status_code do_poll_write( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + rtems_libio_rw_args_t *rw_args = arg; + unsigned32 i; + char cr ='\r'; + +#define BSP_WRITE m8xx_uart_pollWrite + + for( i = 0; i < rw_args->count; i++ ) { + BSP_WRITE(minor, &(rw_args->buffer[i]), 1); + if ( rw_args->buffer[i] == '\n' ) + BSP_WRITE(minor, &cr, 1); + } + rw_args->bytes_moved = i; + return RTEMS_SUCCESSFUL; + +} + + +/* + * Print functions prototyped in bspIo.h + */ + +static void _BSP_output_char( char c ) +{ + char cr = '\r'; + + /* + * Can't rely on console_initialize having been called before this function + * is used, so it may fail unless output is done through EPPC-Bug. + */ +#define PRINTK_WRITE m8xx_uart_pollWrite + + PRINTK_WRITE( PRINTK_MINOR, &c, 1 ); + if( c == '\n' ) + PRINTK_WRITE( PRINTK_MINOR, &cr, 1 ); + +} + + +/* + *************** + * BOILERPLATE * + *************** + * + * All these functions are prototyped in rtems/c/src/lib/include/console.h. + */ + +/* + * Initialize and register the device + */ +rtems_device_driver console_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_status_code status; + rtems_device_minor_number console_minor; + + /* + * Set up TERMIOS if needed + */ + + console_minor = CONSOLE_MINOR; + +#if UARTS_USE_TERMIOS == 1 + + rtems_termios_initialize (); +#else + rtems_termios_initialize (); +#endif /* UARTS_USE_TERMIOS */ + + /* + * Do common initialization. + */ + m8xx_uart_initialize(); + + /* + * Do device-specific initialization + */ +#if 0 + m8xx_uart_smc_initialize(SMC1_MINOR); /* /dev/tty4 */ + m8xx_uart_smc_initialize(SMC2_MINOR); /* /dev/tty5 */ +#endif + + m8xx_uart_scc_initialize(SCC1_MINOR); /* /dev/tty0 */ + m8xx_uart_scc_initialize(SCC2_MINOR); /* /dev/tty1 */ + +#if 0 /* used as network connections */ + m8xx_uart_scc_initialize(SCC3_MINOR); /* /dev/tty2 */ + m8xx_uart_scc_initialize(SCC4_MINOR); /* /dev/tty3 */ +#endif + + + + /* + * Set up interrupts + */ + m8xx_uart_interrupts_initialize(); + + status = rtems_io_register_name ("/dev/tty0", major, SCC1_MINOR); + if (status != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (status); + chmod("/dev/tty0",0660); + chown("/dev/tty0",2,0); + + + status = rtems_io_register_name ("/dev/tty1", major, SCC2_MINOR); + if (status != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (status); + chmod("/dev/tty1",0660); + chown("/dev/tty1",2,0); + +#if 0 + status = rtems_io_register_name ("/dev/tty2", major, SCC3_MINOR); + if (status != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (status); + + status = rtems_io_register_name ("/dev/tty3", major, SCC4_MINOR); + if (status != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (status); + + status = rtems_io_register_name ("/dev/tty4", major, SMC1_MINOR); + if (status != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (status); + + status = rtems_io_register_name ("/dev/tty5", major, SMC2_MINOR); + if (status != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (status); +#endif + /* Now register the RTEMS console */ + status = rtems_io_register_name ("/dev/console", major, console_minor); + if (status != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (status); + chmod("/dev/console",0666); + chown("/dev/console",2,0); + + return RTEMS_SUCCESSFUL; +} + + +/* + * Open the device + */ +rtems_device_driver console_open( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + /* Used to track termios private data for callbacks */ + extern struct rtems_termios_tty *ttyp[]; + + rtems_libio_open_close_args_t *args = arg; + rtems_status_code sc; + + + static const rtems_termios_callbacks intrCallbacks = { + NULL, /* firstOpen */ + NULL, /* lastClose */ + NULL, /* pollRead */ + m8xx_uart_write, /* write */ + m8xx_uart_setAttributes, /* setAttributes */ + NULL, /* stopRemoteTx */ + NULL, /* startRemoteTx */ + 1 /* outputUsesInterrupts */ + }; + + static const rtems_termios_callbacks pollCallbacks = { + NULL, /* firstOpen */ + NULL, /* lastClose */ + m8xx_uart_pollRead, /* pollRead */ + m8xx_uart_pollWrite, /* write */ + m8xx_uart_setAttributes, /* setAttributes */ + NULL, /* stopRemoteTx */ + NULL, /* startRemoteTx */ + 0 /* outputUsesInterrupts */ + }; + + if ( minor > NUM_PORTS-1 ) + return RTEMS_INVALID_NUMBER; + + +#if UARTS_USE_TERMIOS == 1 + +#if UARTS_IO_MODE == 1 /* RTEMS interrupt-driven I/O with termios */ + sc = rtems_termios_open( major, minor, arg, &intrCallbacks ); + ttyp[minor] = args->iop->data1; /* Keep cookie returned by termios_open */ +#else /* RTEMS polled I/O with termios */ + sc = rtems_termios_open( major, minor, arg, &pollCallbacks ); +#endif + +#else /* UARTS_USE_TERMIOS != 1 */ + /* no termios -- default to polled I/O */ + sc = RTEMS_SUCCESSFUL; +#endif /* UARTS_USE_TERMIOS != 1 */ + + return sc; + +} + + +/* + * Close the device + */ +rtems_device_driver console_close( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + if ( minor > NUM_PORTS-1 ) + return RTEMS_INVALID_NUMBER; + +#if UARTS_USE_TERMIOS == 1 + return rtems_termios_close( arg ); +#else + return RTEMS_SUCCESSFUL; +#endif + +} + + +/* + * Read from the device + */ +rtems_device_driver console_read( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + if ( minor > NUM_PORTS-1 ) + return RTEMS_INVALID_NUMBER; + + +#if UARTS_USE_TERMIOS == 1 + return rtems_termios_read( arg ); +#else + return do_poll_read( major, minor, arg ); +#endif + +} + + +/* + * Write to the device + */ +rtems_device_driver console_write( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + if ( minor > NUM_PORTS-1 ) + return RTEMS_INVALID_NUMBER; + + +#if UARTS_USE_TERMIOS == 1 + return rtems_termios_write( arg ); +#else + /* no termios -- default to polled */ + return do_poll_write( major, minor, arg ); +#endif + +} + + +/* + * Handle ioctl request. + */ +rtems_device_driver console_control( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + if ( minor > NUM_PORTS-1 ) + return RTEMS_INVALID_NUMBER; + + +#if UARTS_USE_TERMIOS == 1 + return rtems_termios_ioctl( arg ); +#else + return RTEMS_SUCCESSFUL; +#endif + +} + +/* + * Support routine for console-generic + */ + +int mbx8xx_console_get_configuration(void) +{ +#if UARTS_IO_MODE == 1 + return 0x02; +#else + return 0; +#endif + +} + diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/include/Makefile.am b/c/src/lib/libbsp/powerpc/mpc8260ads/include/Makefile.am new file mode 100644 index 0000000000..c10ba294ff --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/include/Makefile.am @@ -0,0 +1,31 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 + +H_FILES = bsp.h coverhd.h + +BSP_H_FILES = + +$(PROJECT_INCLUDE): + $(mkinstalldirs) $@ + +$(PROJECT_INCLUDE)/bsp: + $(mkinstalldirs) $@ + +$(PROJECT_INCLUDE)/bsp.h: bsp.h + $(INSTALL_DATA) $< $@ + +$(PROJECT_INCLUDE)/coverhd.h: coverhd.h + $(INSTALL_DATA) $< $@ + + + +PREINSTALL_FILES += $(PROJECT_INCLUDE) $(PROJECT_INCLUDE)/bsp \ + $(PROJECT_INCLUDE)/bsp.h \ + $(PROJECT_INCLUDE)/coverhd.h + +all-local: $(PREINSTALL_FILES) + +include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/include/bsp.h b/c/src/lib/libbsp/powerpc/mpc8260ads/include/bsp.h new file mode 100644 index 0000000000..7fc940cbe5 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/include/bsp.h @@ -0,0 +1,157 @@ +/* bsp.h + * + * This include file contains all board IO definitions. + * + * XXX : put yours in here + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#ifndef __NO_BSP_h +#define __NO_BSP_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Board configuration registers + */ + +typedef struct bcsr + +{ + rtems_unsigned32 bcsr0; /* Board Control and Status Register */ + rtems_unsigned32 bcsr1; + rtems_unsigned32 bcsr2; + rtems_unsigned32 bcsr3; + +} BCSR; + +#define UART1_E 0x02000002 /* bit 6 of BCSR1 */ +#define UART2_E 0x01000001 /* bit 7 of BCSR1 */ + +#define GP0_LED 0x02000002 /* bit 6 of BCSR0 */ +#define GP1_LED 0x01000001 /* bit 7 of BCSR0 */ + +/* + * Network driver configuration + */ +struct rtems_bsdnet_ifconfig; +extern int rtems_enet_driver_attach (struct rtems_bsdnet_ifconfig *config, int attaching); +#define RTEMS_BSP_NETWORK_DRIVER_NAME "eth1" +#define RTEMS_BSP_NETWORK_DRIVER_ATTACH rtems_enet_driver_attach + + + +/* miscellaneous stuff assumed to exist */ + +extern rtems_configuration_table BSP_Configuration; +/* + * We need to decide how much memory will be non-cacheable. This + * will mainly be memory that will be used in DMA (network and serial + * buffers). + */ +/* +#define NOCACHE_MEM_SIZE 512*1024 +*/ + +/* + * Define the time limits for RTEMS Test Suite test durations. + * Long test and short test duration limits are provided. These + * values are in seconds and need to be converted to ticks for the + * application. + * + */ + +#define MAX_LONG_TEST_DURATION 300 /* 5 minutes = 300 seconds */ +#define MAX_SHORT_TEST_DURATION 3 /* 3 seconds */ + +/* + * Stuff for Time Test 27 + */ + +#define MUST_WAIT_FOR_INTERRUPT 0 + +#define Install_tm27_vector( handler ) \ + do { \ + static rtems_irq_connect_data scIrqData = { \ + PPC_IRQ_SCALL, \ + (rtems_irq_hdl) handler, \ + NULL, \ + NULL, \ + NULL \ + }; \ + BSP_install_rtems_irq_handler (&scIrqData); \ + } while(0) + +#define Cause_tm27_intr() asm volatile ("sc") + +#define Clear_tm27_intr() + +#define Lower_tm27_intr() + +/* Constants */ +/* +#define RAM_START 0 +#define RAM_END 0x1000000 +*/ + + +/* + * Device Driver Table Entries + */ + +/* + * NOTE: Use the standard Console driver entry + */ + +/* + * NOTE: Use the standard Clock driver entry + */ + +/* + * How many libio files we want + */ + +#define BSP_LIBIO_MAX_FDS 20 + +/* functions */ + +void bsp_cleanup( void ); + +#if 0 +void M8260ExecuteRISC( rtems_unsigned32 command ); +void *M8260AllocateBufferDescriptors( int count ); +void *M8260AllocateRiscTimers( int count ); +extern char M8260DefaultWatchdogFeeder; +#endif + +rtems_isr_entry set_vector( /* returns old vector */ + rtems_isr_entry handler, /* isr routine */ + rtems_vector_number vector, /* vector number */ + int type /* RTEMS or RAW intr */ +); + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/include/coverhd.h b/c/src/lib/libbsp/powerpc/mpc8260ads/include/coverhd.h new file mode 100644 index 0000000000..be7cb04604 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/include/coverhd.h @@ -0,0 +1,114 @@ +/* coverhd.h + * + * This include file has defines to represent the overhead associated + * with calling a particular directive from C. These are used in the + * Timing Test Suite to ignore the overhead required to pass arguments + * to directives. On some CPUs and/or target boards, this overhead + * is significant and makes it difficult to distinguish internal + * RTEMS execution time from that used to call the directive. + * This file should be updated after running the C overhead timing + * test. Once this update has been performed, the RTEMS Time Test + * Suite should be rebuilt to account for these overhead times in the + * timing results. + * + * NOTE: If these are all zero, then the times reported include + * all calling overhead including passing of arguments. + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.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 0 +#define CALLING_OVERHEAD_TASK_IDENT 0 +#define CALLING_OVERHEAD_TASK_START 0 +#define CALLING_OVERHEAD_TASK_RESTART 0 +#define CALLING_OVERHEAD_TASK_DELETE 0 +#define CALLING_OVERHEAD_TASK_SUSPEND 0 +#define CALLING_OVERHEAD_TASK_RESUME 0 +#define CALLING_OVERHEAD_TASK_SET_PRIORITY 0 +#define CALLING_OVERHEAD_TASK_MODE 0 +#define CALLING_OVERHEAD_TASK_GET_NOTE 0 +#define CALLING_OVERHEAD_TASK_SET_NOTE 0 +#define CALLING_OVERHEAD_TASK_WAKE_WHEN 2 +#define CALLING_OVERHEAD_TASK_WAKE_AFTER 0 +#define CALLING_OVERHEAD_INTERRUPT_CATCH 0 +#define CALLING_OVERHEAD_CLOCK_GET 2 +#define CALLING_OVERHEAD_CLOCK_SET 2 +#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 2 +#define CALLING_OVERHEAD_TIMER_RESET 0 +#define CALLING_OVERHEAD_TIMER_CANCEL 0 +#define CALLING_OVERHEAD_SEMAPHORE_CREATE 0 +#define CALLING_OVERHEAD_SEMAPHORE_IDENT 0 +#define CALLING_OVERHEAD_SEMAPHORE_DELETE 0 +#define CALLING_OVERHEAD_SEMAPHORE_OBTAIN 0 +#define CALLING_OVERHEAD_SEMAPHORE_RELEASE 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_CREATE 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_IDENT 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_DELETE 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_SEND 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_URGENT 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_BROADCAST 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_RECEIVE 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_FLUSH 0 + +#define CALLING_OVERHEAD_EVENT_SEND 0 +#define CALLING_OVERHEAD_EVENT_RECEIVE 0 +#define CALLING_OVERHEAD_SIGNAL_CATCH 0 +#define CALLING_OVERHEAD_SIGNAL_SEND 0 +#define CALLING_OVERHEAD_PARTITION_CREATE 0 +#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 0 +#define CALLING_OVERHEAD_REGION_IDENT 0 +#define CALLING_OVERHEAD_REGION_DELETE 0 +#define CALLING_OVERHEAD_REGION_GET_SEGMENT 0 +#define CALLING_OVERHEAD_REGION_RETURN_SEGMENT 0 +#define CALLING_OVERHEAD_PORT_CREATE 0 +#define CALLING_OVERHEAD_PORT_IDENT 0 +#define CALLING_OVERHEAD_PORT_DELETE 0 +#define CALLING_OVERHEAD_PORT_EXTERNAL_TO_INTERNAL 0 +#define CALLING_OVERHEAD_PORT_INTERNAL_TO_EXTERNAL 0 + +#define CALLING_OVERHEAD_IO_INITIALIZE 0 +#define CALLING_OVERHEAD_IO_OPEN 0 +#define CALLING_OVERHEAD_IO_CLOSE 0 +#define CALLING_OVERHEAD_IO_READ 0 +#define CALLING_OVERHEAD_IO_WRITE 0 +#define CALLING_OVERHEAD_IO_CONTROL 0 +#define CALLING_OVERHEAD_FATAL_ERROR_OCCURRED 0 +#define CALLING_OVERHEAD_RATE_MONOTONIC_CREATE 0 +#define CALLING_OVERHEAD_RATE_MONOTONIC_IDENT 0 +#define CALLING_OVERHEAD_RATE_MONOTONIC_DELETE 0 +#define CALLING_OVERHEAD_RATE_MONOTONIC_CANCEL 0 +#define CALLING_OVERHEAD_RATE_MONOTONIC_PERIOD 0 +#define CALLING_OVERHEAD_MULTIPROCESSING_ANNOUNCE 0 + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/irq/.cvsignore b/c/src/lib/libbsp/powerpc/mpc8260ads/irq/.cvsignore new file mode 100644 index 0000000000..282522db03 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/irq/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/irq/Makefile.am b/c/src/lib/libbsp/powerpc/mpc8260ads/irq/Makefile.am new file mode 100644 index 0000000000..4b5bc87fe4 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/irq/Makefile.am @@ -0,0 +1,46 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 + +C_FILES = irq.c irq_init.c +C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) + +H_FILES = irq.h + +S_FILES = irq_asm.S +S_O_FILES = $(S_FILES:%.S=$(ARCH)/%.o) + +OBJS = $(C_O_FILES) $(S_O_FILES) + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../../../../automake/compile.am +include $(top_srcdir)/../../../../../../automake/lib.am + +SORDID_HACK: + rm -f $(PROJECT_INCLUDE)/bsp/irq.h + +$(PROJECT_INCLUDE)/bsp: + $(mkinstalldirs) $@ + +$(PROJECT_INCLUDE)/bsp/%.h: %.h + $(INSTALL_DATA) $< $@ + +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp \ + $(H_FILES:%.h=$(PROJECT_INCLUDE)/bsp/%.h) + +# +# (OPTIONAL) Add local stuff here using += +# + +$(PGM): $(OBJS) + $(make-rel) + +# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile + +all-local: SORDID_HACK $(PREINSTALL_FILES) $(ARCH) $(OBJS) $(PGM) + +EXTRA_DIST = irq.c irq.h irq_asm.S irq_init.c + +include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq.c b/c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq.c new file mode 100644 index 0000000000..75267e48be --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq.c @@ -0,0 +1,453 @@ +/* + * + * This file contains the implementation of the function described in irq.h + * + * Copyright (C) 1998, 1999 valette@crf.canon.fr + * + * Modified for mpc8260 Andy Dachs + * Surrey Satellite Technology Limited, 2000 + * Nested exception handlers not working yet. + * + * The license and distribution terms for this file may be + * found in found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include +#include +#include +#include +#include +#include +#include +/*#include */ +#include +/*#include */ + +/* + * default handler connected on each irq after bsp initialization + */ +static rtems_irq_connect_data default_rtems_entry; + +/* + * location used to store initial tables used for interrupt + * management. + */ +static rtems_irq_global_settings* internal_config; +static rtems_irq_connect_data* rtems_hdl_tbl; + + +/* + * Check if symbolic IRQ name is an CPM IRQ + */ +static inline int is_cpm_irq(const rtems_irq_symbolic_name irqLine) +{ + return (((int) irqLine <= BSP_CPM_IRQ_MAX_OFFSET) & + ((int) irqLine >= BSP_CPM_IRQ_LOWEST_OFFSET) + ); +} + +/* + * Check if symbolic IRQ name is a Processor IRQ + */ +static inline int is_processor_irq(const rtems_irq_symbolic_name irqLine) +{ + return (((int) irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) & + ((int) irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET) + ); +} + + +/* + * bit in the SIU mask registers (PPC bit numbering) that should + * be set to enable the relevant interrupt + * + */ +const static unsigned int SIU_MaskBit[BSP_CPM_IRQ_NUMBER] = +{ + 63, 48, 49, 50, /* err, i2c, spi, rtt */ + 51, 52, 53, 54, /* smc1, smc2, idma1, idma2 */ + 55, 56, 57, 63, /* idma3, idma4, sdma, - */ + 59, 60, 61, 62, /* tmr1, tmr2, tmr3, tmr4 */ + 29, 30, 63, 17, /* pit, tmcnt, -, irq1 */ + 18, 19, 20, 21, /* irq2, irq3, irq4, irq5 */ + 22, 23, 63, 63, /* irq6, irq7, -, - */ + 63, 63, 63, 63, /* -, -, -, - */ + 32, 33, 34, 35, /* fcc1, fcc2, fcc3, - */ + 36, 37, 38, 39, /* mcc1, mcc2, -, - */ + 40, 41, 42, 43, /* scc1, scc2, scc3, scc4 */ + 44, 45, 46, 47, /* -, -, -, - */ + 0, 1, 2, 3, /* pc0, pc1, pc2, pc3 */ + 4, 5, 6, 7, /* pc4, pc5, pc6, pc7 */ + 8, 9, 10, 11, /* pc8, pc9, pc10, pc11 */ + 12, 13, 14, 15 /* pc12, pc13, pc14, pc15 */ +}; + +/* + * ------------------------ RTEMS Irq helper functions ---------------- + */ + +/* + * Caution : this function assumes the variable "internal_config" + * is already set and that the tables it contains are still valid + * and accessible. + */ +static void compute_SIU_IvectMask_from_prio () +{ + /* + * In theory this is feasible. No time to code it yet. See i386/shared/irq.c + * for an example based on 8259 controller mask. The actual masks defined + * correspond to the priorities defined for the SIU in irq_init.c. + */ +} + +/* + * This function check that the value given for the irq line + * is valid. + */ + +static int isValidInterrupt(int irq) +{ + if ( (irq < BSP_LOWEST_OFFSET) || (irq > BSP_MAX_OFFSET) ) + return 0; + return 1; +} + +int BSP_irq_enable_at_cpm(const rtems_irq_symbolic_name irqLine) +{ + int cpm_irq_index; + + if (!is_cpm_irq(irqLine)) + return 1; + + cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET); + + + if( SIU_MaskBit[cpm_irq_index] < 32 ) + m8260.simr_h |= (0x80000000 >> SIU_MaskBit[cpm_irq_index]); + else + m8260.simr_l |= (0x80000000 >> (SIU_MaskBit[cpm_irq_index]-32)); + + return 0; +} + +int BSP_irq_disable_at_cpm(const rtems_irq_symbolic_name irqLine) +{ + int cpm_irq_index; + + if (!is_cpm_irq(irqLine)) + return 1; + + cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET); + + if( SIU_MaskBit[cpm_irq_index] < 32 ) + m8260.simr_h &= ~(0x80000000 >> SIU_MaskBit[cpm_irq_index]); + else + m8260.simr_l &= ~(0x80000000 >> (SIU_MaskBit[cpm_irq_index]-32)); + + + return 0; +} + +int BSP_irq_enabled_at_cpm(const rtems_irq_symbolic_name irqLine) +{ + int cpm_irq_index; + + if (!is_cpm_irq(irqLine)) + return 0; + + cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET); + + if( SIU_MaskBit[cpm_irq_index] < 32 ) + return m8260.simr_h & (0x80000000 >> SIU_MaskBit[cpm_irq_index]); + else + return m8260.simr_l & (0x80000000 >> (SIU_MaskBit[cpm_irq_index]-32)); +} + + +/* + * ------------------------ RTEMS Single Irq Handler Mngt Routines ---------------- + */ + +int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq) +{ + unsigned int level; + + if (!isValidInterrupt(irq->name)) { + printk( "not a valid intr\n" ) ; + return 0; + } + /* + * Check if default handler is actually connected. If not issue an error. + * You must first get the current handler via i386_get_current_idt_entry + * and then disconnect it using i386_delete_idt_entry. + * RATIONALE : to always have the same transition by forcing the user + * to get the previous handler before accepting to disconnect. + */ + if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) { + printk( "Default handler not there\n" ); + return 0; + } + + _CPU_ISR_Disable(level); + + /* + * store the data provided by user + */ + rtems_hdl_tbl[irq->name] = *irq; + + if (is_cpm_irq(irq->name)) { + /* + * Enable interrupt at PIC level + */ + BSP_irq_enable_at_cpm (irq->name); + } + + + if (is_processor_irq(irq->name)) { + /* + * Should Enable exception at processor level but not needed. Will restore + * EE flags at the end of the routine anyway. + */ + } + /* + * Enable interrupt on device + */ + irq->on(irq); + + _CPU_ISR_Enable(level); + +/* + printk( "Enabled\n" ); +*/ + return 1; +} + + +int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq) +{ + if (!isValidInterrupt(irq->name)) { + return 0; + } + *irq = rtems_hdl_tbl[irq->name]; + return 1; +} + +int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq) +{ + unsigned int level; + + if (!isValidInterrupt(irq->name)) { + return 0; + } + /* + * Check if default handler is actually connected. If not issue an error. + * You must first get the current handler via i386_get_current_idt_entry + * and then disconnect it using i386_delete_idt_entry. + * RATIONALE : to always have the same transition by forcing the user + * to get the previous handler before accepting to disconnect. + */ + if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) { + return 0; + } + _CPU_ISR_Disable(level); + + if (is_cpm_irq(irq->name)) { + /* + * disable interrupt at PIC level + */ + BSP_irq_disable_at_cpm (irq->name); + } + + if (is_processor_irq(irq->name)) { + /* + * disable exception at processor level + */ + } + + /* + * Disable interrupt on device + */ + irq->off(irq); + + /* + * restore the default irq value + */ + rtems_hdl_tbl[irq->name] = default_rtems_entry; + + _CPU_ISR_Enable(level); + + return 1; +} + +/* + * ------------------------ RTEMS Global Irq Handler Mngt Routines ---------------- + */ + +int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config) +{ + int i; + unsigned int level; + /* + * Store various code accelerators + */ + internal_config = config; + default_rtems_entry = config->defaultEntry; + rtems_hdl_tbl = config->irqHdlTbl; + + _CPU_ISR_Disable(level); + /* + * start with CPM IRQ + */ + for (i=BSP_CPM_IRQ_LOWEST_OFFSET; i < BSP_CPM_IRQ_LOWEST_OFFSET + BSP_CPM_IRQ_NUMBER ; i++) { + if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) { + BSP_irq_enable_at_cpm (i); + rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]); + } + else { + rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]); + BSP_irq_disable_at_cpm (i); + } + } + + /* + * finish with Processor exceptions handled like IRQ + */ + for (i=BSP_PROCESSOR_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET + BSP_PROCESSOR_IRQ_NUMBER; i++) { + if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) { + rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]); + } + else { + rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]); + } + } + _CPU_ISR_Enable(level); + return 1; +} + +int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config) +{ + *config = internal_config; + return 0; +} + +#ifdef DISPATCH_HANDLER_STAT +volatile unsigned int maxLoop = 0; +#endif + +/* + * High level IRQ handler called from shared_raw_irq_code_entry + */ +void C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum) +{ + register unsigned int irq; +#if 0 + register unsigned oldMask; /* old siu pic masks */ +#endif + register unsigned msr; + register unsigned new_msr; +#ifdef DISPATCH_HANDLER_STAT + unsigned loopCounter; +#endif + + + + /* + * Handle decrementer interrupt + */ + if (excNum == ASM_DEC_VECTOR) { + +/* + _BSP_GPLED1_on(); +*/ + _CPU_MSR_GET(msr); + new_msr = msr | MSR_EE; + _CPU_MSR_SET(new_msr); + + rtems_hdl_tbl[BSP_DECREMENTER].hdl(); + + _CPU_MSR_SET(msr); + +/* + _BSP_GPLED1_off(); +*/ + return; + } + + /* + * Handle external interrupt generated by SIU on PPC core + */ +#ifdef DISPATCH_HANDLER_STAT + loopCounter = 0; +#endif + while (1) { + + if( ((m8260.sipnr_h & m8260.simr_h) | (m8260.sipnr_l & m8260.simr_l)) == 0 ) { +#ifdef DISPATCH_HANDLER_STAT + if (loopCounter > maxLoop) maxLoop = loopCounter; +#endif + break; + } + + irq = (m8260.sivec >> 26) + BSP_CPM_IRQ_LOWEST_OFFSET; + +/* + printk( "dispatching %d\n", irq ); +*/ + + /* Clear pending register */ + if( irq <= BSP_CPM_IRQ_MAX_OFFSET ) { + if( SIU_MaskBit[irq] < 32 ) + m8260.sipnr_h = (0x80000000 >> SIU_MaskBit[irq]); + else + m8260.sipnr_l = (0x80000000 >> (SIU_MaskBit[irq]-32)); + } + +/* + _CPU_MSR_GET(msr); + new_msr = msr | MSR_EE; + _CPU_MSR_SET(new_msr); +*/ + rtems_hdl_tbl[irq].hdl(); +/* + _CPU_MSR_SET(msr); +*/ + + + +#if 0 + ppc_cached_irq_mask |= (oldMask & ~(SIU_IvectMask[irq])); + ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask; +#endif +#ifdef DISPATCH_HANDLER_STAT + ++ loopCounter; +#endif + } + + + + +} + + + +void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx) +{ + /* + * Process pending signals that have not already been + * processed by _Thread_Displatch. This happens quite + * unfrequently : the ISR must have posted an action + * to the current running thread. + */ + if ( _Thread_Do_post_task_switch_extension || + _Thread_Executing->do_post_task_switch_extension ) { + _Thread_Executing->do_post_task_switch_extension = FALSE; + _API_extensions_Run_postswitch(); + } + /* + * I plan to process other thread related events here. + * This will include DEBUG session requested from keyboard... + */ +} diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq.h b/c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq.h new file mode 100644 index 0000000000..7f30ec4402 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq.h @@ -0,0 +1,347 @@ +/* irq.h + * + * This include file describe the data structure and the functions implemented + * by rtems to write interrupt handlers. + * + * CopyRight (C) 1999 valette@crf.canon.fr + * + * This code is heavilly inspired by the public specification of STREAM V2 + * that can be found at : + * + * by following + * the STREAM API Specification Document link. + * + * Modified for mpc8260 by Andy Dachs + * Surrey Satellite Technology Limited + * The interrupt handling on the mpc8260 seems quite different from + * the 860 (I don't know the 860 well). Although some interrupts + * are routed via the CPM irq and some are direct to the SIU they all + * appear logically the same. Therefore I removed the distinction + * between SIU and CPM interrupts. + * + * The license and distribution terms for this file may be + * found in found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#ifndef LIBBSP_POWERPC_MBX8XX_IRQ_IRQ_H +#define LIBBSP_POWERPC_MBX8XX_IRQ_IRQ_H + + +#define BSP_ASM_IRQ_VECTOR_BASE 0x0 + +#ifndef ASM + +/* +extern volatile unsigned int ppc_cached_irq_mask; +*/ + +/* + * Symblolic IRQ names and related definitions. + */ + +typedef enum { + /* Base vector for our SIU IRQ handlers. */ + BSP_SIU_VECTOR_BASE = BSP_ASM_IRQ_VECTOR_BASE, + + /* + * CPM IRQ handlers related definitions + * CAUTION : BSP_CPM_IRQ_LOWEST_OFFSET should be equal to OPENPIC_VEC_SOURCE + */ + BSP_CPM_IRQ_NUMBER = 64, + BSP_CPM_IRQ_LOWEST_OFFSET = BSP_SIU_VECTOR_BASE, + BSP_CPM_IRQ_MAX_OFFSET = BSP_CPM_IRQ_LOWEST_OFFSET + BSP_CPM_IRQ_NUMBER - 1, + /* + * PowerPc exceptions handled as interrupt where a rtems managed interrupt + * handler might be connected + */ + BSP_PROCESSOR_IRQ_NUMBER = 1, + BSP_PROCESSOR_IRQ_LOWEST_OFFSET = BSP_CPM_IRQ_MAX_OFFSET + 1, + BSP_PROCESSOR_IRQ_MAX_OFFSET = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + BSP_PROCESSOR_IRQ_NUMBER - 1, + /* + * Summary + */ + BSP_IRQ_NUMBER = BSP_PROCESSOR_IRQ_MAX_OFFSET + 1, + BSP_LOWEST_OFFSET = BSP_CPM_IRQ_LOWEST_OFFSET, + BSP_MAX_OFFSET = BSP_PROCESSOR_IRQ_MAX_OFFSET, + + /* + * Some SIU IRQ symbolic name definition. Please note that + * INT IRQ are defined but a single one will be used to + * redirect all CPM interrupt. + * + * On the mpc8260 all this seems to be transparent. Although the + * CPM, PIT and TMCNT interrupt may well be the only interrupts routed + * to the SIU at the hardware level all of them appear as CPM interupts + * to software apart from the registers for setting priority. + * + * The MPC8260 User Manual seems shot through with inconsistencies + * about this whole area. + */ + + /* + * Some CPM IRQ symbolic name definition + */ + BSP_CPM_IRQ_ERROR = BSP_CPM_IRQ_LOWEST_OFFSET, + BSP_CPM_IRQ_I2C = BSP_CPM_IRQ_LOWEST_OFFSET + 1, + BSP_CPM_IRQ_SPI = BSP_CPM_IRQ_LOWEST_OFFSET + 2, + BSP_CPM_IRQ_RISC_TIMERS = BSP_CPM_IRQ_LOWEST_OFFSET + 3, + BSP_CPM_IRQ_SMC1 = BSP_CPM_IRQ_LOWEST_OFFSET + 4, + BSP_CPM_IRQ_SMC2 = BSP_CPM_IRQ_LOWEST_OFFSET + 5, + BSP_CPM_IRQ_IDMA1 = BSP_CPM_IRQ_LOWEST_OFFSET + 6, + BSP_CPM_IRQ_IDMA2 = BSP_CPM_IRQ_LOWEST_OFFSET + 7, + BSP_CPM_IRQ_IDMA3 = BSP_CPM_IRQ_LOWEST_OFFSET + 8, + BSP_CPM_IRQ_IDMA4 = BSP_CPM_IRQ_LOWEST_OFFSET + 9, + BSP_CPM_IRQ_SDMA = BSP_CPM_IRQ_LOWEST_OFFSET + 10, + + BSP_CPM_IRQ_TIMER_1 = BSP_CPM_IRQ_LOWEST_OFFSET + 12, + BSP_CPM_IRQ_TIMER_2 = BSP_CPM_IRQ_LOWEST_OFFSET + 13, + BSP_CPM_IRQ_TIMER_3 = BSP_CPM_IRQ_LOWEST_OFFSET + 14, + BSP_CPM_IRQ_TIMER_4 = BSP_CPM_IRQ_LOWEST_OFFSET + 15, + BSP_CPM_IRQ_TMCNT = BSP_CPM_IRQ_LOWEST_OFFSET + 16, + BSP_CPM_IRQ_PIT = BSP_CPM_IRQ_LOWEST_OFFSET + 17, + + BSP_CPM_IRQ_IRQ1 = BSP_CPM_IRQ_LOWEST_OFFSET + 19, + BSP_CPM_IRQ_IRQ2 = BSP_CPM_IRQ_LOWEST_OFFSET + 20, + BSP_CPM_IRQ_IRQ3 = BSP_CPM_IRQ_LOWEST_OFFSET + 21, + BSP_CPM_IRQ_IRQ4 = BSP_CPM_IRQ_LOWEST_OFFSET + 22, + BSP_CPM_IRQ_IRQ5 = BSP_CPM_IRQ_LOWEST_OFFSET + 23, + BSP_CPM_IRQ_IRQ6 = BSP_CPM_IRQ_LOWEST_OFFSET + 24, + BSP_CPM_IRQ_IRQ7 = BSP_CPM_IRQ_LOWEST_OFFSET + 25, + + BSP_CPM_IRQ_FCC1 = BSP_CPM_IRQ_LOWEST_OFFSET + 32, + BSP_CPM_IRQ_FCC2 = BSP_CPM_IRQ_LOWEST_OFFSET + 33, + BSP_CPM_IRQ_FCC3 = BSP_CPM_IRQ_LOWEST_OFFSET + 34, + + BSP_CPM_IRQ_MCC1 = BSP_CPM_IRQ_LOWEST_OFFSET + 36, + BSP_CPM_IRQ_MCC2 = BSP_CPM_IRQ_LOWEST_OFFSET + 37, + + BSP_CPM_IRQ_SCC1 = BSP_CPM_IRQ_LOWEST_OFFSET + 40, + BSP_CPM_IRQ_SCC2 = BSP_CPM_IRQ_LOWEST_OFFSET + 41, + BSP_CPM_IRQ_SCC3 = BSP_CPM_IRQ_LOWEST_OFFSET + 42, + BSP_CPM_IRQ_SCC4 = BSP_CPM_IRQ_LOWEST_OFFSET + 43, + + BSP_CPM_IRQ_PC15 = BSP_CPM_IRQ_LOWEST_OFFSET + 48, + BSP_CPM_IRQ_PC14 = BSP_CPM_IRQ_LOWEST_OFFSET + 49, + BSP_CPM_IRQ_PC13 = BSP_CPM_IRQ_LOWEST_OFFSET + 50, + BSP_CPM_IRQ_PC12 = BSP_CPM_IRQ_LOWEST_OFFSET + 51, + BSP_CPM_IRQ_PC11 = BSP_CPM_IRQ_LOWEST_OFFSET + 52, + BSP_CPM_IRQ_PC10 = BSP_CPM_IRQ_LOWEST_OFFSET + 53, + BSP_CPM_IRQ_PC9 = BSP_CPM_IRQ_LOWEST_OFFSET + 54, + BSP_CPM_IRQ_PC8 = BSP_CPM_IRQ_LOWEST_OFFSET + 55, + BSP_CPM_IRQ_PC7 = BSP_CPM_IRQ_LOWEST_OFFSET + 56, + BSP_CPM_IRQ_PC6 = BSP_CPM_IRQ_LOWEST_OFFSET + 57, + BSP_CPM_IRQ_PC5 = BSP_CPM_IRQ_LOWEST_OFFSET + 58, + BSP_CPM_IRQ_PC4 = BSP_CPM_IRQ_LOWEST_OFFSET + 59, + BSP_CPM_IRQ_PC3 = BSP_CPM_IRQ_LOWEST_OFFSET + 60, + BSP_CPM_IRQ_PC2 = BSP_CPM_IRQ_LOWEST_OFFSET + 61, + BSP_CPM_IRQ_PC1 = BSP_CPM_IRQ_LOWEST_OFFSET + 62, + BSP_CPM_IRQ_PC0 = BSP_CPM_IRQ_LOWEST_OFFSET + 63, + + + /* + * Some Processor exception handled as rtems IRQ symbolic name definition + */ + BSP_DECREMENTER = BSP_PROCESSOR_IRQ_LOWEST_OFFSET, + BSP_PERIODIC_TIMER = BSP_DECREMENTER + +}rtems_irq_symbolic_name; + +#define CPM_INTERRUPT + + +/* + * Type definition for RTEMS managed interrupts + */ +typedef unsigned char rtems_irq_prio; +struct __rtems_irq_connect_data__; /* forward declaratiuon */ + +typedef void (*rtems_irq_hdl) (void); +typedef void (*rtems_irq_enable) (const struct __rtems_irq_connect_data__*); +typedef void (*rtems_irq_disable) (const struct __rtems_irq_connect_data__*); +typedef int (*rtems_irq_is_enabled) (const struct __rtems_irq_connect_data__*); + +typedef struct __rtems_irq_connect_data__ { + /* + * IRQ line + */ + rtems_irq_symbolic_name name; + /* + * handler. See comment on handler properties below in function prototype. + */ + rtems_irq_hdl hdl; + /* + * function for enabling interrupts at device level (ONLY!). + * The BSP code will automatically enable it at SIU level and CPM level. + * RATIONALE : anyway such code has to exist in current driver code. + * It is usually called immediately AFTER connecting the interrupt handler. + * RTEMS may well need such a function when restoring normal interrupt + * processing after a debug session. + * + */ + rtems_irq_enable on; + /* + * function for disabling interrupts at device level (ONLY!). + * The code will disable it at SIU and CPM level. RATIONALE : anyway + * such code has to exist for clean shutdown. It is usually called + * BEFORE disconnecting the interrupt. RTEMS may well need such + * a function when disabling normal interrupt processing for + * a debug session. May well be a NOP function. + */ + rtems_irq_disable off; + /* + * function enabling to know what interrupt may currently occur + * if someone manipulates the i8259s interrupt mask without care... + */ + rtems_irq_is_enabled isOn; +} rtems_irq_connect_data; + +typedef struct { + /* + * size of all the table fields (*Tbl) described below. + */ + unsigned int irqNb; + /* + * Default handler used when disconnecting interrupts. + */ + rtems_irq_connect_data defaultEntry; + /* + * Table containing initials/current value. + */ + rtems_irq_connect_data* irqHdlTbl; + /* + * actual value of BSP_SIU_IRQ_VECTOR_BASE... + */ + rtems_irq_symbolic_name irqBase; + /* + * software priorities associated with interrupts. + * if irqPrio [i] > intrPrio [j] it means that + * interrupt handler hdl connected for interrupt name i + * will not be interrupted by the handler connected for interrupt j + * The interrupt source will be physically masked at i8259 level. + */ + rtems_irq_prio* irqPrioTbl; +}rtems_irq_global_settings; + + + + +/*-------------------------------------------------------------------------+ +| Function Prototypes. ++--------------------------------------------------------------------------*/ +/* + * ------------------------ PPC CPM Mngt Routines ------- + */ + +/* + * function to disable a particular irq. After calling + * this function, even if the device asserts the interrupt line it will + * not be propagated further to the processor + */ +int BSP_irq_disable_at_cpm (const rtems_irq_symbolic_name irqLine); +/* + * function to enable a particular irq. After calling + * this function, if the device asserts the interrupt line it will + * be propagated further to the processor + */ +int BSP_irq_enable_at_cpm (const rtems_irq_symbolic_name irqLine); +/* + * function to acknoledge a particular irq. After calling + * this function, if a device asserts an enabled interrupt line it will + * be propagated further to the processor. Mainly usefull for people + * writting raw handlers as this is automagically done for rtems managed + * handlers. + */ +int BSP_irq_ack_at_cpm (const rtems_irq_symbolic_name irqLine); +/* + * function to check if a particular irq is enabled. After calling + */ +int BSP_irq_enabled_at_cpm (const rtems_irq_symbolic_name irqLine); + + + +/* + * ------------------------ RTEMS Single Irq Handler Mngt Routines ---------------- + */ +/* + * function to connect a particular irq handler. This hanlder will NOT be called + * directly as the result of the corresponding interrupt. Instead, a RTEMS + * irq prologue will be called that will : + * + * 1) save the C scratch registers, + * 2) switch to a interrupt stack if the interrupt is not nested, + * 4) modify them to disable the current interrupt at SIU level (and may + * be others depending on software priorities) + * 5) aknowledge the SIU', + * 6) demask the processor, + * 7) call the application handler + * + * As a result the hdl function provided + * + * a) can perfectly be written is C, + * b) may also well directly call the part of the RTEMS API that can be used + * from interrupt level, + * c) It only responsible for handling the jobs that need to be done at + * the device level including (aknowledging/re-enabling the interrupt at device, + * level, getting the data,...) + * + * When returning from the function, the following will be performed by + * the RTEMS irq epilogue : + * + * 1) masks the interrupts again, + * 2) restore the original SIU interrupt masks + * 3) switch back on the orinal stack if needed, + * 4) perform rescheduling when necessary, + * 5) restore the C scratch registers... + * 6) restore initial execution flow + * + */ +int BSP_install_rtems_irq_handler (const rtems_irq_connect_data*); +/* + * function to get the current RTEMS irq handler for ptr->name. It enables to + * define hanlder chain... + */ +int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* ptr); +/* + * function to get disconnect the RTEMS irq handler for ptr->name. + * This function checks that the value given is the current one for safety reason. + * The user can use the previous function to get it. + */ +int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data*); + + +/* + * ------------------------ RTEMS Global Irq Handler Mngt Routines ---------------- + */ +/* + * (Re) Initialize the RTEMS interrupt management. + * + * The result of calling this function will be the same as if each individual + * handler (config->irqHdlTbl[i].hdl) different from "config->defaultEntry.hdl" + * has been individualy connected via + * BSP_install_rtems_irq_handler(&config->irqHdlTbl[i]) + * And each handler currently equal to config->defaultEntry.hdl + * has been previously disconnected via + * BSP_remove_rtems_irq_handler (&config->irqHdlTbl[i]) + * + * This is to say that all information given will be used and not just + * only the space. + * + * CAUTION : the various table address contained in config will be used + * directly by the interrupt mangement code in order to save + * data size so they must stay valid after the call => they should + * not be modified or declared on a stack. + */ + +int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config); +/* + * (Re) get info on current RTEMS interrupt management. + */ +int BSP_rtems_irq_mngt_get(rtems_irq_global_settings**); + +extern void BSP_rtems_irq_mng_init(unsigned cpuId); +#endif + +#endif diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq_asm.S b/c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq_asm.S new file mode 100644 index 0000000000..3216e63e28 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq_asm.S @@ -0,0 +1,339 @@ +/* + * This file contains the assembly code for the PowerPC + * IRQ veneers for RTEMS. + * + * The license and distribution terms for this file may be + * found in found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * Modified to support the MCP750. + * Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr + * + * + * $Id$ + */ + +#include +#include +#include +#include /* for PPC_HAS_FPU */ +#include "asm.h" + + +#define SYNC \ + sync; \ + isync + + .text + .p2align 5 + + PUBLIC_VAR(decrementer_exception_vector_prolog_code) + +SYM (decrementer_exception_vector_prolog_code): + + /* + * let room for exception frame + */ + stwu r1, - (EXCEPTION_FRAME_END)(r1) + stw r4, GPR4_OFFSET(r1) + li r4, ASM_DEC_VECTOR + ba shared_raw_irq_code_entry + + PUBLIC_VAR (decrementer_exception_vector_prolog_code_size) + + decrementer_exception_vector_prolog_code_size = . - decrementer_exception_vector_prolog_code + + PUBLIC_VAR(external_exception_vector_prolog_code) + +SYM (external_exception_vector_prolog_code): + /* + * let room for exception frame + */ + stwu r1, - (EXCEPTION_FRAME_END)(r1) + stw r4, GPR4_OFFSET(r1) + li r4, ASM_EXT_VECTOR + ba shared_raw_irq_code_entry + + PUBLIC_VAR (external_exception_vector_prolog_code_size) + + external_exception_vector_prolog_code_size = . - external_exception_vector_prolog_code + + PUBLIC_VAR(shared_raw_irq_code_entry) + PUBLIC_VAR(C_dispatch_irq_handler) + + .p2align 5 +SYM (shared_raw_irq_code_entry): + /* + * Entry conditions : + * Registers already saved : R1, R4 + * R1 : points to a location with enough room for the + * interrupt frame + * R4 : vector number + */ + /* + * Save SRR0/SRR1 As soon As possible as it is the minimal needed + * to reenable exception processing + */ + stw r0, GPR0_OFFSET(r1) + stw r2, GPR2_OFFSET(r1) + stw r3, GPR3_OFFSET(r1) + + mfsrr0 r0 + mfsrr1 r2 + mfmsr r3 + + stw r0, SRR0_FRAME_OFFSET(r1) + stw r2, SRR1_FRAME_OFFSET(r1) + + + /* + * Enable data and instruction address translation, exception recovery + * + * also, on CPUs with FP, enable FP so that FP context can be + * saved and restored (using FP instructions) + */ +#if (PPC_HAS_FPU == 0) + ori r3, r3, MSR_RI /*| MSR_IR | MSR_DR*/ +#else + ori r3, r3, MSR_RI | /*MSR_IR | MSR_DR |*/ MSR_FP +#endif + mtmsr r3 + SYNC + + /* + * Push C scratch registers on the current stack. It may + * actually be the thread stack or the interrupt stack. + * Anyway we have to make it in order to be able to call C/C++ + * functions. Depending on the nesting interrupt level, we will + * switch to the right stack later. + */ + stw r5, GPR5_OFFSET(r1) + stw r6, GPR6_OFFSET(r1) + stw r7, GPR7_OFFSET(r1) + stw r8, GPR8_OFFSET(r1) + stw r9, GPR9_OFFSET(r1) + stw r10, GPR10_OFFSET(r1) + stw r11, GPR11_OFFSET(r1) + stw r12, GPR12_OFFSET(r1) + stw r13, GPR13_OFFSET(r1) + + mfcr r5 + mfctr r6 + mfxer r7 + mflr r8 + + stw r5, EXC_CR_OFFSET(r1) + stw r6, EXC_CTR_OFFSET(r1) + stw r7, EXC_XER_OFFSET(r1) + stw r8, EXC_LR_OFFSET(r1) + + /* + * Add some non volatile registers to store information + * that will be used when returning from C handler + */ + stw r14, GPR14_OFFSET(r1) + stw r15, GPR15_OFFSET(r1) + /* + * save current stack pointer location in R14 + */ + addi r14, r1, 0 + /* + * store part of _Thread_Dispatch_disable_level address in R15 + */ + addis r15,0, _Thread_Dispatch_disable_level@ha + /* + * Get current nesting level in R2 + */ + mfspr r2, SPRG0 + /* + * Check if stack switch is necessary + */ + cmpwi r2,0 + bne nested + mfspr r1, SPRG1 + +nested: + /* + * Start Incrementing nesting level in R2 + */ + addi r2,r2,1 + /* + * Start Incrementing _Thread_Dispatch_disable_level R4 = _Thread_Dispatch_disable_level + */ + lwz r6,_Thread_Dispatch_disable_level@l(r15) + /* + * store new nesting level in SPRG0 + */ + mtspr SPRG0, r2 + + addi r6, r6, 1 + mfmsr r5 + /* + * store new _Thread_Dispatch_disable_level value + */ + stw r6, _Thread_Dispatch_disable_level@l(r15) + /* + * We are now running on the interrupt stack. External and decrementer + * exceptions are still disabled. I see no purpose trying to optimize + * further assembler code. + */ + /* + * Call C exception handler for decrementer Interrupt frame is passed just + * in case... + */ + addi r3, r14, 0x8 + bl C_dispatch_irq_handler /* C_dispatch_irq_handler(cpu_interrupt_frame* r3, vector r4) */ + /* + * start decrementing nesting level. Note : do not test result against 0 + * value as an easy exit condition because if interrupt nesting level > 1 + * then _Thread_Dispatch_disable_level > 1 + */ + mfspr r2, SPRG0 + /* + * start decrementing _Thread_Dispatch_disable_level + */ + lwz r3,_Thread_Dispatch_disable_level@l(r15) + addi r2, r2, -1 /* Continue decrementing nesting level */ + addi r3, r3, -1 /* Continue decrementing _Thread_Dispatch_disable_level */ + mtspr SPRG0, r2 /* End decrementing nesting level */ + stw r3,_Thread_Dispatch_disable_level@l(r15) /* End decrementing _Thread_Dispatch_disable_level */ + cmpwi r3, 0 + /* + * switch back to original stack (done here just optimize registers + * contention. Could have been done before...) + */ + addi r1, r14, 0 + bne easy_exit /* if (_Thread_Dispatch_disable_level != 0) goto easy_exit */ + /* + * Here we are running again on the thread system stack. + * We have interrupt nesting level = _Thread_Dispatch_disable_level = 0. + * Interrupt are still disabled. Time to check if scheduler request to + * do something with the current thread... + */ + addis r4, 0, _Context_Switch_necessary@ha + lwz r5, _Context_Switch_necessary@l(r4) + cmpwi r5, 0 + bne switch + + addis r6, 0, _ISR_Signals_to_thread_executing@ha + lwz r7, _ISR_Signals_to_thread_executing@l(r6) + cmpwi r7, 0 + li r8, 0 + beq easy_exit + stw r8, _ISR_Signals_to_thread_executing@l(r6) + /* + * going to call _ThreadProcessSignalsFromIrq + * Push a complete exception like frame... + */ + stmw r16, GPR16_OFFSET(r1) + addi r3, r1, 0x8 + /* + * compute SP at exception entry + */ + addi r2, r1, EXCEPTION_FRAME_END + /* + * store it at the right place + */ + stw r2, GPR1_OFFSET(r1) + /* + * Call High Level signal handling code + */ + bl _ThreadProcessSignalsFromIrq + + + /* + * start restoring exception like frame + */ + lwz r31, EXC_CTR_OFFSET(r1) + lwz r30, EXC_XER_OFFSET(r1) + lwz r29, EXC_CR_OFFSET(r1) + lwz r28, EXC_LR_OFFSET(r1) + + mtctr r31 + mtxer r30 + mtcr r29 + mtlr r28 + + + lmw r4, GPR4_OFFSET(r1) + + + lwz r2, GPR2_OFFSET(r1) + lwz r0, GPR0_OFFSET(r1) + + /* + * Disable data and instruction translation. Make path non recoverable... + */ + mfmsr r3 + xori r3, r3, MSR_RI /*| MSR_IR | MSR_DR*/ + mtmsr r3 + SYNC + /* + * Restore rfi related settings + */ + + lwz r3, SRR1_FRAME_OFFSET(r1) + mtsrr1 r3 + lwz r3, SRR0_FRAME_OFFSET(r1) + mtsrr0 r3 + + lwz r3, GPR3_OFFSET(r1) + addi r1,r1, EXCEPTION_FRAME_END + SYNC + rfi + +switch: + bl SYM (_Thread_Dispatch) + +easy_exit: + /* + * start restoring interrupt frame + */ + lwz r3, EXC_CTR_OFFSET(r1) + lwz r4, EXC_XER_OFFSET(r1) + lwz r5, EXC_CR_OFFSET(r1) + lwz r6, EXC_LR_OFFSET(r1) + + mtctr r3 + mtxer r4 + mtcr r5 + mtlr r6 + + lwz r15, GPR15_OFFSET(r1) + lwz r14, GPR14_OFFSET(r1) + lwz r13, GPR13_OFFSET(r1) + lwz r12, GPR12_OFFSET(r1) + lwz r11, GPR11_OFFSET(r1) + lwz r10, GPR10_OFFSET(r1) + lwz r9, GPR9_OFFSET(r1) + lwz r8, GPR8_OFFSET(r1) + lwz r7, GPR7_OFFSET(r1) + lwz r6, GPR6_OFFSET(r1) + lwz r5, GPR5_OFFSET(r1) + + /* + * Disable nested exception processing, data and instruction + * translation. + */ + mfmsr r3 + xori r3, r3, MSR_RI /*| MSR_IR | MSR_DR*/ + mtmsr r3 + SYNC + + /* + * Restore rfi related settings + */ + + lwz r4, SRR1_FRAME_OFFSET(r1) + lwz r2, SRR0_FRAME_OFFSET(r1) + lwz r3, GPR3_OFFSET(r1) + lwz r0, GPR0_OFFSET(r1) + + mtsrr1 r4 + mtsrr0 r2 + lwz r4, GPR4_OFFSET(r1) + lwz r2, GPR2_OFFSET(r1) + addi r1,r1, EXCEPTION_FRAME_END + SYNC + rfi + diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq_init.c b/c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq_init.c new file mode 100644 index 0000000000..166185eac5 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq_init.c @@ -0,0 +1,150 @@ +/* irq_init.c + * + * This file contains the implementation of rtems initialization + * related to interrupt handling. + * + * CopyRight (C) 2001 valette@crf.canon.fr + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ +#include +#include +#include +#include +/* +#include +#include +#include +*/ + +extern unsigned int external_exception_vector_prolog_code_size; +extern void external_exception_vector_prolog_code(); +extern unsigned int decrementer_exception_vector_prolog_code_size; +extern void decrementer_exception_vector_prolog_code(); + +extern void BSP_panic(char *s); +extern void _BSP_Fatal_error(unsigned int v); +/* +volatile unsigned int ppc_cached_irq_mask; +*/ + +/* + * default on/off function + */ +static void nop_func(){} +/* + * default isOn function + */ +static int not_connected() {return 0;} +/* + * default possible isOn function + */ +static int connected() {return 1;} + +static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER]; +static rtems_irq_global_settings initial_config; +static rtems_irq_connect_data defaultIrq = { + /* vectorIdex, hdl , on , off , isOn */ + 0, nop_func , nop_func , nop_func , not_connected +}; +static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={ + /* + * actual priorities for interrupt : + */ + /* + * CPM Interrupts + */ + 0, 45, 63, 44, 66, 68, 35, 39, 50, 62, 34, 0, 30, 40, 52, 58, + 2, 3, 0, 5, 15, 16, 17, 18, 49, 51, 0, 0, 0, 0, 0, 0, + 6, 7, 8, 0, 11, 12, 0, 0, 20, 21, 22, 23, 0, 0, 0, 0, + 29, 31, 33, 37, 38, 41, 47, 48, 55, 56, 57, 60, 64, 65, 69, 70, + /* + * Processor exceptions handled as interrupts + */ + 0 +}; + + +/* + * Initialize CPM interrupt management + */ +void +BSP_CPM_irq_init(void) +{ + m8260.simr_l = 0; + m8260.simr_h = 0; + m8260.sipnr_l = 0xffffffff; + m8260.sipnr_h = 0xffffffff; + m8260.sicr = 0; + + /* + * Initialize the interrupt priorities. + */ + m8260.siprr = 0x05309770; /* reset value */ + m8260.scprr_h = 0x05309770; /* reset value */ + m8260.scprr_l = 0x05309770; /* reset value */ + +} + +void BSP_rtems_irq_mng_init(unsigned cpuId) +{ + rtems_raw_except_connect_data vectorDesc; + int i; + + BSP_CPM_irq_init(); + /* + * Initialize Rtems management interrupt table + */ + /* + * re-init the rtemsIrq table + */ + for (i = 0; i < BSP_IRQ_NUMBER; i++) { + rtemsIrq[i] = defaultIrq; + rtemsIrq[i].name = i; + } + /* + * Init initial Interrupt management config + */ + initial_config.irqNb = BSP_IRQ_NUMBER; + initial_config.defaultEntry = defaultIrq; + initial_config.irqHdlTbl = rtemsIrq; + initial_config.irqBase = BSP_ASM_IRQ_VECTOR_BASE; + initial_config.irqPrioTbl = irqPrioTable; + + if (!BSP_rtems_irq_mngt_set(&initial_config)) { + /* + * put something here that will show the failure... + */ + BSP_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n"); + } + + /* + * We must connect the raw irq handler for the two + * expected interrupt sources : decrementer and external interrupts. + */ + vectorDesc.exceptIndex = ASM_DEC_VECTOR; + vectorDesc.hdl.vector = ASM_DEC_VECTOR; + vectorDesc.hdl.raw_hdl = decrementer_exception_vector_prolog_code; + vectorDesc.hdl.raw_hdl_size = (unsigned) &decrementer_exception_vector_prolog_code_size; + vectorDesc.on = nop_func; + vectorDesc.off = nop_func; + vectorDesc.isOn = connected; + if (!mpc8xx_set_exception (&vectorDesc)) { + BSP_panic("Unable to initialize RTEMS decrementer raw exception\n"); + } + vectorDesc.exceptIndex = ASM_EXT_VECTOR; + vectorDesc.hdl.vector = ASM_EXT_VECTOR; + vectorDesc.hdl.raw_hdl = external_exception_vector_prolog_code; + vectorDesc.hdl.raw_hdl_size = (unsigned) &external_exception_vector_prolog_code_size; + if (!mpc8xx_set_exception (&vectorDesc)) { + BSP_panic("Unable to initialize RTEMS external raw exception\n"); + } +#ifdef TRACE_IRQ_INIT + printk("RTEMS IRQ management is now operationnal\n"); +#endif +} + diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/network/Makefile.am b/c/src/lib/libbsp/powerpc/mpc8260ads/network/Makefile.am new file mode 100644 index 0000000000..dcd5e211e7 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/network/Makefile.am @@ -0,0 +1,37 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 + +PGM = $(ARCH)/network.rel + +C_FILES = network.c if_hdlcsubr.c +C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) + +OBJS = $(C_O_FILES) + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../../../../automake/compile.am +include $(top_srcdir)/../../../../../../automake/lib.am + +# +# (OPTIONAL) Add local stuff here using += +# + +AM_CPPFLAGS += -D__INSIDE_RTEMS_BSD_TCPIP_STACK__ + +$(PGM): $(OBJS) + $(make-rel) + +# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile + +if HAS_NETWORKING +all-local: $(ARCH) $(OBJS) $(PGM) +endif + +.PRECIOUS: $(PGM) + +EXTRA_DIST = network.c + +include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/network/README b/c/src/lib/libbsp/powerpc/mpc8260ads/network/README new file mode 100644 index 0000000000..d5722557c3 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/network/README @@ -0,0 +1,55 @@ +Networking with HDLC +==================== + +Author: Andy Dachs +Date: 31st August 2001 +Surrey Satellite Technology Limited + + +The network support in this BSP is not Ethernet support. The +"network" referred to here is a point to point HDLC communication link. +The ADS board does have a 10/100 ethernet port and it would be nice to +get support for that added. + +My requirement is for a WAN so I need the ability to send IP frames over +HDLC. Ultimately this will end up as frame relay support but in the meantime +I'm simply wrapping up the IP packet inside an HDLC frame. There is no +addressing mechanism or mac address attached to the start of the frame. + +This is what is physically transmitted: + + + +The physical link consists of four lines, +TX DATA : Data transmitted +TX CLOCK: Clock for transmitted data. Data source provides clock. +RX DATA : Received data +RX CLOCK: Clock for received data. Data sink accepts clock. + +To connect two entities you require a NULL modem arrangement, i.e. TX data +and Tx clock from one end go into RX data and Rx clock on the other end. + +The MPC8260ADS side of the link is implemented using SCC3 in HDLC mode. The +TX clock is generated by BRG4. The RX clock in input to the board on the CLK5 +input. I built a LVTTL to RS422 converter. + +The other end of the link is a Windows NT PC with WANic400 synchronous +communication card. We bought the card from ImageStream +(http://www.imagestream.com/WANic400.html). You also need the NT +drivers and a cable. There are other distributors but I found these +guys helpful - and they also do Linux drivers. + +The NT WANic driver has a number of modes, one of which is ethernet emulation. +This mode is what is needed to transport IP packets in HDLC frames. + +In libnetworking/net you will find a file called if_hdlcsubr.c containing +the hdlc_input and hdlc_output routines required by network.c. This file was +created by taking out the addressing mechanisms from if_ethersubr.c in the +same directory. There are probably neater ways to do this . + + + + + + diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/network/if_hdlcsubr.c b/c/src/lib/libbsp/powerpc/mpc8260ads/network/if_hdlcsubr.c new file mode 100644 index 0000000000..d630a32a43 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/network/if_hdlcsubr.c @@ -0,0 +1,346 @@ +/* + * Created from if_ethersubr.c by Andy Dachs + * Surrey Satellite Technology Limited (SSTL), 2001 + * Modified (hacked) to support IP frames transmitted over HDLC. This + * all needs tidying up in future but it does actually work for point + * to point communications. I have an SDL WANic400 synchronous + * communications card that comes with Windows NT drivers. The drivers + * support a mode that they call "Ethernet Emulation". That simply + * puts the IP frame in an HDLC frame without any ethernet header. i.e. + * . There is no addressing beyond + * the IP header information so is only suitable for point to point links + * with a single protocol. "At some point" I will add a Frame Relay header + * but at the moment I have difficulties getting the WANic card driver's + * Frame Relay driver to work. + * + * Copyright (c) 1982, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93 + * $Id$ + */ + +#include +/*#include +#include */ +#define KERNEL +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "if_hdlcsubr.h" + + +/* +u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +*/ +#define senderr(e) { error = (e); goto bad;} + +/* + * HDLC output routine. + * Just transmit the packet (hardware adds flags and CRC) + */ +int +hdlc_output(ifp, m0, dst, rt0) + register struct ifnet *ifp; + struct mbuf *m0; + struct sockaddr *dst; + struct rtentry *rt0; +{ + short type; + int s, error = 0; + u_char edst[6]; + register struct mbuf *m = m0; + register struct rtentry *rt; + struct mbuf *mcopy = (struct mbuf *)0; +/* register struct ether_header *eh; */ + int off, len = m->m_pkthdr.len; + +/* printk( "hdlc output" ); */ +/* struct arpcom *ac = (struct arpcom *)ifp; */ + + if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) + senderr(ENETDOWN); + rt = rt0; + if (rt) { + if ((rt->rt_flags & RTF_UP) == 0) { + rt0 = rt = rtalloc1(dst, 1, 0UL); + if (rt0) + rt->rt_refcnt--; + else + senderr(EHOSTUNREACH); + } + if (rt->rt_flags & RTF_GATEWAY) { + if (rt->rt_gwroute == 0) + goto lookup; + if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { + rtfree(rt); rt = rt0; + lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, + 0UL); + if ((rt = rt->rt_gwroute) == 0) + senderr(EHOSTUNREACH); + } + } + if (rt->rt_flags & RTF_REJECT) + if (rt->rt_rmx.rmx_expire == 0 || + rtems_bsdnet_seconds_since_boot() < rt->rt_rmx.rmx_expire) + senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); + } + switch (dst->sa_family) { + + case AF_INET: +#if 0 + if (!arpresolve(ac, rt, m, dst, edst, rt0)) + return (0); /* if not yet resolved */ +#endif + + /* If broadcasting on a simplex interface, loopback a copy */ + if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) + mcopy = m_copy(m, 0, (int)M_COPYALL); + off = m->m_pkthdr.len - m->m_len; + type = htons(ETHERTYPE_IP); + break; +#if 0 + case AF_UNSPEC: + eh = (struct ether_header *)dst->sa_data; + (void)memcpy(edst, eh->ether_dhost, sizeof (edst)); + type = eh->ether_type; + break; +#endif + default: + printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, + dst->sa_family); + senderr(EAFNOSUPPORT); + } + + + if (mcopy) + (void) looutput(ifp, mcopy, dst, rt); +#if 0 + /* + * Add local net header. If no space in first mbuf, + * allocate another. + */ + M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); +#endif + + if (m == 0) + senderr(ENOBUFS); + +#if 0 + eh = mtod(m, struct ether_header *); + (void)memcpy(&eh->ether_type, &type, + sizeof(eh->ether_type)); + (void)memcpy(eh->ether_dhost, edst, sizeof (edst)); + (void)memcpy(eh->ether_shost, ac->ac_enaddr, + sizeof(eh->ether_shost)); +#endif + + s = splimp(); + /* + * Queue message on interface, and start output if interface + * not yet active. + */ + if (IF_QFULL(&ifp->if_snd)) { + IF_DROP(&ifp->if_snd); + splx(s); + senderr(ENOBUFS); + } + IF_ENQUEUE(&ifp->if_snd, m); + if ((ifp->if_flags & IFF_OACTIVE) == 0) + (*ifp->if_start)(ifp); + splx(s); + + ifp->if_obytes += len /*+ sizeof (struct ether_header)*/; + if (m->m_flags & M_MCAST) + ifp->if_omcasts++; + return (error); + +bad: + if (m) + m_freem(m); + return (error); +} + +/* + * Process a received Ethernet packet; + * the packet is in the mbuf chain m without + * the ether header, which is provided separately. + */ +void +hdlc_input(ifp, m) + struct ifnet *ifp; + struct mbuf *m; +{ + register struct ifqueue *inq; + int s; + + struct ether_header eh; + + if ((ifp->if_flags & IFF_UP) == 0) { + m_freem(m); + return; + } + ifp->if_ibytes += m->m_pkthdr.len; +/* + if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, + sizeof(etherbroadcastaddr)) == 0) + m->m_flags |= M_BCAST; + else if (eh->ether_dhost[0] & 1) + m->m_flags |= M_MCAST; +*/ + if (m->m_flags & (M_BCAST|M_MCAST)) + ifp->if_imcasts++; + + + /* + * RTEMS addition -- allow application to `tap into' + * the incoming packet stream. + */ + if (ifp->if_tap && (*ifp->if_tap)(ifp, &eh, m)) { + m_freem(m); + return; + } + + schednetisr(NETISR_IP); + inq = &ipintrq; + + + s = splimp(); + if (IF_QFULL(inq)) { + IF_DROP(inq); + m_freem(m); + } else + IF_ENQUEUE(inq, m); + splx(s); +} + +/* + * Perform common duties while attaching to interface list + */ +void +hdlc_ifattach(ifp) + register struct ifnet *ifp; +{ + register struct ifaddr *ifa; + register struct sockaddr_dl *sdl; + + ifp->if_type = IFT_ETHER; + ifp->if_addrlen = 0; + ifp->if_hdrlen = 0; + ifp->if_mtu = 2048; + if (ifp->if_baudrate == 0) + ifp->if_baudrate = 8000000; + for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) + if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && + sdl->sdl_family == AF_LINK) { + sdl->sdl_type = IFT_ETHER; + sdl->sdl_alen = ifp->if_addrlen; +/* + bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr, + LLADDR(sdl), ifp->if_addrlen); +*/ + break; + } +} + + +SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet"); + +int +hdlc_ioctl(struct ifnet *ifp, int command, caddr_t data) +{ + struct ifaddr *ifa = (struct ifaddr *) data; + struct ifreq *ifr = (struct ifreq *) data; + int error = 0; + + switch (command) { + case SIOCSIFADDR: + ifp->if_flags |= IFF_UP; + + switch (ifa->ifa_addr->sa_family) { +#if 0 +#ifdef INET + case AF_INET: + ifp->if_init(ifp->if_softc); /* before arpwhohas */ + + arp_ifinit((struct arpcom *)ifp, ifa); + break; +#endif +#endif + default: + ifp->if_init(ifp->if_softc); + break; + } + break; + + case SIOCGIFADDR: + { + struct sockaddr *sa; + + sa = (struct sockaddr *) & ifr->ifr_data; +/* + bcopy(((struct arpcom *)ifp->if_softc)->ac_enaddr, + (caddr_t) sa->sa_data, ETHER_ADDR_LEN); +*/ + } + break; + + case SIOCSIFMTU: + /* + * Set the interface MTU. + */ + if (ifr->ifr_mtu > ETHERMTU) { + error = EINVAL; + } else { + ifp->if_mtu = ifr->ifr_mtu; + } + break; + } + return (error); +} diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/network/if_hdlcsubr.h b/c/src/lib/libbsp/powerpc/mpc8260ads/network/if_hdlcsubr.h new file mode 100644 index 0000000000..48faf5a9d3 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/network/if_hdlcsubr.h @@ -0,0 +1,40 @@ +/* + * RTEMS/TCPIP driver for MPC8260 SCC HDLC networking + * + * Submitted by Andy Dachs + * (c) Surrey Satellite Technology Limited, 2001 + * + * On the ADS board the ethernet interface is connected to FCC2 + * but in my application I want TCP over HDLC (see README) + * so will use SCC3 as the network interface. I have other plans + * for the FCCs so am unlikely to add true ethernet support to + * this BSP. Contributions welcome! + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ +#ifndef __IF_HDLCSUBR_H +#define __IF_HDLCSUBR_H + + +struct ifnet; +struct mbuf; +struct sockaddr; +struct rtentry; + + + +void hdlc_ifattach __P((struct ifnet *)); +void hdlc_input __P((struct ifnet *, struct mbuf *)); +int hdlc_output __P((struct ifnet *, + struct mbuf *, struct sockaddr *, struct rtentry *)); +int hdlc_ioctl __P((struct ifnet *, int , caddr_t )); + +#endif \ No newline at end of file diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/network/network.c b/c/src/lib/libbsp/powerpc/mpc8260ads/network/network.c new file mode 100644 index 0000000000..46725bd261 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/network/network.c @@ -0,0 +1,1016 @@ +/* + * RTEMS/TCPIP driver for MPC8260 SCC + * + * Modified for MPC8260 by Andy Dachs + * Surrey Satellite Technology Limited + * + * On the ADS board the ethernet interface is connected to FCC2 + * but in my application I want TCP over HDLC (see README) + * so will use SCC3 as the network interface. I have other plans + * for the FCCs so am unlikely to add true ethernet support to + * this BSP. Contributions welcome! + * + * Modified for MPC860 by Jay Monkman (jmonkman@frasca.com) + * + * This supports ethernet on either SCC1 or the FEC of the MPC860T. + * Right now, we only do 10 Mbps, even with the FEC. The function + * rtems_m860_enet_driver_attach determines which one to use. Currently, + * only one may be used at a time. + * + * W. Eric Norum + * Saskatchewan Accelerator Laboratory + * University of Saskatchewan + * Saskatoon, Saskatchewan, CANADA + * eric@skatter.usask.ca + * + * $Id$ + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include "if_hdlcsubr.h" + +/* + * Number of interfaces supported by this driver + */ +#define NIFACES 1 + +/* + * Default number of buffer descriptors set aside for this driver. + * The number of transmit buffer descriptors has to be quite large + * since a single frame often uses four or more buffer descriptors. + */ +#define RX_BUF_COUNT 32 +#define TX_BUF_COUNT 8 +#define TX_BD_PER_BUF 4 + +#define INET_ADDR_MAX_BUF_SIZE (sizeof "255.255.255.255") + + +extern void m8xx_dump_brgs( void ); + +/* + * RTEMS event used by interrupt handler to signal daemons. + * This must *not* be the same event used by the TCP/IP task synchronization. + */ +#define INTERRUPT_EVENT RTEMS_EVENT_1 + +/* + * RTEMS event used to start transmit daemon. + * This must not be the same as INTERRUPT_EVENT. + */ +#define START_TRANSMIT_EVENT RTEMS_EVENT_2 + + +/* + * Receive buffer size -- Allow for a full ethernet packet plus CRC (1518). + * Round off to nearest multiple of RBUF_ALIGN. + */ +#define MAX_MTU_SIZE 1518 +/*#define MAX_MTU_SIZE 2050*/ +#define RBUF_ALIGN 4 +#define RBUF_SIZE ((MAX_MTU_SIZE + RBUF_ALIGN) & ~RBUF_ALIGN) + +#if (MCLBYTES < RBUF_SIZE) +# error "Driver must have MCLBYTES > RBUF_SIZE" +#endif + +/* + * Per-device data + */ +struct m8260_hdlc_struct { + struct ifnet ac_if; + struct mbuf **rxMbuf; + struct mbuf **txMbuf; + int acceptBroadcast; + int rxBdCount; + int txBdCount; + int txBdHead; + int txBdTail; + int txBdActiveCount; + m8260BufferDescriptor_t *rxBdBase; + m8260BufferDescriptor_t *txBdBase; + rtems_id rxDaemonTid; + rtems_id txDaemonTid; + + /* + * Statistics + */ + unsigned long rxNotFirst; + unsigned long rxNotLast; + unsigned long rxInterrupts; + unsigned long rxGiant; + unsigned long rxNonOctet; + unsigned long rxAbort; + unsigned long rxBadCRC; + unsigned long rxOverrun; + unsigned long rxLostCarrier; + unsigned long txInterrupts; + unsigned long txUnderrun; + unsigned long txLostCarrier; + unsigned long txRawWait; +}; +static struct m8260_hdlc_struct hdlc_driver[NIFACES]; + + +static void m8xx_scc3_hdlc_on(const rtems_irq_connect_data* ptr) +{ +} + +static void m8xx_scc3_hdlc_off(const rtems_irq_connect_data* ptr) +{ + /* + * Please put relevant code there + */ +} + +static int m8xx_scc3_hdlc_isOn(const rtems_irq_connect_data* ptr) +{ + return BSP_irq_enabled_at_cpm (ptr->name); +} + +/* + * SCC interrupt handler + * TBD: Can we work out which SCC generated the interrupt from the + * value of v? If so we can use the same handler for multiple + * SCCs. + */ +static void +m8xx_scc3_interrupt_handler () +{ + /* + * Frame received? + */ + if ((m8260.scc3.sccm & M8260_SCCE_RXF) && + (m8260.scc3.scce & M8260_SCCE_RXF) ) { + m8260.scc3.scce = M8260_SCCE_RXF; +/* m8260.scc3.sccm &= ~M8260_SCCE_RXF; */ + hdlc_driver[0].rxInterrupts++; + rtems_event_send (hdlc_driver[0].rxDaemonTid, INTERRUPT_EVENT); +/* + printk( "Rx " ); +*/ + } + + /* + * Buffer transmitted or transmitter error? + */ + if ((m8260.scc3.sccm & (M8260_SCCE_TX | M8260_SCCE_TXE) ) && + (m8260.scc3.scce & (M8260_SCCE_TX | M8260_SCCE_TXE) )) { + m8260.scc3.scce = M8260_SCCE_TX | M8260_SCCE_TXE; +/* m8260.scc3.sccm &= ~(M8260_SCCE_TX | M8260_SCCE_TXE); */ + hdlc_driver[0].txInterrupts++; + rtems_event_send (hdlc_driver[0].txDaemonTid, INTERRUPT_EVENT); +/* + printk( "Tx " ); +*/ + } + +#if 0 + m8260.sipnr_l = M8260_SIMASK_SCC3; /* Clear SCC3 interrupt-in-service bit */ +#endif +} + + +static rtems_irq_connect_data hdlcSCC3IrqData = { + BSP_CPM_IRQ_SCC3, + (rtems_irq_hdl) m8xx_scc3_interrupt_handler, + (rtems_irq_enable) m8xx_scc3_hdlc_on, + (rtems_irq_disable) m8xx_scc3_hdlc_off, + (rtems_irq_is_enabled)m8xx_scc3_hdlc_isOn +}; + + +/* + * Initialize the SCC hardware + * Configure I/O ports for SCC3 + * Internal Tx clock, External Rx clock + */ +static void +m8260_scc_initialize_hardware (struct m8260_hdlc_struct *sc) +{ + int i; + int brg; + +/* + unsigned char *hwaddr; +*/ + rtems_status_code status; +/* + rtems_isr_entry old_handler; +*/ + + /* RxD PB14 */ + m8260.pparb |= 0x00020000; + m8260.psorb &= ~0x00020000; + m8260.pdirb &= ~0x00020000; + + /* RxC (CLK5) PC27 */ + m8260.pparc |= 0x00000010; + m8260.psorc &= ~0x00000010; + m8260.pdirc &= ~0x00000010; + + /* TxD PD24 and TxC PD10 (BRG4) */ + m8260.ppard |= 0x00200080; + m8260.psord |= 0x00200000; + m8260.psord &= ~0x00000080; + m8260.pdird |= 0x00200080; + + + /* External Rx Clock from CLK5 */ + if( m8xx_get_clk( M8xx_CLK_5 ) == -1 ) + printk( "Error allocating CLK5 for network device.\n" ); + else + m8260.cmxscr |= 0x00002000; + + /* Internal Tx Clock from BRG4 */ + if( (brg = m8xx_get_brg(M8xx_BRG_4, 8000000 )) == -1 ) + printk( "Error allocating BRG for network device\n" ); + else + m8260.cmxscr |= ((unsigned)brg << 8); + + + + /* + * Allocate mbuf pointers + */ + sc->rxMbuf = malloc (sc->rxBdCount * sizeof *sc->rxMbuf, + M_MBUF, M_NOWAIT); + sc->txMbuf = malloc (sc->txBdCount * sizeof *sc->txMbuf, + M_MBUF, M_NOWAIT); + if (!sc->rxMbuf || !sc->txMbuf) + rtems_panic ("No memory for mbuf pointers"); + + /* + * Set receiver and transmitter buffer descriptor bases + */ + sc->rxBdBase = m8xx_bd_allocate (sc->rxBdCount); + sc->txBdBase = m8xx_bd_allocate (sc->txBdCount); + + m8260.scc3p.rbase = (char *)sc->rxBdBase - (char *)&m8260; + m8260.scc3p.tbase = (char *)sc->txBdBase - (char *)&m8260; + + /* + * Send "Init parameters" command + */ + + m8xx_cp_execute_cmd (M8260_CR_OP_INIT_RX_TX | M8260_CR_SCC3 ); + + /* + * Set receive and transmit function codes + */ + m8260.scc3p.rfcr = M8260_RFCR_MOT | M8260_RFCR_60X_BUS; + m8260.scc3p.tfcr = M8260_TFCR_MOT | M8260_TFCR_60X_BUS; + + /* + * Set maximum receive buffer length + */ + m8260.scc3p.mrblr = RBUF_SIZE; + + + m8260.scc3p.un.hdlc.c_mask = 0xF0B8; + m8260.scc3p.un.hdlc.c_pres = 0xFFFF; + m8260.scc3p.un.hdlc.disfc = 0; + m8260.scc3p.un.hdlc.crcec = 0; + m8260.scc3p.un.hdlc.abtsc = 0; + m8260.scc3p.un.hdlc.nmarc = 0; + m8260.scc3p.un.hdlc.retrc = 0; + m8260.scc3p.un.hdlc.rfthr = 1; + m8260.scc3p.un.hdlc.mflr = RBUF_SIZE; + + m8260.scc3p.un.hdlc.hmask = 0x0000; /* promiscuous */ + + m8260.scc3p.un.hdlc.haddr1 = 0xFFFF; /* Broadcast address */ + m8260.scc3p.un.hdlc.haddr2 = 0xFFFF; /* Station address */ + m8260.scc3p.un.hdlc.haddr3 = 0xFFFF; /* Dummy */ + m8260.scc3p.un.hdlc.haddr4 = 0xFFFF; /* Dummy */ + + + /* + * Send "Init parameters" command + */ +/* + m8xx_cp_execute_cmd (M8260_CR_OP_INIT_RX_TX | M8260_CR_SCC3 ); +*/ + + /* + * Set up receive buffer descriptors + */ + for (i = 0 ; i < sc->rxBdCount ; i++) { + (sc->rxBdBase + i)->status = 0; + } + + /* + * Set up transmit buffer descriptors + */ + for (i = 0 ; i < sc->txBdCount ; i++) { + (sc->txBdBase + i)->status = 0; + sc->txMbuf[i] = NULL; + } + sc->txBdHead = sc->txBdTail = 0; + sc->txBdActiveCount = 0; + + + m8260.scc3.sccm = 0; /* No interrupts unmasked till necessary */ + + /* + * Clear any outstanding events + */ + m8260.scc3.scce = 0xFFFF; + + /* + * Set up interrupts + */ + status = BSP_install_rtems_irq_handler (&hdlcSCC3IrqData); +/* + printk( "status = %d, Success = %d\n", status, RTEMS_SUCCESSFUL ); +*/ + if (status != 1 /*RTEMS_SUCCESSFUL*/ ) { + rtems_panic ("Can't attach M8260 SCC3 interrupt handler: %s\n", + rtems_status_text (status)); + } + m8260.scc3.sccm = 0; /* No interrupts unmasked till necessary */ + +#if 0 + /* + * Set up interrupts + */ + status = rtems_interrupt_catch (m8260_scc3_interrupt_handler, + PPC_IRQ_CPM_SCC3, + &old_handler); + if (status != RTEMS_SUCCESSFUL) { + rtems_panic ("Can't attach M8260 SCC3 interrupt handler: %s\n", + rtems_status_text (status)); + } + + m8260.sipnr_l = M8260_SIMASK_SCC3; /* clear pending event */ + m8260.simr_l |= M8260_SIMASK_SCC3; /* Enable SCC interrupt */ + +#endif + + + + m8260.scc3.gsmr_h = 0; + m8260.scc3.gsmr_l = 0x10000000; + m8260.scc3.dsr = 0x7E7E; /* flag character */ + m8260.scc3.psmr = 0x2000; /* 2 flags between Tx'd frames */ + +/* printk("scc3 init\n" ); */ + + m8260.scc3.gsmr_l |= 0x00000030; /* Set ENR and ENT to enable Rx and Tx */ + +} + + + +/* + * Soak up buffer descriptors that have been sent + * Note that a buffer descriptor can't be retired as soon as it becomes + * ready. The MC68360 Errata (May 96) says that, "If an Ethernet frame is + * made up of multiple buffers, the user should not reuse the first buffer + * descriptor until the last buffer descriptor of the frame has had its + * ready bit cleared by the CPM". + */ +static void +m8260Enet_retire_tx_bd (struct m8260_hdlc_struct *sc) +{ + rtems_unsigned16 status; + int i; + int nRetired; + struct mbuf *m, *n; + + i = sc->txBdTail; + nRetired = 0; + while ((sc->txBdActiveCount != 0) + && (((status = (sc->txBdBase + i)->status) & M8260_BD_READY) == 0)) { + /* + * See if anything went wrong + */ + if (status & (M8260_BD_UNDERRUN | + M8260_BD_CTS_LOST)) { + /* + * Check for errors which stop the transmitter. + */ + if( status & M8260_BD_UNDERRUN ) { + hdlc_driver[0].txUnderrun++; + + /* + * Restart the transmitter + */ + /* FIXME: this should get executed only if using the SCC */ + m8xx_cp_execute_cmd (M8260_CR_OP_RESTART_TX | M8260_CR_SCC3); + } + if (status & M8260_BD_CTS_LOST) + hdlc_driver[0].txLostCarrier++; + } + nRetired++; + if (status & M8260_BD_LAST) { + /* + * A full frame has been transmitted. + * Free all the associated buffer descriptors. + */ + sc->txBdActiveCount -= nRetired; + while (nRetired) { + nRetired--; + m = sc->txMbuf[sc->txBdTail]; + MFREE (m, n); + if (++sc->txBdTail == sc->txBdCount) + sc->txBdTail = 0; + } + } + if (++i == sc->txBdCount) + i = 0; + } +} + +/* + * reader task + */ +static void +scc_rxDaemon (void *arg) +{ + struct m8260_hdlc_struct *sc = (struct m8260_hdlc_struct *)arg; + struct ifnet *ifp = &sc->ac_if; + struct mbuf *m; + rtems_unsigned16 status; + m8260BufferDescriptor_t *rxBd; + int rxBdIndex; + + /* + * Allocate space for incoming packets and start reception + */ + for (rxBdIndex = 0 ; ;) { + rxBd = sc->rxBdBase + rxBdIndex; + MGETHDR (m, M_WAIT, MT_DATA); + MCLGET (m, M_WAIT); + m->m_pkthdr.rcvif = ifp; + sc->rxMbuf[rxBdIndex] = m; + rxBd->buffer = mtod (m, void *); + rxBd->status = M8260_BD_EMPTY | M8260_BD_INTERRUPT; + if (++rxBdIndex == sc->rxBdCount) { + rxBd->status |= M8260_BD_WRAP; + break; + } + } + +/* + m8260.scc3.sccm |= M8260_SCCE_RXF; +*/ + + /* + * Input packet handling loop + */ + rxBdIndex = 0; + for (;;) { + rxBd = sc->rxBdBase + rxBdIndex; + + /* + * Wait for packet if there's not one ready + */ + if ((status = rxBd->status) & M8260_BD_EMPTY) { + /* + * Clear old events + */ + + m8260.scc3.scce = M8260_SCCE_RXF; + + /* + * Wait for packet + * Note that the buffer descriptor is checked + * *before* the event wait -- this catches the + * possibility that a packet arrived between the + * `if' above, and the clearing of the event register. + */ + while ((status = rxBd->status) & M8260_BD_EMPTY) { + rtems_event_set events; + + /* + * Unmask RXF (Full frame received) event + */ + m8260.scc3.sccm |= M8260_SCCE_RXF; + +/* printk( "Rxdwait "); */ + + rtems_bsdnet_event_receive (INTERRUPT_EVENT, + RTEMS_WAIT|RTEMS_EVENT_ANY, + RTEMS_NO_TIMEOUT, + &events); + +/* printk( "Rxd " ); */ + } + } + + /* + * Check that packet is valid + */ + if ((status & (M8260_BD_LAST | + M8260_BD_FIRST_IN_FRAME | + M8260_BD_LONG | + M8260_BD_NONALIGNED | + M8260_BD_ABORT | + M8260_BD_CRC_ERROR | + M8260_BD_OVERRUN /*| + M8260_BD_CARRIER_LOST*/)) == + (M8260_BD_LAST | + M8260_BD_FIRST_IN_FRAME ) ) { + +/* printk( "RxV " ); */ + +/* + * Invalidate the buffer for this descriptor + */ + + rtems_cache_invalidate_multiple_data_lines(rxBd->buffer, rxBd->length); + + m = sc->rxMbuf[rxBdIndex]; + + /* strip off HDLC CRC */ + m->m_len = m->m_pkthdr.len = rxBd->length - sizeof(rtems_unsigned16); + + hdlc_input( ifp, m ); + + /* + * Allocate a new mbuf + */ + MGETHDR (m, M_WAIT, MT_DATA); + MCLGET (m, M_WAIT); + m->m_pkthdr.rcvif = ifp; + sc->rxMbuf[rxBdIndex] = m; + rxBd->buffer = mtod (m, void *); + } + else { + printk( "RxErr[%04X,%d]", status, rxBd->length ); + /* + * Something went wrong with the reception + */ + if (!(status & M8260_BD_LAST)) + sc->rxNotLast++; + if (!(status & M8260_BD_FIRST_IN_FRAME)) + sc->rxNotFirst++; + + if (status & M8260_BD_LONG) + sc->rxGiant++; + if (status & M8260_BD_NONALIGNED) + sc->rxNonOctet++; + if (status & M8260_BD_ABORT) + sc->rxAbort++; + if (status & M8260_BD_CRC_ERROR) + sc->rxBadCRC++; + if (status & M8260_BD_OVERRUN) + sc->rxOverrun++; + if (status & M8260_BD_CARRIER_LOST) + sc->rxLostCarrier++; + } + + /* + * Reenable the buffer descriptor + */ + rxBd->status = (status & (M8260_BD_WRAP | M8260_BD_INTERRUPT)) | + M8260_BD_EMPTY; + + /* + * Move to next buffer descriptor + */ + if (++rxBdIndex == sc->rxBdCount) + rxBdIndex = 0; + } +} + + +static void +scc_sendpacket (struct ifnet *ifp, struct mbuf *m) +{ + struct m8260_hdlc_struct *sc = ifp->if_softc; + volatile m8260BufferDescriptor_t *firstTxBd, *txBd; + struct mbuf *l = NULL; + rtems_unsigned16 status; + int nAdded; + + /* + * Free up buffer descriptors + */ + m8260Enet_retire_tx_bd (sc); + + /* + * Set up the transmit buffer descriptors. + * No need to pad out short packets since the + * hardware takes care of that automatically. + * No need to copy the packet to a contiguous buffer + * since the hardware is capable of scatter/gather DMA. + */ + nAdded = 0; + txBd = firstTxBd = sc->txBdBase + sc->txBdHead; + +/* + m8260.scc3.sccm |= (M8260_SCCE_TX | M8260_SCCE_TXE); +*/ + + for (;;) { + /* + * Wait for buffer descriptor to become available. + */ + if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { + /* + * Clear old events + */ + m8260.scc3.scce = M8260_SCCE_TX | M8260_SCCE_TXE; + + /* + * Wait for buffer descriptor to become available. + * Note that the buffer descriptors are checked + * *before* * entering the wait loop -- this catches + * the possibility that a buffer descriptor became + * available between the `if' above, and the clearing + * of the event register. + * This is to catch the case where the transmitter + * stops in the middle of a frame -- and only the + * last buffer descriptor in a frame can generate + * an interrupt. + */ + m8260Enet_retire_tx_bd (sc); + while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { + rtems_event_set events; + + /* + * Unmask TX (buffer transmitted) event + */ + m8260.scc3.sccm |= (M8260_SCCE_TX | M8260_SCCE_TXE); + + rtems_bsdnet_event_receive (INTERRUPT_EVENT, + RTEMS_WAIT|RTEMS_EVENT_ANY, + RTEMS_NO_TIMEOUT, + &events); + m8260Enet_retire_tx_bd (sc); + } + } + + /* + * Don't set the READY flag till the + * whole packet has been readied. + */ + status = nAdded ? M8260_BD_READY : 0; + + /* + * FIXME: Why not deal with empty mbufs at at higher level? + * The IP fragmentation routine in ip_output + * can produce packet fragments with zero length. + * I think that ip_output should be changed to get + * rid of these zero-length mbufs, but for now, + * I'll deal with them here. + */ + if (m->m_len) { + /* + * Fill in the buffer descriptor + */ + + txBd->buffer = mtod (m, void *); + txBd->length = m->m_len; + + + /* + * Flush the buffer for this descriptor + */ + + rtems_cache_flush_multiple_data_lines(txBd->buffer, txBd->length); + + +/* throw off the header for Ethernet Emulation mode */ +/* + txBd->buffer = mtod (m, void *); + txBd->buffer += sizeof( struct ether_header ) + 2; + txBd->length = m->m_len - sizeof( struct ether_header ) - 2; +*/ + sc->txMbuf[sc->txBdHead] = m; + nAdded++; + if (++sc->txBdHead == sc->txBdCount) { + status |= M8260_BD_WRAP; + sc->txBdHead = 0; + } + l = m; + m = m->m_next; + } + else { + /* + * Just toss empty mbufs + */ + struct mbuf *n; + MFREE (m, n); + m = n; + if (l != NULL) + l->m_next = m; + } + + /* + * Set the transmit buffer status. + * Break out of the loop if this mbuf is the last in the frame. + */ + if (m == NULL) { + if (nAdded) { + status |= M8260_BD_LAST | M8260_BD_TX_CRC | M8260_BD_INTERRUPT; + txBd->status = status; + firstTxBd->status |= M8260_BD_READY; + sc->txBdActiveCount += nAdded; + } + break; + } + txBd->status = status; + txBd = sc->txBdBase + sc->txBdHead; + } +} + + +/* + * Driver transmit daemon + */ +void +scc_txDaemon (void *arg) +{ + struct m8260_hdlc_struct *sc = (struct m8260_hdlc_struct *)arg; + struct ifnet *ifp = &sc->ac_if; + struct mbuf *m; + rtems_event_set events; + + for (;;) { + /* + * Wait for packet + */ + rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events); + + /* + * Send packets till queue is empty + */ + for (;;) { + /* + * Get the next mbuf chain to transmit. + */ + IF_DEQUEUE(&ifp->if_snd, m); + if (!m) + break; + + + scc_sendpacket (ifp, m); + + + } + ifp->if_flags &= ~IFF_OACTIVE; + } +} + + +/* + * Send packet (caller provides header). + */ +static void +m8260_hdlc_start (struct ifnet *ifp) +{ + struct m8260_hdlc_struct *sc = ifp->if_softc; + + rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT); + ifp->if_flags |= IFF_OACTIVE; +} + +/* + * Initialize and start the device + */ +static void +scc_init (void *arg) +{ + struct m8260_hdlc_struct *sc = arg; + struct ifnet *ifp = &sc->ac_if; + + if (sc->txDaemonTid == 0) { + + /* + * Set up SCC hardware + */ + m8260_scc_initialize_hardware (sc); + + /* + * Start driver tasks + */ + sc->txDaemonTid = rtems_bsdnet_newproc ("SCtx", 4096, scc_txDaemon, sc); + sc->rxDaemonTid = rtems_bsdnet_newproc ("SCrx", 4096, scc_rxDaemon, sc); + + } + +#if 0 + /* + * Set flags appropriately + */ + if (ifp->if_flags & IFF_PROMISC) + m8260.scc3.psmr |= 0x200; + else + m8260.scc3.psmr &= ~0x200; +#endif + + /* + * Tell the world that we're running. + */ + ifp->if_flags |= IFF_RUNNING; + + /* + * Enable receiver and transmitter + */ + m8260.scc3.gsmr_l |= 0x30; +} + + + +/* + * Stop the device + */ +static void +scc_stop (struct m8260_hdlc_struct *sc) +{ + struct ifnet *ifp = &sc->ac_if; + + ifp->if_flags &= ~IFF_RUNNING; + + /* + * Shut down receiver and transmitter + */ + m8260.scc3.gsmr_l &= ~0x30; +} + + +/* + * Show interface statistics + */ +static void +hdlc_stats (struct m8260_hdlc_struct *sc) +{ + printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); + printf (" Giant:%-8lu", sc->rxGiant); + printf (" Non-octet:%-8lu\n", sc->rxNonOctet); + printf (" Bad CRC:%-8lu", sc->rxBadCRC); + printf (" Overrun:%-8lu", sc->rxOverrun); + printf (" No Carrier:%-8lu\n", sc->rxLostCarrier); + printf (" Discarded:%-8lu\n", (unsigned long)m8260.scc3p.un.hdlc.disfc); + + printf (" Tx Interrupts:%-8lu", sc->txInterrupts); + printf (" No Carrier:%-8lu", sc->txLostCarrier); + printf (" Underrun:%-8lu\n", sc->txUnderrun); + printf (" Raw output wait:%-8lu\n", sc->txRawWait); +} + +/* + * Driver ioctl handler + */ +static int +scc_ioctl (struct ifnet *ifp, int command, caddr_t data) +{ + struct m8260_hdlc_struct *sc = ifp->if_softc; + int error = 0; + + switch (command) { + case SIOCGIFADDR: + case SIOCSIFADDR: + hdlc_ioctl (ifp, command, data); + break; + + case SIOCSIFFLAGS: + switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { + case IFF_RUNNING: + scc_stop (sc); + break; + + case IFF_UP: + scc_init (sc); + break; + + case IFF_UP | IFF_RUNNING: + scc_stop (sc); + scc_init (sc); + break; + + default: + break; + } + break; + + case SIO_RTEMS_SHOW_STATS: + hdlc_stats (sc); + break; + + /* + * FIXME: All sorts of multicast commands need to be added here! + */ + default: + error = EINVAL; + break; + } + return error; +} + + + +/* + * Attach an SCC driver to the system + */ +int +rtems_scc3_driver_attach (struct rtems_bsdnet_ifconfig *config) +{ + struct m8260_hdlc_struct *sc; + struct ifnet *ifp; + int mtu; + int i; + + /* + * Find a free driver + */ + for (i = 0 ; i < NIFACES ; i++) { + sc = &hdlc_driver[i]; + ifp = &sc->ac_if; + if (ifp->if_softc == NULL) + break; + } + if (i >= NIFACES) { + printf ("Too many SCC drivers.\n"); + return 0; + } + +#if 0 + /* + * Process options + */ + + if (config->hardware_address) { + memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); + } + else { + sc->arpcom.ac_enaddr[0] = 0x44; + sc->arpcom.ac_enaddr[1] = 0x22; + sc->arpcom.ac_enaddr[2] = 0x33; + sc->arpcom.ac_enaddr[3] = 0x33; + sc->arpcom.ac_enaddr[4] = 0x22; + sc->arpcom.ac_enaddr[5] = 0x44; + } +#endif + + if (config->mtu) + mtu = config->mtu; + else + mtu = ETHERMTU; + if (config->rbuf_count) + sc->rxBdCount = config->rbuf_count; + else + sc->rxBdCount = RX_BUF_COUNT; + if (config->xbuf_count) + sc->txBdCount = config->xbuf_count; + else + sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF; + sc->acceptBroadcast = !config->ignore_broadcast; + + /* + * Set up network interface values + */ + ifp->if_softc = sc; + ifp->if_unit = i + 1; + ifp->if_name = "eth"; + ifp->if_mtu = mtu; + ifp->if_init = scc_init; + ifp->if_ioctl = scc_ioctl; + ifp->if_start = m8260_hdlc_start; + ifp->if_output = hdlc_output; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | /*IFF_PROMISC |*/ IFF_NOARP; + if (ifp->if_snd.ifq_maxlen == 0) + ifp->if_snd.ifq_maxlen = ifqmaxlen; + + /* + * Attach the interface + */ + if_attach (ifp); + hdlc_ifattach (ifp); + return 1; +}; + + +int +rtems_enet_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching) +{ + return rtems_scc3_driver_attach( config ); + +/* + if ((m8260.fec.mii_data & 0xffff) == 0x2000) { + return rtems_fec_driver_attach(config); + } + else { + return rtems_scc1_driver_attach(config); + } +*/ +} diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/start/Makefile.am b/c/src/lib/libbsp/powerpc/mpc8260ads/start/Makefile.am new file mode 100644 index 0000000000..86053b9e99 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/start/Makefile.am @@ -0,0 +1,33 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 + +PGM = $(ARCH)/start.o + +S_FILES = start.S +S_O_FILES = $(S_FILES:%.S=$(ARCH)/%.o) + +OBJS = $(S_O_FILES) + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../../../../automake/compile.am +include $(top_srcdir)/../../../../../../automake/lib.am + +# +# (OPTIONAL) Add local stuff here using += +# + +$(PROJECT_RELEASE)/lib/start$(LIB_VARIANT).o: $(PGM) + $(INSTALL_DATA) $< $@ + +TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/start$(LIB_VARIANT).o + +all-local: $(ARCH) $(OBJS) $(PGM) $(TMPINSTALL_FILES) + +.PRECIOUS: $(PGM) + +EXTRA_DIST = start.S + +include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/start/start.S b/c/src/lib/libbsp/powerpc/mpc8260ads/start/start.S new file mode 100644 index 0000000000..b517c175c9 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/start/start.S @@ -0,0 +1,191 @@ +/* start.S + * + * $Id$ + * + * Modified for the Motorola PQII ADS board by + * Andy Dachs 23-11-00. + * Surrey Satellite Technology Limited + * + * I have a proprietary bootloader programmed into the flash + * on the board which initialises the SDRAM prior to calling + * this function. + * + * This file is based on the one by Jay Monkman (jmonkman@fracsa.com) + * which in turn was based on the dlentry.s file for the Papyrus BSP, + * written by: + * + * Author: Andrew Bray + * + * COPYRIGHT (c) 1995 by i-cubed ltd. + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of i-cubed limited not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * i-cubed limited makes no representations about the suitability + * of this software for any purpose. + * + */ + +#include "asm.h" + +/* + * The initial stack is set to run BELOW the code base address. + * (between the vectors and text sections) + * + * The entry veneer has to clear the BSS and copy the read only + * version of the data segment to the correct location. + */ + + + .section ".entry" /* This might have to be the first thing in the + * text section. At one time, it had to be + * first, but I don't believe it is true + * any more. */ + PUBLIC_VAR (start) +SYM(start): + bl .startup +base_addr: + +/* + * Parameters from linker + */ +toc_pointer: + .long s.got +bss_length: + .long bss.size +bss_addr: + .long bss.start + +PUBLIC_VAR (data_length ) +data_length: + .long data.size +PUBLIC_VAR (data_addr ) +data_addr: + .long data.start + + + +PUBLIC_VAR (text_addr) +text_addr: + .long text.start + +PUBLIC_VAR (text_length) +text_length: + .long text.size + + +/* + * Initialization code + */ +.startup: + /* Get start address */ + mflr r1 + + + /* -------------------------------------------------- + * Clear MSR[EE] to disable interrupts + * Clear MSR[IP] bit to put vectors at 0x00000000 + * Set MSR[FP] to enable FPU - not on my eval board! + * -------------------------------------------------- */ + mfmsr r5 + lis r13, 0xFFFF + ori r13, r13, 0x7FBF + and r5, r5, r13 /* Clear EE and IP */ +#if 1 + ori r5, r5, 0x2000 /* Enable FPU */ +#endif + mtmsr r5 + + + + +#ifdef ENABLE_CACHE + /* Enable caches */ + mfspr r5, 1008 + ori r5, r5, 0x8000 + isync + mtspr 1008, r5 + +/* Leave D-cache disabled for now */ +#if 0 + ori r5, r5, 0x4000 + sync + mtspr 1008, r5 +#endif +#endif + + + /*-------------------------------------------------- + * Set up the power management modes + * The 8260 has a dynamic power management mode that + * is automatically invoked if the unit is idle. + * We invoke the NAP mode in the RTEMS idle task. + *-------------------------------------------------- */ + + lis r13, 0x0050 /* set nap mode and DPM */ + or r5, r5, r13 + mtspr 1008, r5 + + /*-------------------------------------------------- + * + *-------------------------------------------------- */ + + + + /* clear the bss section */ + bl bssclr + + +/* + * C_setup. + */ + + /* set toc */ + lwz r2, toc_pointer-base_addr(r1) + + /* Set up stack pointer = beginning of text section - 56 */ + addi r1, r1, -56-4 + + + /* clear argc and argv */ + xor r3, r3, r3 + xor r4, r4, r4 + + .extern SYM (boot_card) + bl SYM (boot_card) /* call the first C routine */ + + + + /* we don't expect to return from boot_card but if we do */ + /* wait here for watchdog to kick us into hard reset */ + + +twiddle: + b twiddle + + +/* + * bssclr - zero out bss + */ +bssclr: + lwz r4, bss_addr-base_addr(r1) /* Start of bss */ + lwz r5, bss_length-base_addr(r1) /* Length of bss */ + + rlwinm. r5,r5,30,0x3FFFFFFF /* form length/4 */ + beqlr /* no bss */ + mtctr r5 /* set ctr reg */ + xor r6,r6,r6 /* r6 = 0 */ +clear_bss: + stswi r6,r4,0x4 /* store r6 */ + addi r4,r4,0x4 /* update r2 */ + + bdnz clear_bss /* dec counter and loop */ + blr /* return */ + + + diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/startup/Makefile.am b/c/src/lib/libbsp/powerpc/mpc8260ads/startup/Makefile.am new file mode 100644 index 0000000000..4291994005 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/startup/Makefile.am @@ -0,0 +1,43 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 + +VPATH = @srcdir@:@srcdir@/../../../shared + +PGM = $(ARCH)/startup.rel + +C_FILES = bspclean.c bsplibc.c bsppost.c bspstart.c bootcard.c \ + main.c sbrk.c setvec.c gnatinstallhandler.c cpuinit.c +C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) + +S_FILES = +S_O_FILES = $(S_FILES:%.s=$(ARCH)/%.o) + +OBJS = $(C_O_FILES) $(S_O_FILES) + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../../../../automake/compile.am +include $(top_srcdir)/../../../../../../automake/lib.am + +# +# (OPTIONAL) Add local stuff here using += +# + +$(PGM): $(OBJS) + $(make-rel) + +$(PROJECT_RELEASE)/lib/linkcmds: linkcmds + $(INSTALL_DATA) $< $@ + +# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile +TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/linkcmds + +all-local: $(ARCH) $(OBJS) $(PGM) $(TMPINSTALL_FILES) + +.PRECIOUS: $(PGM) + +EXTRA_DIST = bspstart.c linkcmds setvec.c + +include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/startup/bspstart.c b/c/src/lib/libbsp/powerpc/mpc8260ads/startup/bspstart.c new file mode 100644 index 0000000000..ebb8bf917b --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/startup/bspstart.c @@ -0,0 +1,370 @@ +/* bsp_start() + * + * This routine starts the application. It includes application, + * board, and monitor specific initialization and configuration. + * The generic CPU dependent initialization has been performed + * before this routine is invoked. + * + * The MPC860 specific stuff was written by Jay Monkman (jmonkman@frasca.com) + * + * Modified for the MPC8260ADS board by Andy Dachs + * Surrey Satellite Technology Limited, 2001 + * A 40MHz system clock is assumed. + * The PON. RST.CONF. Dip switches (DS1) are + * 1 - Off + * 2 - On + * 3 - Off + * 4 - On + * 5 - Off + * 6 - Off + * 7 - Off + * 8 - Off + * Dip switches on DS2 and DS3 are all set to ON + * The LEDs on the board are used to signal panic and fatal_error + * conditions. + * The mmu is unused at this time. + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include + +/* +#include +*/ + +#include +#include +#include +#include + +#include + +#ifdef STACK_CHECKER_ON +#include +#endif + + + +/* + * 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; +extern unsigned long intrStackPtr; +rtems_configuration_table BSP_Configuration; + +rtems_cpu_table Cpu_table; + +char *rtems_progname; + + +/* + * Use the shared implementations of the following routines. + * Look in rtems/c/src/lib/libbsp/shared/bsppost.c and + * rtems/c/src/lib/libbsp/shared/bsplibc.c. + */ +void bsp_postdriver_hook(void); +void bsp_libc_init( void *, unsigned32, int ); + + +void BSP_panic(char *s) +{ + _BSP_GPLED1_on(); + printk("%s PANIC %s\n",_RTEMS_version, s); + __asm__ __volatile ("sc"); +} + +void _BSP_Fatal_error(unsigned int v) +{ + _BSP_GPLED0_on(); + _BSP_GPLED1_on(); + printk("%s PANIC ERROR %x\n",_RTEMS_version, v); + __asm__ __volatile ("sc"); +} + +void _BSP_GPLED0_on() +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr0 &= ~GP0_LED; /* Turn on GP0 LED */ +} + +void _BSP_GPLED0_off() +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr0 |= GP0_LED; /* Turn off GP0 LED */ +} + +void _BSP_GPLED1_on() +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr0 &= ~GP1_LED; /* Turn on GP1 LED */ +} + +void _BSP_GPLED1_off() +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr0 |= GP1_LED; /* Turn off GP1 LED */ +} + +void _BSP_Uart1_enable() +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr1 &= ~UART1_E; /* Enable Uart1 */ +} + +void _BSP_Uart1_disable() +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr1 |= UART1_E; /* Disable Uart1 */ +} + +void _BSP_Uart2_enable() +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr1 &= ~UART2_E; /* Enable Uart2 */ +} + +void _BSP_Uart2_disable() +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr1 |= UART2_E; /* Disable Uart2 */ + +} + + + + + + +extern void m8260_console_reserve_resources(rtems_configuration_table *); + + +/* + * Function: bsp_pretasking_hook + * Created: 95/03/10 + * + * Description: + * BSP pretasking hook. Called just before drivers are initialized. + * Used to setup libc and install any BSP extensions. + * + * NOTES: + * Must not use libc (to do io) from here, since drivers are + * not yet initialized. + * + */ + +void +bsp_pretasking_hook(void) +{ + /* + * These are assigned addresses in the linkcmds file for the BSP. This + * approach is better than having these defined as manifest constants and + * compiled into the kernel, but it is still not ideal when dealing with + * multiprocessor configuration in which each board as a different memory + * map. A better place for defining these symbols might be the makefiles. + * Consideration should also be given to developing an approach in which + * the kernel and the application can be linked and burned into ROM + * independently of each other. + */ + extern unsigned char _HeapStart; + extern unsigned char _HeapEnd; + + bsp_libc_init( &_HeapStart, &_HeapEnd - &_HeapStart, 0 ); + + + +#ifdef STACK_CHECKER_ON + /* + * Initialize the stack bounds checker + * We can either turn it on here or from the app. + */ + + Stack_check_Initialize(); +#endif + +#ifdef RTEMS_DEBUG + rtems_debug_enable( RTEMS_DEBUG_ALL_MASK ); +#endif +} + + +void bsp_start(void) +{ + extern void *_WorkspaceBase; + extern int _end; + rtems_unsigned32 heap_start; + rtems_unsigned32 ws_start; + ppc_cpu_id_t myCpu; + ppc_cpu_revision_t myCpuRevision; + register unsigned char* intrStack; + register unsigned int intrNestingLevel = 0; + + + /* Set MPC8260ADS board LEDS and Uart enable lines */ + _BSP_GPLED0_off(); + _BSP_GPLED1_off(); + _BSP_Uart1_enable(); + _BSP_Uart2_enable(); + + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() function + * store the result in global variables so that it can be used latter... + */ + myCpu = get_ppc_cpu_type(); + myCpuRevision = get_ppc_cpu_revision(); + + + + cpu_init(); + +/* + mmu_init(); +*/ + /* + * Initialize some SPRG registers related to irq handling + */ + + intrStack = (((unsigned char*)&intrStackPtr) - CPU_MINIMUM_STACK_FRAME_SIZE); + asm volatile ("mtspr 273, %0" : "=r" (intrStack) : "0" (intrStack)); + asm volatile ("mtspr 272, %0" : "=r" (intrNestingLevel) : "0" (intrNestingLevel)); + +/* + printk( "About to call initialize_exceptions\n" ); +*/ + /* + * Install our own set of exception vectors + */ + + initialize_exceptions(); + +/* + mmu_init(); +*/ + + /* + * Enable instruction and data caches. Do not force writethrough mode. + */ +#if INSTRUCTION_CACHE_ENABLE + rtems_cache_enable_instruction(); +#endif +#if DATA_CACHE_ENABLE + rtems_cache_enable_data(); +#endif + + /* + * Allocate the memory for the RTEMS Work Space. This can come from + * a variety of places: hard coded address, malloc'ed from outside + * RTEMS world (e.g. simulator or primitive memory manager), or (as + * typically done by stock BSPs) by subtracting the required amount + * of work space from the last physical address on the CPU board. + */ + + /* + * 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; + + +/* + BSP_Configuration.microseconds_per_tick = 1000; +*/ + + /* + * initialize the CPU table for this BSP + */ + + Cpu_table.pretasking_hook = bsp_pretasking_hook; /* init libc, etc. */ + Cpu_table.postdriver_hook = bsp_postdriver_hook; + if( Cpu_table.interrupt_stack_size < 4*1024 ) + Cpu_table.interrupt_stack_size = 4 * 1024; + + Cpu_table.clicks_per_usec = 10; /* for 40MHz extclk */ + Cpu_table.serial_per_sec = 40000000; + Cpu_table.serial_external_clock = 0; + Cpu_table.serial_xon_xoff = 0; + Cpu_table.serial_cts_rts = 0; + Cpu_table.serial_rate = 9600; + Cpu_table.timer_average_overhead = 3; + Cpu_table.timer_least_valid = 3; + Cpu_table.clock_speed = 40000000; + + + + +#ifdef REV_0_2 + /* set up some board specific registers */ + m8260.siumcr &= 0xF3FFFFFF; /* set TBEN ** BUG FIX ** */ + m8260.siumcr |= 0x08000000; +#endif + + /* use BRG1 to generate 32kHz timebase */ +/* + m8260.brgc1 = M8260_BRG_EN + (unsigned32)(((unsigned16)((40016384)/(32768)) - 1) << 1) + 0; +*/ + + + /* + * Initalize RTEMS IRQ system + */ + BSP_rtems_irq_mng_init(0); + + + /* + * Call this in case we use TERMIOS for console I/O + */ + + m8xx_uart_reserve_resources(&BSP_Configuration); + +/* + rtems_termios_initialize(); +*/ +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Exit from bspstart\n"); +#endif + +} + +/* + * + * _Thread_Idle_body + * + * Replaces the one in c/src/exec/score/src/threadidlebody.c + * The MSR[POW] bit is set to put the CPU into the low power mode + * defined in HID0. HID0 is set during starup in start.S. + * + */ +Thread _Thread_Idle_body( + unsigned32 ignored ) +{ + + for( ; ; ) + { + asm volatile( + "mfmsr 3; oris 3,3,4; sync; mtmsr 3; isync; ori 3,3,0; ori 3,3,0" + ); + } +} + diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/startup/cpuinit.c b/c/src/lib/libbsp/powerpc/mpc8260ads/startup/cpuinit.c new file mode 100644 index 0000000000..8c5ff89d4b --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/startup/cpuinit.c @@ -0,0 +1,51 @@ +/* + * cpuinit.c - this file contains functions for initializing the CPU + * + * Written by Jay Monkman (jmonkman@frasca.com) + * + * $Id$ + */ + +#include + +/* Macros for handling all the MMU SPRs */ +#define PUT_IC_CST(r) __asm__ volatile ("mtspr 0x230,%0\n" ::"r"(r)) +#define GET_IC_CST(r) __asm__ volatile ("mfspr %0,0x230\n" :"=r"(r)) +#define PUT_DC_CST(r) __asm__ volatile ("mtspr 0x238,%0\n" ::"r"(r)) +#define GET_DC_CST(r) __asm__ volatile ("mfspr %0,0x238\n" :"=r"(r)) + +void cpu_init(void) +{ + /* BRGCLK is VCO_OUT/4 */ +/* + m8260.sccr = 0; +*/ + +#if 0 + register unsigned long t1, t2; + + /* Let's clear MSR[IR] and MSR[DR] */ + t2 = PPC_MSR_IR | PPC_MSR_DR; + __asm__ volatile ( + "mfmsr %0\n" + "andc %0, %0, %1\n" + "mtmsr %0\n" :"=r"(t1), "=r"(t2): + "1"(t2)); + + t1 = M8xx_CACHE_CMD_UNLOCK; + /* PUT_DC_CST(t1); */ + PUT_IC_CST(t1); + + t1 = M8xx_CACHE_CMD_INVALIDATE; + /* PUT_DC_CST(t1); */ + PUT_IC_CST(t1); + + t1 = M8xx_CACHE_CMD_ENABLE; + PUT_IC_CST(t1); + + t1 = M8xx_CACHE_CMD_SFWT; + /* PUT_DC_CST(t1); */ + t1 = M8xx_CACHE_CMD_ENABLE; + /* PUT_DC_CST(t1);*/ +#endif +} diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/startup/linkcmds b/c/src/lib/libbsp/powerpc/mpc8260ads/startup/linkcmds new file mode 100644 index 0000000000..2e2314166d --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/startup/linkcmds @@ -0,0 +1,285 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the MPC8260ADS Board + * + * $Id$ + */ + +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc) + SEARCH_DIR(/usr/local/rtems/powerpc-rtems/lib); + +ENTRY(start) + +/* + * Declare some sizes. + * XXX: The assignment of ". += XyzSize;" fails in older gld's if the + * number used there is not constant. If this happens to you, edit + * the lines marked XXX below to use a constant value. + */ +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x400000; /* 4M Heap */ +StackSize = DEFINED(StackSize) ? StackSize : 0x8000; +WorkSpaceSize = DEFINED(WorkSpaceSize) ? WorkSpaceSize : 0x80000; /* 512k */ +RamDiskSize = DEFINED(RamDiskSize) ? RamDiskSize : 0x0800000; /* 8M ram disk */ + +MEMORY + { + ram : org = 0x0, l = 16M + dpram : org = 0x04700000, l = 128K + flash : org = 0xff800000, l = 8M + } + + +SECTIONS +{ + + /* + * The stack will live in this area - between the vectors and + * the text section. + */ + + .text 0x10000: + { + _textbase = .; + + + text.start = .; + + /* Entry point is the .entry section */ + *(.entry) + *(.entry2) + + /* Actual Code */ + *(.text) + *(.text.*) + + + *(.rodata) + *(.rodata1) + + /* C++ constructors/destructors */ + *(.gnu.linkonce.t*) + + /* Initialization and finalization code. + * + * Various files can provide initialization and finalization functions. + * The bodies of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues from + * ecrti.o and function epilogues from ecrtn.o. ecrti.o must be linked + * first; ecrtn.o must be linked last. Because these are wildcards, it + * doesn't matter if the user does not actually link against ecrti.o and + * ecrtn.o; the linker won't look for a file to match a wildcard. The + * wildcard also means that it doesn't matter which directory ecrti.o + * and ecrtn.o are in. + */ + PROVIDE (_init = .); + *ecrti.o(.init) + *(.init) + *ecrtn.o(.init) + + PROVIDE (_fini = .); + *ecrti.o(.fini) + *(.fini) + *ecrtn.o(.init) + + /* + * C++ constructors and destructors for static objects. + * PowerPC EABI does not use crtstuff yet, so we build "old-style" + * constructor and destructor lists that begin with the list lenght + * end terminate with a NULL entry. + */ + + PROVIDE (__CTOR_LIST__ = .); + /* LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) */ + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + LONG(0) + PROVIDE (__CTOR_END__ = .); + + PROVIDE (__DTOR_LIST__ = .); + /* LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) */ + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + LONG(0) + PROVIDE (__DTOR_END__ = .); + + /* Exception frame info */ + *(.eh_frame) + + /* Miscellaneous read-only data */ + _rodata_start = . ; + *(.gnu.linkonce.r*) + *(.lit) + *(.shdata) + *(.rodata) + *(.rodata1) + *(.descriptors) + *(rom_ver) + _erodata = .; + + + /* Various possible names for the end of the .text section */ + etext = ALIGN(0x10); + _etext = .; + _endtext = .; + text.end = .; + PROVIDE (etext = .); + PROVIDE (__etext = .); + + } > ram + + + PROVIDE (__EXCEPT_START__ = .); + .gcc_except_table : { *(.gcc_except_table) } >RAM + PROVIDE (__EXCEPT_END__ = .); + __GOT_START__ = .; + .got : + { + s.got = .; + *(.got.plt) *(.got) + } > ram + __GOT_END__ = .; + + .got1 : { *(.got1) } >ram + PROVIDE (__GOT2_START__ = .); + PROVIDE (_GOT2_START_ = .); + .got2 : { *(.got2) } >ram + PROVIDE (__GOT2_END__ = .); + PROVIDE (_GOT2_END_ = .); + + PROVIDE (__FIXUP_START__ = .); + PROVIDE (_FIXUP_START_ = .); + .fixup : { *(.fixup) } >ram + PROVIDE (_FIXUP_END_ = .); + PROVIDE (__FIXUP_END__ = .); + + PROVIDE (__SDATA2_START__ = .); + .sdata2 : { *(.sdata2) } >ram + .sbss2 : { *(.sbss2) } >ram + PROVIDE (__SBSS2_END__ = .); + + .sbss2 : { *(.sbss2) } >ram + PROVIDE (__SBSS2_END__ = .); + + __SBSS_START__ = .; + .bss : + { + bss.start = .; + *(.bss) *(.sbss) *(COMMON) + . = ALIGN(4); + bss.end = .; + } > ram + __SBSS_END__ = .; + + + + + + /* R/W Data */ + .data ( . ) : + { + . = ALIGN (4); + + data.start = .; + + *(.data) + *(.data1) + *(.gnu.linkonce.d.*) + PROVIDE (__SDATA_START__ = .); + *(.sdata) + + data.end = .; + } > ram + + data.size = data.end - data.start; + bss.size = bss.end - bss.start; + text.size = text.end - text.start; + + PROVIDE(_end = data.end); + + .gzipmalloc : { + . = ALIGN (16); + _startmalloc = .; + } >ram + + + /* + * Interrupt stack setup + */ + IntrStack_start = ALIGN(0x10); + . += 0x4000; + intrStack = .; + PROVIDE(intrStackPtr = intrStack); + + + _HeapStart = .; + __HeapStart = .; + . += HeapSize; + _HeapEnd = .; + __HeapEnd = .; + + clear_end = .; + + + _WorkspaceBase = .; + __WorkspaceBase = .; + . += WorkSpaceSize; + + + _RamDiskBase = .; + __RamDiskBase = .; + . += RamDiskSize; + _RamDiskEnd = .; + __RamDiskEnd = .; + PROVIDE( _RamDiskSize = _RamDiskEnd - _RamDiskBase ); + + /* Sections for compressed .text and .data */ + /* after the .datarom section is an int specifying */ + /* the length of the following compressed image */ + /* Executes once then could get overwritten */ + .textrom 0x100000 : + { + *(.textrom) + _endloader = .; + } > ram + + .datarom : + { + _dr_start = .; + *(.datarom) + _dr_end = .; + } > ram + dr_len = _dr_end - _dr_start; + + .dpram : + { + m8260 = .; + _m8260 = .; + . += (128 * 1024); + } > dpram + + + /* the reset vector is at 0xfff00000 which is */ + /* located at offset 0x400000 from the base */ + /* of flash */ + .bootrom 0xFFF00000 : + { + *(.bootrom) + _endboot = .; + } > flash + + + .line 0 : { *(.line) } + .debug 0 : { *(.debug) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_aregion 0 : { *(.debug_aregion) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } +} diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/startup/setvec.c b/c/src/lib/libbsp/powerpc/mpc8260ads/startup/setvec.c new file mode 100644 index 0000000000..bfaa31d9da --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/startup/setvec.c @@ -0,0 +1,43 @@ +/* set_vector + * + * This routine installs an interrupt vector on the target Board/CPU. + * This routine is allowed to be as board dependent as necessary. + * + * INPUT: + * handler - interrupt handler entry point + * vector - vector number + * type - 0 indicates raw hardware connect + * 1 indicates RTEMS interrupt connect + * + * RETURNS: + * address of previous interrupt handler + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include +#include + +rtems_isr_entry set_vector( /* returns old vector */ + rtems_isr_entry handler, /* isr routine */ + rtems_vector_number vector, /* vector number */ + int type /* RTEMS or RAW intr */ +) +{ + rtems_isr_entry previous_isr; + + if (type) { + rtems_interrupt_catch(handler, vector, (rtems_isr_entry *) &previous_isr ); + } else { + /* XXX: install non-RTEMS ISR as "raw" interupt */ + } + return previous_isr; +} + diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/times b/c/src/lib/libbsp/powerpc/mpc8260ads/times new file mode 100644 index 0000000000..f898344dc2 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/times @@ -0,0 +1,196 @@ +# +# Timing Test Suite Results for the mpc8260ads BSP +# +# +# $Id$ +# + +# Testing not complete. +# DO NOT BELIEVE THESE RESULTS + +Board: mpc8260ads +CPU: Motorola MPC8260 +Clock Speed: 40 Mhz +Memory Configuration: SDRAM, no caches +Wait States: + +Times Reported in: cycles, microseconds, etc +Timer Source: Time Base register + +Column X: +Column Y: + +# DESCRIPTION A B +== ================================================================= ==== ==== +1 rtems_semaphore_create 56 + rtems_semaphore_delete 35 + rtems_semaphore_obtain: available 13 + rtems_semaphore_obtain: not available -- NO_WAIT 13 + rtems_semaphore_release: no waiting tasks 16 + +2 rtems_semaphore_obtain: not available -- caller blocks 48 + +3 rtems_semaphore_release: task readied -- preempts caller 36 + +4 rtems_task_restart: blocked task -- preempts caller 117 + rtems_task_restart: ready task -- preempts caller 94 + rtems_semaphore_release: task readied -- returns to caller 22 + rtems_task_create 83 + rtems_task_start 30 + rtems_task_restart: suspended task -- returns to caller 36 + rtems_task_delete: suspended task 74 + rtems_task_restart: ready task -- returns to caller 35 + rtems_task_restart: blocked task -- returns to caller 47 + rtems_task_delete: blocked task 76 + +5 rtems_task_suspend: calling task 37 + rtems_task_resume: task readied -- preempts caller 31 + +6 rtems_task_restart: calling task 48 + rtems_task_suspend: returns to caller 14 + rtems_task_resume: task readied -- returns to caller 16 + rtems_task_delete: ready task 80 + +7 rtems_task_restart: suspended task -- preempts caller 56 + +8 rtems_task_set_priority: obtain current priority 12 + rtems_task_set_priority: returns to caller 23 + rtems_task_mode: obtain current mode 5 + rtems_task_mode: no reschedule 7 + rtems_task_mode: reschedule -- returns to caller 14 + rtems_task_mode: reschedule -- preempts caller 43 + rtems_task_set_note 13 + rtems_task_get_note 12 + rtems_clock_set 28 + rtems_clock_get 0 + +9 rtems_message_queue_create 110 + rtems_message_queue_send: no waiting tasks 28 + rtems_message_queue_urgent: no waiting tasks 28 + rtems_message_queue_receive: available 26 + rtems_message_queue_flush: no messages flushed 13 + rtems_message_queue_flush: messages flushed 14 + rtems_message_queue_delete 45 + +10 rtems_message_queue_receive: not available -- NO_WAIT 15 + rtems_message_queue_receive: not available -- caller blocks 48 + +11 rtems_message_queue_send: task readied -- preempts caller 46 + +12 rtems_message_queue_send: task readied -- returns to caller 31 + +13 rtems_message_queue_urgent: task readied -- preempts caller 46 + +14 rtems_message_queue_urgent: task readied -- returns to caller 31 + +15 rtems_event_receive: obtain current events 1 + rtems_event_receive: not available -- NO_WAIT 11 + rtems_event_receive: not available -- caller blocks 36 + rtems_event_send: no task readied 12 + rtems_event_receive: available 19 + rtems_event_send: task readied -- returns to caller 21 + +16 rtems_event_send: task readied -- preempts caller 38 + +17 rtems_task_set_priority: preempts caller 51 + +18 rtems_task_delete: calling task 102 + +19 rtems_signal_catch 31 + rtems_signal_send: returns to caller 21 + rtems_signal_send: signal to self 39 + exit ASR overhead: returns to calling task 30 + exit ASR overhead: returns to preempting task 33 + +20 rtems_partition_create 59 + rtems_region_create 37 + rtems_partition_get_buffer: available 19 + rtems_partition_get_buffer: not available 12 + rtems_partition_return_buffer 21 + rtems_partition_delete 20 + rtems_region_get_segment: available 20 + rtems_region_get_segment: not available -- NO_WAIT 24 + rtems_region_return_segment: no waiting tasks 21 + rtems_region_get_segment: not available -- caller blocks 76 + rtems_region_return_segment: task readied -- preempts caller 82 + rtems_region_return_segment: task readied -- returns to caller 55 + rtems_region_delete 20 + rtems_io_initialize 1 + rtems_io_open 1 + rtems_io_close 1 + rtems_io_read 1 + rtems_io_write 1 + rtems_io_control 1 + +21 rtems_task_ident 84 + rtems_message_queue_ident 82 + rtems_semaphore_ident 94 + rtems_partition_ident 82 + rtems_region_ident 84 + rtems_port_ident 82 + rtems_timer_ident 82 + rtems_rate_monotonic_ident 82 + +22 rtems_message_queue_broadcast: task readied -- returns to caller 81 + rtems_message_queue_broadcast: no waiting tasks 22 + rtems_message_queue_broadcast: task readied -- preempts caller 76 + +23 rtems_timer_create 11 + rtems_timer_fire_after: inactive 20 + rtems_timer_fire_after: active 22 + rtems_timer_cancel: active 12 + rtems_timer_cancel: inactive 11 + rtems_timer_reset: inactive 18 + rtems_timer_reset: active 21 + rtems_timer_fire_when: inactive 24 + rtems_timer_fire_when: active 24 + rtems_timer_delete: active 16 + rtems_timer_delete: inactive 14 + rtems_task_wake_when 49 + +24 rtems_task_wake_after: yield -- returns to caller 8 + rtems_task_wake_after: yields -- preempts caller 30 + +25 rtems_clock_tick 35 + +26 _ISR_Disable 24 + _ISR_Flash 0 + _ISR_Enable 1 + _Thread_Disable_dispatch 1 + _Thread_Enable_dispatch 7 + _Thread_Set_state 7 + _Thread_Disptach (NO FP) 31 + context switch: no floating point contexts 22 + context switch: self 9 + context switch: to another task 10 + fp context switch: restore 1st FP task 24 + fp context switch: save idle, restore initialized 10 + fp context switch: save idle, restore idle 23 + fp context switch: save initialized, restore initialized 10 + _Thread_Resume 11 + _Thread_Unblock 6 + _Thread_Ready 10 + _Thread_Get 3 + _Semaphore_Get 2 + _Thread_Get: invalid id 0 + + +27 interrupt entry overhead: returns to interrupted task 14 + interrupt exit overhead: returns to interrupted task 26 + interrupt entry overhead: returns to nested interrupt 7 + interrupt exit overhead: returns to nested interrupt 10 + interrupt entry overhead: returns to preempting task 14 + interrupt exit overhead: returns to preempting task 45 + +28 rtems_port_create 23 + rtems_port_external_to_internal 10 + rtems_port_internal_to_external 10 + rtems_port_delete 21 + +29 rtems_rate_monotonic_create 43 + rtems_rate_monotonic_period: initiate period -- returns to caller 32 + rtems_rate_monotonic_period: obtain status 17 + rtems_rate_monotonic_cancel 22 + rtems_rate_monotonic_delete: inactive 25 + rtems_rate_monotonic_delete: active 28 + rtems_rate_monotonic_period: conclude periods -- caller blocks 30 diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/vectors/.cvsignore b/c/src/lib/libbsp/powerpc/mpc8260ads/vectors/.cvsignore new file mode 100644 index 0000000000..282522db03 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/vectors/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/vectors/Makefile.am b/c/src/lib/libbsp/powerpc/mpc8260ads/vectors/Makefile.am new file mode 100644 index 0000000000..d3a237fee4 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/vectors/Makefile.am @@ -0,0 +1,40 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 + +VPATH = @srcdir@: + +C_FILES = vectors_init.c +C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) + +H_FILES = vectors.h + +S_FILES = vectors.S +S_O_FILES = $(S_FILES:%.S=$(ARCH)/%.o) + +OBJS = $(S_O_FILES) $(C_O_FILES) + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../../../../automake/compile.am +include $(top_srcdir)/../../../../../../automake/lib.am + +# +# (OPTIONAL) Add local stuff here using += +# + +$(PGM): $(OBJS) + $(make-rel) + +$(PROJECT_INCLUDE)/bsp: + $(mkinstalldirs) $@ + +$(PROJECT_INCLUDE)/bsp/vectors.h: vectors.h + $(INSTALL_DATA) $< $@ + +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp $(PROJECT_INCLUDE)/bsp/vectors.h + +all-local: $(ARCH) $(PREINSTALL_FILES) $(OBJS) + +include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/vectors/vectors.S b/c/src/lib/libbsp/powerpc/mpc8260ads/vectors/vectors.S new file mode 100644 index 0000000000..da802bcecd --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/vectors/vectors.S @@ -0,0 +1,145 @@ +/* + * (c) 1999, Eric Valette valette@crf.canon.fr + * + * + * This file contains the assembly code for the PowerPC + * exception veneers for RTEMS. + * + * $Id$ + */ + + + +#include +#include +#include +#include "asm.h" + + +#define SYNC \ + sync; \ + isync + + .text + .p2align 5 + +PUBLIC_VAR(default_exception_vector_code_prolog) +SYM (default_exception_vector_code_prolog): + /* + * let room for exception frame + */ + stwu r1, - (EXCEPTION_FRAME_END)(r1) + stw r3, GPR3_OFFSET(r1) + stw r2, GPR2_OFFSET(r1) + mflr r2 + stw r2, EXC_LR_OFFSET(r1) + bl 0f +0: /* + * r3 = exception vector entry point + * (256 * vector number) + few instructions + */ + mflr r3 + /* + * r3 = r3 >> 8 = vector + */ + srwi r3,r3,8 + ba push_normalized_frame + + PUBLIC_VAR (default_exception_vector_code_prolog_size) + + default_exception_vector_code_prolog_size= . - default_exception_vector_code_prolog + + .p2align 5 +PUBLIC_VAR (push_normalized_frame) +SYM (push_normalized_frame): + stw r3, EXCEPTION_NUMBER_OFFSET(r1) + stw r0, GPR0_OFFSET(r1) + mfsrr0 r2 + stw r2, SRR0_FRAME_OFFSET(r1) + mfsrr1 r3 + stw r3, SRR1_FRAME_OFFSET(r1) + /* + * Save general purpose registers + * Already saved in prolog : R1, R2, R3, LR. + * Saved a few line above : R0 + * + * Manual says that "stmw" instruction may be slower than + * series of individual "stw" but who cares about performance + * for the DEFAULT exception handler? + */ + stmw r4, GPR4_OFFSET(r1) /* save R4->R31 */ + + mfcr r31 + stw r31, EXC_CR_OFFSET(r1) + mfctr r30 + stw r30, EXC_CTR_OFFSET(r1) + mfxer r28 + stw r28, EXC_XER_OFFSET(r1) + /* + * compute SP at exception entry + */ + addi r2, r1, EXCEPTION_FRAME_END + /* + * store it at the right place + */ + stw r2, GPR1_OFFSET(r1) + + /* + * Enable data and instruction address translation, exception nesting + */ + mfmsr r3 + ori r3,r3, MSR_RI /*| MSR_IR | MSR_DR*/ + mtmsr r3 + SYNC + + /* + * Call C exception handler + */ + /* + * store the execption frame address in r3 (first param) + */ + addi r3, r1, 0x8 + /* + * globalExceptHdl(r3) + */ + addis r4, 0, globalExceptHdl@ha + lwz r5, globalExceptHdl@l(r4) + mtlr r5 + blrl + /* + * Restore registers status + */ + lwz r31, EXC_CR_OFFSET(r1) + mtcr r31 + lwz r30, EXC_CTR_OFFSET(r1) + mtctr r30 + lwz r29, EXC_LR_OFFSET(r1) + mtlr r29 + lwz r28, EXC_XER_OFFSET(r1) + mtxer r28 + + lmw r4, GPR4_OFFSET(r1) + lwz r2, GPR2_OFFSET(r1) + lwz r0, GPR0_OFFSET(r1) + + /* + * Disable data and instruction translation. Make path non recoverable... + */ + mfmsr r3 + xori r3, r3, MSR_RI /*| MSR_IR | MSR_DR*/ + mtmsr r3 + SYNC + + /* + * Restore rfi related settings + */ + + lwz r3, SRR1_FRAME_OFFSET(r1) + mtsrr1 r3 + lwz r3, SRR0_FRAME_OFFSET(r1) + mtsrr0 r3 + + lwz r3, GPR3_OFFSET(r1) + addi r1,r1, EXCEPTION_FRAME_END + SYNC + rfi diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/vectors/vectors.h b/c/src/lib/libbsp/powerpc/mpc8260ads/vectors/vectors.h new file mode 100644 index 0000000000..2b77e76232 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/vectors/vectors.h @@ -0,0 +1,144 @@ +/* + * vectors.h Exception frame related contant and API. + * + * This include file describe the data structure and the functions implemented + * by rtems to handle exceptions. + * + * CopyRight (C) 1999 valette@crf.canon.fr + * + * The license and distribution terms for this file may be + * found in found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ +#ifndef LIBBSP_POWERPC_MBX8XX_VECTORS_H +#define LIBBSP_POWERPC_MBX8XX_VECTORS_H + +/* + * The callee (high level exception code written in C) + * will store the Link Registers (return address) at entry r1 + 4 !!!. + * So let room for it!!!. + */ +#define LINK_REGISTER_CALLEE_UPDATE_ROOM 4 +#define SRR0_FRAME_OFFSET 8 +#define SRR1_FRAME_OFFSET 12 +#define EXCEPTION_NUMBER_OFFSET 16 +#define GPR0_OFFSET 20 +#define GPR1_OFFSET 24 +#define GPR2_OFFSET 28 +#define GPR3_OFFSET 32 +#define GPR4_OFFSET 36 +#define GPR5_OFFSET 40 +#define GPR6_OFFSET 44 +#define GPR7_OFFSET 48 +#define GPR8_OFFSET 52 +#define GPR9_OFFSET 56 +#define GPR10_OFFSET 60 +#define GPR11_OFFSET 64 +#define GPR12_OFFSET 68 +#define GPR13_OFFSET 72 +#define GPR14_OFFSET 76 +#define GPR15_OFFSET 80 +#define GPR16_OFFSET 84 +#define GPR17_OFFSET 88 +#define GPR18_OFFSET 92 +#define GPR19_OFFSET 96 +#define GPR20_OFFSET 100 +#define GPR21_OFFSET 104 +#define GPR22_OFFSET 108 +#define GPR23_OFFSET 112 +#define GPR24_OFFSET 116 +#define GPR25_OFFSET 120 +#define GPR26_OFFSET 124 +#define GPR27_OFFSET 128 +#define GPR28_OFFSET 132 +#define GPR29_OFFSET 136 +#define GPR30_OFFSET 140 +#define GPR31_OFFSET 144 +#define EXC_CR_OFFSET 148 +#define EXC_CTR_OFFSET 152 +#define EXC_XER_OFFSET 156 +#define EXC_LR_OFFSET 160 +#define EXC_DAR_OFFSET 164 +/* + * maintain the EABI requested 8 bytes aligment + * As SVR4 ABI requires 16, make it 16 (as some + * exception may need more registers to be processed...) + */ +#define EXCEPTION_FRAME_END 176 + +#ifndef ASM +/* + * default raw exception handlers + */ + +extern void default_exception_vector_code_prolog(); +extern int default_exception_vector_code_prolog_size; + +/* codemove is like memmove, but it also gets the cache line size + * as 4th parameter to synchronize them. If this last parameter is + * zero, it performs more or less like memmove. No copy is performed if + * source and destination addresses are equal. However the caches + * are synchronized. Note that the size is always rounded up to the + * next mutiple of 4. + */ +extern void * codemove(void *, const void *, unsigned int, unsigned long); +extern void initialize_exceptions(); + +typedef struct { + unsigned EXC_SRR0; + unsigned EXC_SRR1; + unsigned _EXC_number; + unsigned GPR0; + unsigned GPR1; + unsigned GPR2; + unsigned GPR3; + unsigned GPR4; + unsigned GPR5; + unsigned GPR6; + unsigned GPR7; + unsigned GPR8; + unsigned GPR9; + unsigned GPR10; + unsigned GPR11; + unsigned GPR12; + unsigned GPR13; + unsigned GPR14; + unsigned GPR15; + unsigned GPR16; + unsigned GPR17; + unsigned GPR18; + unsigned GPR19; + unsigned GPR20; + unsigned GPR21; + unsigned GPR22; + unsigned GPR23; + unsigned GPR24; + unsigned GPR25; + unsigned GPR26; + unsigned GPR27; + unsigned GPR28; + unsigned GPR29; + unsigned GPR30; + unsigned GPR31; + unsigned EXC_CR; + unsigned EXC_CTR; + unsigned EXC_XER; + unsigned EXC_LR; + unsigned EXC_MSR; + unsigned EXC_DAR; +}BSP_Exception_frame; + + +typedef void (*exception_handler_t) (BSP_Exception_frame* excPtr); +extern exception_handler_t globalExceptHdl; +/* + * Compatibility with pc386 + */ +typedef BSP_Exception_frame CPU_Exception_frame; +typedef exception_handler_t cpuExcHandlerType; + +#endif /* ASM */ + +#endif /* LIBBSP_POWERPC_MCP750_VECTORS_H */ diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/vectors/vectors_init.c b/c/src/lib/libbsp/powerpc/mpc8260ads/vectors/vectors_init.c new file mode 100644 index 0000000000..1c17a6513f --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/vectors/vectors_init.c @@ -0,0 +1,151 @@ +/* + * vectors_init.c Exception hanlding initialisation (and generic handler). + * + * This include file describe the data structure and the functions implemented + * by rtems to handle exceptions. + * + * CopyRight (C) 1999 valette@crf.canon.fr + * + * The license and distribution terms for this file may be + * found in found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ +#include +#include +#include + +static rtems_raw_except_global_settings exception_config; +static rtems_raw_except_connect_data exception_table[LAST_VALID_EXC + 1]; + +exception_handler_t globalExceptHdl; + +void C_exception_handler(BSP_Exception_frame* excPtr) +{ + int recoverable = 0; + + printk("exception handler called for exception %d\n", excPtr->_EXC_number); + printk("\t Next PC or Address of fault = %x\n", excPtr->EXC_SRR0); + printk("\t Saved MSR = %x\n", excPtr->EXC_SRR1); + printk("\t R0 = %x\n", excPtr->GPR0); + printk("\t R1 = %x\n", excPtr->GPR1); + printk("\t R2 = %x\n", excPtr->GPR2); + printk("\t R3 = %x\n", excPtr->GPR3); + printk("\t R4 = %x\n", excPtr->GPR4); + printk("\t R5 = %x\n", excPtr->GPR5); + printk("\t R6 = %x\n", excPtr->GPR6); + printk("\t R7 = %x\n", excPtr->GPR7); + printk("\t R8 = %x\n", excPtr->GPR8); + printk("\t R9 = %x\n", excPtr->GPR9); + printk("\t R10 = %x\n", excPtr->GPR10); + printk("\t R11 = %x\n", excPtr->GPR11); + printk("\t R12 = %x\n", excPtr->GPR12); + printk("\t R13 = %x\n", excPtr->GPR13); + printk("\t R14 = %x\n", excPtr->GPR14); + printk("\t R15 = %x\n", excPtr->GPR15); + printk("\t R16 = %x\n", excPtr->GPR16); + printk("\t R17 = %x\n", excPtr->GPR17); + printk("\t R18 = %x\n", excPtr->GPR18); + printk("\t R19 = %x\n", excPtr->GPR19); + printk("\t R20 = %x\n", excPtr->GPR20); + printk("\t R21 = %x\n", excPtr->GPR21); + printk("\t R22 = %x\n", excPtr->GPR22); + printk("\t R23 = %x\n", excPtr->GPR23); + printk("\t R24 = %x\n", excPtr->GPR24); + printk("\t R25 = %x\n", excPtr->GPR25); + printk("\t R26 = %x\n", excPtr->GPR26); + printk("\t R27 = %x\n", excPtr->GPR27); + printk("\t R28 = %x\n", excPtr->GPR28); + printk("\t R29 = %x\n", excPtr->GPR29); + printk("\t R30 = %x\n", excPtr->GPR30); + printk("\t R31 = %x\n", excPtr->GPR31); + printk("\t CR = %x\n", excPtr->EXC_CR); + printk("\t CTR = %x\n", excPtr->EXC_CTR); + printk("\t XER = %x\n", excPtr->EXC_XER); + printk("\t LR = %x\n", excPtr->EXC_LR); + printk("\t MSR = %x\n", excPtr->EXC_MSR); + if (excPtr->_EXC_number == ASM_DEC_VECTOR) + recoverable = 1; + if (excPtr->_EXC_number == ASM_SYS_VECTOR) +#ifdef TEST_RAW_EXCEPTION_CODE + recoverable = 1; +#else + recoverable = 0; +#endif + if (!recoverable) { + printk("unrecoverable exception!!! Push reset button\n"); + while(1); + } +} + +void nop_except_enable(const rtems_raw_except_connect_data* ptr) +{ +} +int except_always_enabled(const rtems_raw_except_connect_data* ptr) +{ + return 1; +} + +void initialize_exceptions() +{ + int i; + + /* + * Initialize pointer used by low level execption handling + */ + globalExceptHdl = C_exception_handler; + /* + * Put default_exception_vector_code_prolog at relevant exception + * code entry addresses + */ + exception_config.exceptSize = LAST_VALID_EXC + 1; + exception_config.rawExceptHdlTbl = &exception_table[0]; + exception_config.defaultRawEntry.exceptIndex = 0; + exception_config.defaultRawEntry.hdl.vector = 0; + exception_config.defaultRawEntry.hdl.raw_hdl = default_exception_vector_code_prolog; + /* + * Note that next line the '&' before default_exception_vector_code_prolog_size + * is not a bug as it is defined a .set directly in asm... + */ + exception_config.defaultRawEntry.hdl.raw_hdl_size = (unsigned) &default_exception_vector_code_prolog_size; + +/* + _BSP_GPLED0_off(); + _BSP_GPLED1_on(); +*/ + + for (i=0; i <= exception_config.exceptSize; i++) { +/* + printk("installing exception number %d\n", i); +*/ + if (!mpc8xx_vector_is_valid (i)) { + continue; + } + exception_table[i].exceptIndex = i; + exception_table[i].hdl = exception_config.defaultRawEntry.hdl; + exception_table[i].hdl.vector = i; + exception_table[i].on = nop_except_enable; + exception_table[i].off = nop_except_enable; + exception_table[i].isOn = except_always_enabled; + } + +/* _BSP_GPLED0_on(); */ + + + if (!mpc8xx_init_exceptions(&exception_config)) { + /* + * At this stage we may not call BSP_Panic because it uses exceptions!!! + */ + printk("Exception handling initialization failed\n"); + printk("System locked\n"); while(1); + } + else { +#if 0 + printk("Exception handling initialization done\n"); +#endif + } + +/* _BSP_GPLED1_off(); */ + +} diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/wrapup/Makefile.am b/c/src/lib/libbsp/powerpc/mpc8260ads/wrapup/Makefile.am new file mode 100644 index 0000000000..71e6a86f25 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/wrapup/Makefile.am @@ -0,0 +1,44 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 + +# We only build the networking device driver if HAS_NETWORKING was defined +if HAS_NETWORKING +NETWORKING = network +endif + +BSP_PIECES = clock irq start startup console vectors $(NETWORKING) +# pieces to pick up out of libcpu/ppc +# CPU_PIECES = mpc8xx/clock mpc8xx/console-generic mpc8xx/cpm \ +# mpc8xx/mmu mpc8xx/timer mpc8xx/vectors + +# bummer; have to use $foreach since % pattern subst rules only replace 1x +OBJS = $(foreach piece, $(BSP_PIECES), $(wildcard ../$(piece)/$(ARCH)/*.o)) \ + $(wildcard ../../../../libcpu/$(RTEMS_CPU)/shared/*/$(ARCH)/*.o) \ + $(wildcard ../../../../libcpu/powerpc/new_exception_processing/$(ARCH)/*.rel) \ + $(wildcard ../../../../libcpu/$(RTEMS_CPU)/mpc8260/*/$(ARCH)/*.o) +LIB = $(ARCH)/libbsp.a + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../../../../automake/compile.am +include $(top_srcdir)/../../../../../../automake/lib.am + +# +# (OPTIONAL) Add local stuff here using += +# + +$(LIB): $(OBJS) + $(make-library) + +$(PROJECT_RELEASE)/lib/libbsp$(LIB_VARIANT).a: $(LIB) + $(INSTALL_DATA) $< $@ + +TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/libbsp$(LIB_VARIANT).a + +all-local: $(ARCH) $(OBJS) $(LIB) $(TMPINSTALL_FILES) + +.PRECIOUS: $(LIB) + +include $(top_srcdir)/../../../../../../automake/local.am -- cgit v1.2.3