[PATCH] Virtex4 BSP: Various updates and improvements.

Ric Claus claus at slac.stanford.edu
Fri Nov 30 23:56:04 UTC 2012


Switched to using the PPC403 clock driver.  Added support for the MMU but
didn't enable it by default.  Made some functions static to avoid compiler
warnings.  Added a README.
---
 c/src/lib/libbsp/powerpc/virtex4/Makefile.am       |   15 +-
 c/src/lib/libbsp/powerpc/virtex4/README            |   86 +++
 c/src/lib/libbsp/powerpc/virtex4/clock/clock.c     |  265 ---------
 c/src/lib/libbsp/powerpc/virtex4/include/mmu.h     |  269 +++++++++
 c/src/lib/libbsp/powerpc/virtex4/irq/irq_init.c    |   18 +-
 c/src/lib/libbsp/powerpc/virtex4/mmu/mmu.c         |  567 ++++++++++++++++++++
 c/src/lib/libbsp/powerpc/virtex4/preinstall.am     |    4 +
 .../lib/libbsp/powerpc/virtex4/startup/bspstart.c  |   84 ++--
 c/src/lib/libbsp/powerpc/virtex4/startup/linkcmds  |   13 +-
 c/src/lib/libbsp/powerpc/virtex4/startup/start.S   |   22 +-
 10 files changed, 1010 insertions(+), 333 deletions(-)
 create mode 100644 c/src/lib/libbsp/powerpc/virtex4/README
 delete mode 100644 c/src/lib/libbsp/powerpc/virtex4/clock/clock.c
 create mode 100644 c/src/lib/libbsp/powerpc/virtex4/include/mmu.h
 create mode 100644 c/src/lib/libbsp/powerpc/virtex4/mmu/mmu.c

diff --git a/c/src/lib/libbsp/powerpc/virtex4/Makefile.am b/c/src/lib/libbsp/powerpc/virtex4/Makefile.am
index adce297..58fcea5 100644
--- a/c/src/lib/libbsp/powerpc/virtex4/Makefile.am
+++ b/c/src/lib/libbsp/powerpc/virtex4/Makefile.am
@@ -36,15 +36,12 @@ libbsp_a_SOURCES = startup/bspclean.c \
                    startup/bspstart.c \
                    ../../shared/bootcard.c \
                    ../../shared/sbrk.c \
-                   ../../shared/gnatinstallhandler.c
+                   ../../shared/gnatinstallhandler.c \
+                   ../shared/src/memcpy.c

 # start
 libbsp_a_SOURCES += startup/start.S

-# clock & timer
-libbsp_a_SOURCES += ../../../libcpu/@RTEMS_CPU@/ppc403/clock/clock.c
-libbsp_a_SOURCES += ../../../libcpu/@RTEMS_CPU@/ppc403/timer/timer.c
-
 # console
 libbsp_a_SOURCES += startup/dummy_console.c \
                     ../../shared/dummy_printk_support.c
@@ -53,6 +50,10 @@ libbsp_a_SOURCES += startup/dummy_console.c \
 include_bsp_HEADERS += include/irq.h
 libbsp_a_SOURCES += irq/irq_init.c

+# mmu
+include_bsp_HEADERS += include/mmu.h
+libbsp_a_SOURCES += mmu/mmu.c
+
 #vectors
 include_bsp_HEADERS += ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/vectors.h
 include_bsp_HEADERS += ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/irq_supp.h
@@ -60,7 +61,9 @@ include_bsp_HEADERS += ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/irq_s
 libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/@exceptions@/rtems-cpu.rel \
                   ../../../libcpu/@RTEMS_CPU@/@exceptions@/exc_bspsupport.rel \
                   ../../../libcpu/@RTEMS_CPU@/shared/cache.rel \
-                  ../../../libcpu/@RTEMS_CPU@/shared/cpuIdent.rel
+                  ../../../libcpu/@RTEMS_CPU@/shared/cpuIdent.rel \
+                  ../../../libcpu/@RTEMS_CPU@/ppc403/clock.rel \
+                  ../../../libcpu/@RTEMS_CPU@/ppc403/timer.rel

 EXTRA_DIST = times

diff --git a/c/src/lib/libbsp/powerpc/virtex4/README b/c/src/lib/libbsp/powerpc/virtex4/README
new file mode 100644
index 0000000..68a0c24
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/virtex4/README
@@ -0,0 +1,86 @@
+# Adapted from virtex BSP
+
+BSP NAME:           virtex4
+BOARD:              N/A
+BUS:                N/A
+CPU FAMILY:         ppc
+CPU:                PowerPC 405D5
+COPROCESSORS:       N/A
+MODE:               32 bit mode
+
+DEBUG MONITOR:
+
+PERIPHERALS
+===========
+TIMERS:             405 internal
+SERIAL PORTS:       none
+REAL-TIME CLOCK:    none
+DMA:                Xilinx virtex internal
+VIDEO:              none
+SCSI:               none
+NETWORKING:         none
+
+DRIVER INFORMATION
+==================
+CLOCK DRIVER:       PPC Decrementer
+IOSUPP DRIVER:      N/A
+SHMSUPP:            N/A
+TIMER DRIVER:       N/A
+TTY DRIVER:         N/A
+
+STDIO
+=====
+PORT:               N/A
+ELECTRICAL:         N/A
+BAUD:               N/A
+BITS PER CHARACTER: N/A
+PARITY:             N/A
+STOP BITS:          N/A
+
+Notes
+=====
+
+Board description
+-----------------
+clock rate:	350 MHz
+ROM:		N/A
+RAM:		128MByte DRAM
+
+Virtex only supports single processor operations.
+
+Porting
+-------
+This board support package is written for a naked Virtex 4/PPC FPGA
+system. The rough features of such a board are described above.
+The BSP itself makes no assumptions on what is loaded in the FPGA,
+other than that the CPU has access to some memory, either on-board
+or external, from which code can be run.
+
+This BSP has been constructed so that an application of both firmware
+and software can be layered on top of it by supplying implementations
+for the various 'weak' symbols.  These symbols are prefaced with the
+term 'app_'.  Applications can thus be built outside of the RTEMS
+directory tree by linking with the appropriate libraries.
+
+The linkcmds file describes the memory layout.  Included in this
+definition is a section of memory named MsgArea.  Output sent to
+stdout is recorded in this area and can be dumped using the JTAG
+interface, for example.
+
+For adapting this BSP to other boards, the following files should be
+modified:
+
+- c/src/lib/libbsp/powerpc/virtex4/startup/linkcmds
+	for the memory layout required
+
+- c/src/lib/libbsp/powerpc/virtex4/startup/bspstart.c
+	Here you can select the clock source for the timers and the
+        serial interface (system clock or external clock pin), the
+        clock rates, etc.
+
+- c/src/lib/libbsp/powerpc/virtex4/include/bsp.h
+	some BSP-related constants
+
+- c/src/lib/libbsp/powerpc/virtex4/*
+	well, they should be generic, so there _should_ be no reason
+	to mess around there (but who knows...)
diff --git a/c/src/lib/libbsp/powerpc/virtex4/clock/clock.c b/c/src/lib/libbsp/powerpc/virtex4/clock/clock.c
deleted file mode 100644
index 7617720..0000000
--- a/c/src/lib/libbsp/powerpc/virtex4/clock/clock.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/*  clock.c
- *
- *  This routine initializes the interval timer on the
- *  PowerPC 403 CPU.  The tick frequency is specified by the bsp.
- *
- *  Author: Andrew Bray <andy at i-cubed.co.uk>
- *
- *  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.
- *
- *  Derived from c/src/lib/libcpu/hppa1.1/clock/clock.c:
- *
- *  Modifications for deriving timer clock from cpu system clock by
- *              Thomas Doerfler <td at imd.m.isar.de>
- *  for these modifications:
- *  COPYRIGHT (c) 1997 by IMD, Puchheim, Germany.
- *
- *  COPYRIGHT (c) 1989-2007.
- *  On-Line Applications Research Corporation (OAR).
- *
- *  The license and distribution terms for this file may be
- *  found in the file LICENSE in this distribution or at
- *  http://www.rtems.com/license/LICENSE.
- *
- *  Modifications for PPC405GP by Dennis Ehlin
- */
-
-#include <rtems.h>
-#include <rtems/clockdrv.h>
-#include <rtems/libio.h>
-#include <stdlib.h>                     /* for atexit() */
-#include <rtems/bspIo.h>
-#include <rtems/powerpc/powerpc.h>
-
-/*
- * check, which exception handling code is present
- */
-
-#include <bsp.h>
-
-#include <bsp/vectors.h>
-#include <bsp/irq_supp.h>
-
-volatile uint32_t   Clock_driver_ticks;
-static uint32_t   pit_value, tick_time;
-static bool auto_restart;
-
-void Clock_exit( void );
-
-/*
- * These are set by clock driver during its init
- */
-
-rtems_device_major_number rtems_clock_major = ~0;
-rtems_device_minor_number rtems_clock_minor;
-
-static inline uint32_t   get_itimer(void)
-{
-    register uint32_t   rc;
-
-    asm volatile ("mfspr %0, 0x10c" : "=r" ((rc))); /* 405GP TBL */
-
-    return rc;
-}
-
-/*
- *  ISR Handler
- */
-
-int Clock_isr(BSP_Exception_frame *f, unsigned int vector)
-{
-    uint32_t   clicks_til_next_interrupt;
-#if defined(BSP_PPC403_CLOCK_ISR_IRQ_LEVEL)
-    uint32_t   l_orig = _ISR_Get_level();
-#endif
-    if (!auto_restart)
-    {
-      uint32_t   itimer_value;
-      /*
-       * setup for next interrupt; making sure the new value is reasonably
-       * in the future.... in case we lost out on an interrupt somehow
-       */
-
-      itimer_value = get_itimer();
-      tick_time += pit_value;
-
-      /*
-       * how far away is next interrupt *really*
-       * It may be a long time; this subtraction works even if
-       * Clock_clicks_interrupt < Clock_clicks_low_order via
-       * the miracle of unsigned math.
-       */
-      clicks_til_next_interrupt = tick_time - itimer_value;
-
-      /*
-       * If it is too soon then bump it up.
-       * This should only happen if CPU_HPPA_CLICKS_PER_TICK is too small.
-       * But setting it low is useful for debug, so...
-       */
-
-      if (clicks_til_next_interrupt < 400)
-      {
-        tick_time = itimer_value + 1000;
-        clicks_til_next_interrupt = 1000;
-        /* XXX: count these! this should be rare */
-      }
-
-      /*
-       * If it is too late, that means we missed the interrupt somehow.
-       * Rather than wait 35-50s for a wrap, we just fudge it here.
-       */
-
-      if (clicks_til_next_interrupt > pit_value)
-      {
-        tick_time = itimer_value + 1000;
-        clicks_til_next_interrupt = 1000;
-        /* XXX: count these! this should never happen :-) */
-      }
-
-      asm volatile ("mtspr 0x3db, %0" :: "r"
-                         (clicks_til_next_interrupt)); /* PIT */
-    }
-
-    /* Clear the Programmable Interrupt Status */
-    asm volatile ( "mtspr 0x3d8, %0" :: "r" (0x08000000)); /* TSR */
-
-    Clock_driver_ticks++;
-
-    rtems_clock_tick();
-
-    return 0;
-}
-
-void ClockOff(void)
-{
-    register uint32_t   tcr;
-
-    asm volatile ("mfspr %0, 0x3da" : "=r" ((tcr))); /* TCR */
-
-    tcr &= ~ 0x04400000;
-
-    asm volatile ("mtspr 0x3da, %0" : "=r" ((tcr)) : "0" ((tcr))); /* TCR */
-}
-
-void ClockOn(void)
-{
-    uint32_t   iocr;
-    register uint32_t   tcr;
-
-    Clock_driver_ticks = 0;
-
-    asm volatile ("mfdcr %0, 0x0b2" : "=r" (iocr));  /*405GP CPC0_CR1 */
-    if (bsp_timer_internal_clock) {
-      iocr &=~0x800000;               /* timer clocked from system clock CETE*/
-    }
-    else {
-      iocr |= 0x800000;               /* select external timer clock CETE*/
-    }
-    asm volatile ("mtdcr 0x0b2, %0" : "=r" (iocr) : "0" (iocr)); /* 405GP CPC0_CR1 */
-
-     /*
-      * Enable auto restart
-      */
-
-    auto_restart = true;
-
-    pit_value = rtems_configuration_get_microseconds_per_tick() *
-      bsp_clicks_per_usec;
-
-     /*
-      * Set PIT value
-      */
-
-    asm volatile ("mtspr 0x3db, %0" : : "r" (pit_value)); /* PIT */
-
-     /*
-      * Set timer to autoreload, bit TCR->ARE = 1  0x0400000
-      * Enable PIT interrupt, bit TCR->PIE = 1     0x4000000
-      */
-    tick_time = get_itimer() + pit_value;
-
-    asm volatile ("mfspr %0, 0x3da" : "=r" ((tcr)));               /* TCR */
-    tcr = (tcr & ~0x04400000) | (auto_restart ? 0x04400000 : 0x04000000);
-    asm volatile ("mtspr 0x3da, %0" : "=r" ((tcr)) : "0" ((tcr))); /* TCR */
-}
-
-
-
-void Install_clock(ppc_exc_handler_t clock_isr)
-{
-#ifdef ppc403
-   uint32_t   pvr;
-#endif /* ppc403 */
-
-   Clock_driver_ticks = 0;
-
-   /*
-    * initialize the interval here
-    * First tick is set to right amount of time in the future
-    * Future ticks will be incremented over last value set
-    * in order to provide consistent clicks in the face of
-    * interrupt overhead
-    */
-
-   ppc_exc_set_handler( BSP_PPC403_CLOCK_HOOK_EXCEPTION, clock_isr );
-   ClockOn();
-
-   atexit(Clock_exit);
-}
-
-void
-ReInstall_clock(ppc_exc_handler_t clock_isr)
-{
-  uint32_t   isrlevel = 0;
-
-  rtems_interrupt_disable(isrlevel);
-
-   ppc_exc_set_handler( BSP_PPC403_CLOCK_HOOK_EXCEPTION, clock_isr );
-   ClockOn();
-
-  rtems_interrupt_enable(isrlevel);
-}
-
-
-/*
- * Called via atexit()
- * Remove the clock interrupt handler by setting handler to NULL
- *
- * This will not work on the 405GP because
- * when bit's are set in TCR they can only be unset by a reset
- */
-
-void Clock_exit(void)
-{
-  ClockOff();
-  ppc_exc_set_handler( BSP_PPC403_CLOCK_HOOK_EXCEPTION, 0 );
-}
-
-rtems_device_driver Clock_initialize(
-  rtems_device_major_number major,
-  rtems_device_minor_number minor,
-  void *pargp
-)
-{
-  Install_clock( Clock_isr );
-
-  /*
-   * make major/minor avail to others such as shared memory driver
-   */
-
-  rtems_clock_major = major;
-  rtems_clock_minor = minor;
-
-  return RTEMS_SUCCESSFUL;
-}
diff --git a/c/src/lib/libbsp/powerpc/virtex4/include/mmu.h b/c/src/lib/libbsp/powerpc/virtex4/include/mmu.h
new file mode 100644
index 0000000..3e2710b
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/virtex4/include/mmu.h
@@ -0,0 +1,269 @@
+#ifndef RTEMS_VIRTEX4_MMU_H
+#define RTEMS_VIRTEX4_MMU_H
+/**
+ * @file
+ *
+ * @ingroup Virtex4MMU
+ *
+ * @brief Routines to manipulate the PPC 405 MMU.
+ */
+/*
+ * Authorship
+ * ----------
+ * This software was created by
+ *     Till Straumann <strauman at slac.stanford.edu>, 2005-2007,
+ *       Stanford Linear Accelerator Center, Stanford University.
+ * and was transcribed for the PPC 405 by
+ *     R. Claus <claus at slac.stanford.edu>, 2012,
+ *       Stanford Linear Accelerator Center, Stanford University,
+ *
+ * Acknowledgement of sponsorship
+ * ------------------------------
+ * This software was produced by
+ *     the Stanford Linear Accelerator Center, Stanford University,
+ *     under Contract DE-AC03-76SFO0515 with the Department of Energy.
+ *
+ * Government disclaimer of liability
+ * ----------------------------------
+ * Neither the United States nor the United States Department of Energy,
+ * nor any of their employees, makes any warranty, express or implied, or
+ * assumes any legal liability or responsibility for the accuracy,
+ * completeness, or usefulness of any data, apparatus, product, or process
+ * disclosed, or represents that its use would not infringe privately owned
+ * rights.
+ *
+ * Stanford disclaimer of liability
+ * --------------------------------
+ * Stanford University makes no representations or warranties, express or
+ * implied, nor assumes any liability for the use of this software.
+ *
+ * Stanford disclaimer of copyright
+ * --------------------------------
+ * Stanford University, owner of the copyright, hereby disclaims its
+ * copyright and all other rights in this software.  Hence, anyone may
+ * freely use it for any purpose without restriction.
+ *
+ * Maintenance of notices
+ * ----------------------
+ * In the interest of clarity regarding the origin and status of this
+ * SLAC software, this and all the preceding Stanford University notices
+ * are to remain affixed to any copy or derivative of this software made
+ * or distributed by the recipient and are to be affixed to any copy of
+ * software made or distributed by the recipient that contains a copy or
+ * derivative of this software.
+ *
+ * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
+ */
+
+#include <rtems.h>
+#include <inttypes.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup Virtex4MMU Virtex 4 - MMU Support
+ *
+ * @ingroup Virtex4
+ *
+ * @brief MMU support.
+ *
+ * @{
+ */
+
+/* Some routines require or return a index 'key'.
+ */
+typedef int bsp_tlb_idx_t;
+
+/* Cache the relevant TLB entries so that we can make sure the user cannot
+ * create conflicting (overlapping) entries. Keep them public for informational
+ * purposes.
+ */
+typedef struct {
+  struct {
+    uint32_t pad:24;
+    uint32_t tid:8;             /** Translation ID */
+  }        id;
+  struct {
+    uint32_t epn:22;            /** Effective page number */
+    uint32_t size:3;            /** Page size */
+    uint32_t v:1;               /** Valid */
+    uint32_t att:2;             /** Little-endian, User-defined */
+    uint32_t pad:4;
+  }        hi;                  /** High word*/
+  struct {
+    uint32_t rpn:22;            /** Real page number */
+    uint32_t perm:6;            /** Execute enable, Write-enable, Zone select */
+    uint32_t wimg:4;            /** Write-through, Caching inhibited, Mem coherent, Guarded */
+  }        lo;                  /** Low word */
+} bsp_tlb_entry_t;
+
+#define NTLBS  64
+
+extern bsp_tlb_entry_t* bsp_mmu_cache;
+
+
+// These constants will have to be shifted right by 20 bits before
+// being inserted the high word of the TLB.
+
+#define MMU_M_SIZE_1K               (0x00000000U)
+#define MMU_M_SIZE_4K               (0x08000000U)
+#define MMU_M_SIZE_16K              (0x10000000U)
+#define MMU_M_SIZE_64K              (0x18000000U)
+#define MMU_M_SIZE_256K             (0x20000000U)
+#define MMU_M_SIZE_1M               (0x28000000U)
+#define MMU_M_SIZE_4M               (0x30000000U)
+#define MMU_M_SIZE_16M              (0x38000000U)
+#define MMU_M_SIZE_MIN              (MMU_M_SIZE_1K)
+#define MMU_M_SIZE_MAX              (MMU_M_SIZE_16M)
+#define MMU_M_SIZE                  (0x38000000U)
+#define MMU_V_SIZE                  (27)
+
+#define MMU_M_ATTR_LITTLE_ENDIAN    (0x02000000U)
+#define MMU_M_ATTR_USER0            (0x01000000U)
+#define MMU_M_ATTR                  (0x03000000U)
+#define MMU_V_ATTR                  (24)
+
+// These constants have the same bit positions they'll occupy
+// in low word of the TLB.
+
+#define MMU_M_PERM_EXEC             (0x00000200U)
+#define MMU_M_PERM_DATA_WRITE       (0x00000100U)
+#define MMU_M_PERM_ZONE_SELECT      (0x000000f0U)
+#define MMU_M_PERM                  (0x000003f0U)
+#define MMU_V_PERM                  (4)
+
+#define MMU_M_PROP_WRITE_THROUGH    (0x00000008U)
+#define MMU_M_PROP_UNCACHED         (0x00000004U)
+#define MMU_M_PROP_MEM_COHERENT     (0x00000002U)
+#define MMU_M_PROP_GUARDED          (0x00000001U)
+#define MMU_M_PROP                  (0x0000000fU)
+#define MMU_V_PROP                  (0)
+
+
+/*
+ * Dump (cleartext) content info from cached TLB entries
+ * to a file (stdout if f==NULL).
+ */
+void
+bsp_mmu_dump_cache(FILE *f);
+
+/* Read a TLB entry from the hardware and store the settings in the
+ * bsp_mmu_cache[] structure.
+ *
+ * The routine can perform this operation quietly or
+ * print information to a file.
+ *
+ *   'key': TLB entry index.
+ * 'quiet': perform operation silently (no info printed) if nonzero.
+ *     'f': open FILE where to print information. May be NULL, in
+ *          which case 'stdout' is used.
+ *
+ * RETURNS:
+ *       0: success; TLB entry is VALID
+ *      +1: success but TLB entry is INVALID
+ *     < 0: error (-1: invalid argument)
+ *                (-2: driver not initialized)
+ */
+int
+bsp_mmu_update(bsp_tlb_idx_t key, bool quiet, FILE *f);
+
+/* Initialize cache.  Should be done only once although this is not enforced.
+ *
+ * RETURNS: zero on success, nonzero on error; in this case the driver will
+ *          refuse to change TLB entries (other than disabling them).
+ */
+int
+bsp_mmu_initialize(void);
+
+/* Find first free TLB entry by examining all entries' valid bit.  The first
+ * entry without the valid bit set is returned.
+ *
+ * RETURNS: A free TLB entry number.  -1 if no entry can be found.
+ */
+bsp_tlb_idx_t
+bsp_mmu_find_first_free(void);
+
+/* Write a TLB entry (can also be used to disable an entry).
+ *
+ * The routine checks against the cached data in bsp_mmu_cache[]
+ * to prevent the user from generating overlapping entries.
+ *
+ *   'idx': TLB entry # to manipulate
+ *    'ea': Effective address (must be page aligned)
+ *    'pa': Physical  address (must be page aligned)
+ *    'sz': Page size selector; page size is 1024 * 2^(2*sz) bytes.
+ *          'sz' may also be one of the following:
+ *          - page size in bytes ( >= 1024 ); the selector
+ *            value is then computed by this routine.
+ *            However, 'sz' must be a valid page size
+ *            or -1 will be returned.
+ *          - a value < 0 to invalidate/disable the
+ *            TLB entry.
+ *  'flgs': Page's little-endian & user-defined flags, permissions and attributes
+ *   'tid': Translation ID
+ *
+ * RETURNS: 0 on success, nonzero on error:
+ *
+ *         >0: requested mapping would overlap with
+ *             existing mapping in another entry. Return
+ *             value gives conflicting entry + 1; i.e.,
+ *             if a value of 4 is returned then the request
+ *             conflicts with existing mapping in entry 3.
+ *         -1: invalid argument
+ *         -3: driver not initialized (or initialization failed).
+ *         <0: other error
+ */
+bsp_tlb_idx_t
+bsp_mmu_write(bsp_tlb_idx_t idx, uint32_t ea, uint32_t pa, uint sz,
+              uint32_t flgs, uint32_t tid);
+
+/* Check if a ea/tid/sz mapping overlaps with an existing entry.
+ *
+ *    'ea': The Effective Address to match against
+ *    'sz': The 'logarithmic' size selector; the page size
+ *          is 1024*2^(2*sz).
+ *   'tid': The TID to match against
+ *
+ * RETURNS:
+ *     >= 0: index of TLB entry that already provides a mapping
+ *           which overlaps within the ea range.
+ *       -1: SUCCESS (no conflicting entry found)
+ *     <=-2: ERROR (invalid input)
+ */
+bsp_tlb_idx_t
+bsp_mmu_match(uint32_t ea, int sz, uint32_t tid);
+
+/* Find TLB index that maps 'ea/tid' combination
+ *
+ *    'ea': Effective address to match against
+ *   'tid': The TID to match against
+ *
+ * RETURNS: index 'key'; i.e., the index number.
+ *
+ *          On error (no mapping) -1 is returned.
+ */
+bsp_tlb_idx_t
+bsp_mmu_find(uint32_t ea, uint32_t tid);
+
+/* Mark TLB entry as invalid ('disabled').
+ *
+ * 'key': TLB entry index.
+ *
+ * RETURNS: zero on success, nonzero on error (TLB unchanged).
+ *
+ * NOTE:  If a TLB entry is disabled the associated
+ *        entry in bsp_mmu_cache[] is also marked as disabled.
+ */
+int
+bsp_mmu_invalidate(bsp_tlb_idx_t key);
+
+/** @} */
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
diff --git a/c/src/lib/libbsp/powerpc/virtex4/irq/irq_init.c b/c/src/lib/libbsp/powerpc/virtex4/irq/irq_init.c
index 74aaebb..ba22c02 100644
--- a/c/src/lib/libbsp/powerpc/virtex4/irq/irq_init.c
+++ b/c/src/lib/libbsp/powerpc/virtex4/irq/irq_init.c
@@ -26,8 +26,6 @@
 #include <rtems/powerpc/powerpc.h>
 #include <bsp/vectors.h>

-uint32_t* IRQ_Counter = (uint32_t*)0x1500;
-
 static rtems_irq_connect_data rtemsIrqTbl[BSP_IRQ_NUMBER];
 rtems_irq_connect_data *BSP_rtems_irq_tbl;
 rtems_irq_global_settings* BSP_rtems_irq_config;
@@ -37,21 +35,21 @@ rtems_irq_global_settings* BSP_rtems_irq_config;
  * these functions just do nothing fulfill the semantic
  * requirements to enable/disable a certain interrupt or exception
  */
-void BSP_irq_nop_func(const rtems_irq_connect_data *unused)
+static void BSP_irq_nop_func(const rtems_irq_connect_data *unused)
 {
   /*
    * nothing to do
    */
 }

-void BSP_irq_nop_hdl(void *hdl)
+static void BSP_irq_nop_hdl(void *hdl)
 {
   /*
    * nothing to do
    */
 }

-int BSP_irq_isOn_func(const rtems_irq_connect_data *unused)
+static int BSP_irq_isOn_func(const rtems_irq_connect_data *unused)
 {
   /*
    * nothing to do
@@ -66,7 +64,7 @@ int BSP_irq_isOn_func(const rtems_irq_connect_data *unused)
 /***********************************************************
  * functions to enable/disable/query external/critical interrupts
  */
-void BSP_irqexc_on_fnc(rtems_irq_connect_data *conn_data)
+void BSP_irqexc_on_fnc(const rtems_irq_connect_data *conn_data)
 {
   uint32_t msr_value;
   /*
@@ -78,7 +76,7 @@ void BSP_irqexc_on_fnc(rtems_irq_connect_data *conn_data)
   _CPU_MSR_SET(msr_value);
 }

-void BSP_irqexc_off_fnc(rtems_irq_connect_data *unused)
+void BSP_irqexc_off_fnc(const rtems_irq_connect_data *unused)
 {
   uint32_t msr_value;
   /*
@@ -277,7 +275,7 @@ int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
  * dummy for an empty IRQ handler entry
  */
 static rtems_irq_connect_data emptyIrq = {
-  0, 		         /* Irq Name                 */
+  0, 		         /* IRQ Name                 */
   BSP_irq_nop_hdl,       /* handler function         */
   NULL,                  /* handle passed to handler */
   BSP_irq_nop_func,      /* on function              */
@@ -286,8 +284,8 @@ static rtems_irq_connect_data emptyIrq = {
 };

 static rtems_irq_global_settings initialConfig = {
-  BSP_IRQ_NUMBER,    /* irqNb */
-  {  0, 		         /* Irq Name                 */
+  BSP_IRQ_NUMBER,           /* IRQ Number               */
+  {  0, 		    /* IRQ Name                 */
      BSP_irq_nop_hdl,       /* handler function         */
      NULL,                  /* handle passed to handler */
      BSP_irq_nop_func,      /* on function              */
diff --git a/c/src/lib/libbsp/powerpc/virtex4/mmu/mmu.c b/c/src/lib/libbsp/powerpc/virtex4/mmu/mmu.c
new file mode 100644
index 0000000..92b4dbd
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/virtex4/mmu/mmu.c
@@ -0,0 +1,567 @@
+/**
+ * @file
+ *
+ * @ingroup Virtex4MMU
+ *
+ * @brief Implementation of routines to manipulate the PPC 405 mmu.
+ *
+ *        Since this is a real-time OS we want to stay away from
+ *        software TLB replacement.
+ */
+/*
+ * Authorship
+ * ----------
+ * This software was created by
+ *     Till Straumann <strauman at slac.stanford.edu>, 2005-2007,
+ * 	   Stanford Linear Accelerator Center, Stanford University.
+ * and was transcribed for the PPC 405 by
+ *     R. Claus <claus at slac.stanford.edu>, 2012,
+ *       Stanford Linear Accelerator Center, Stanford University,
+ *
+ * Acknowledgement of sponsorship
+ * ------------------------------
+ * This software was produced by
+ *     the Stanford Linear Accelerator Center, Stanford University,
+ * 	   under Contract DE-AC03-76SFO0515 with the Department of Energy.
+ *
+ * Government disclaimer of liability
+ * ----------------------------------
+ * Neither the United States nor the United States Department of Energy,
+ * nor any of their employees, makes any warranty, express or implied, or
+ * assumes any legal liability or responsibility for the accuracy,
+ * completeness, or usefulness of any data, apparatus, product, or process
+ * disclosed, or represents that its use would not infringe privately owned
+ * rights.
+ *
+ * Stanford disclaimer of liability
+ * --------------------------------
+ * Stanford University makes no representations or warranties, express or
+ * implied, nor assumes any liability for the use of this software.
+ *
+ * Stanford disclaimer of copyright
+ * --------------------------------
+ * Stanford University, owner of the copyright, hereby disclaims its
+ * copyright and all other rights in this software.  Hence, anyone may
+ * freely use it for any purpose without restriction.
+ *
+ * Maintenance of notices
+ * ----------------------
+ * In the interest of clarity regarding the origin and status of this
+ * SLAC software, this and all the preceding Stanford University notices
+ * are to remain affixed to any copy or derivative of this software made
+ * or distributed by the recipient and are to be affixed to any copy of
+ * software made or distributed by the recipient that contains a copy or
+ * derivative of this software.
+ *
+ * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
+ */
+
+/* 405 MSR definitions; note that there are *substantial* differences
+ * compared to classic powerpc; in particular, IS/DS are *different*
+ * from IR/DR.
+ *
+ * Also: To disable/enable all external interrupts, CE and EE must both be
+ *       controlled.
+ */
+#include <rtems.h>
+#include <rtems/bspIo.h>
+#include <rtems/powerpc/powerpc.h>
+#include <inttypes.h>
+#include <stdio.h>
+
+#include <bsp/mmu.h>
+
+
+#ifdef DEBUG
+#define STATIC
+#else
+#define STATIC static
+#endif
+
+
+bsp_tlb_entry_t* bsp_mmu_cache = 0;
+
+
+/* Since it is likely that these routines are used during
+ * early initialization when stdio is not available yet
+ * we provide a helper that resorts to 'printk()'
+ */
+static void
+myprintf(FILE *f, char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+
+  if (!f || !_impure_ptr->__sdidinit) {
+    /* Might be called at an early stage when stdio is not yet initialized. */
+    vprintk(fmt,ap);
+  } else {
+    vfprintf(f,fmt,ap);
+  }
+  va_end(ap);
+}
+
+
+void
+bsp_mmu_dump_cache(FILE *f)
+{
+  bsp_tlb_idx_t idx;
+  if ( !bsp_mmu_cache ) {
+    myprintf(stderr,"MMU TLB cache not initialized\n");
+    return;
+  }
+  for ( idx=0; idx<NTLBS; idx++ ) {
+    bsp_tlb_entry_t *tlb = bsp_mmu_cache + idx;
+    if ( !tlb->hi.v )
+      continue;
+    myprintf(f, "#%2i: EA 0x%08x .. 0x%08x, TID  0x%03x, EU0  0x%01x\n",
+             idx,
+             tlb->hi.epn << 10,
+             (tlb->hi.epn << 10) + (1024<<(2*tlb->hi.size))-1,
+             tlb->id.tid,
+             tlb->hi.att);
+    myprintf(f, "     PA 0x%08"PRIx32" .. 0x%08"PRIx32", PERM 0x%03x, WIMG 0x%02x\n",
+             tlb->lo.rpn << 10,
+             (tlb->lo.rpn << 10) + (1024<<(2*tlb->hi.size))-1,
+             tlb->lo.perm,
+             tlb->lo.wimg);
+  }
+}
+
+static void
+fetch(bsp_tlb_idx_t key, bsp_tlb_entry_t* tlb)
+{
+  register uint32_t tmp;
+  __asm__ volatile ("mfpid   %[tmp]           \n\t"
+                    "stw     %[tmp],0(%[tlb]) \n\t"
+                    "tlbrehi %[tmp],%[key]    \n\t"
+                    "stw     %[tmp],4(%[tlb]) \n\t"
+                    "tlbrelo %[tmp],%[key]    \n\t"
+                    "stw     %[tmp],8(%[tlb]) \n\t"
+                    "sync                     \n\t"
+                    : [tmp]"=&r"(tmp)
+                    : [key]"r"(key),
+                      [tlb]"b"(tlb)
+                    );
+}
+
+
+static void
+store(bsp_tlb_idx_t key, bsp_tlb_entry_t* tlb)
+{
+  register uint32_t tmp;
+  __asm__ volatile ("lwz     %[tmp],0(%[tlb]) \n\t"
+                    "mtpid   %[tmp]           \n\t"
+                    "lwz     %[tmp],4(%[tlb]) \n\t"
+                    "tlbwehi %[tmp],%[key]    \n\t"
+                    "lwz     %[tmp],8(%[tlb]) \n\t"
+                    "tlbwelo %[tmp],%[key]    \n\t"
+                    : [tmp]"=&r"(tmp)
+                    : [tlb]"b"(tlb),
+                      [key]"r"(key)
+                    );
+}
+
+
+static void
+commit(void)
+{
+  __asm__ volatile("isync           \n\t");
+}
+
+
+/*
+ * Read a TLB entry from the hardware and store the current settings in the
+ * bsp_mmu_cache[] structure.
+ *
+ * The routine can perform this operation quietly or
+ * print information to a file.
+ *
+ *   'idx': which TLB entry to access.
+ * 'quiet': perform operation silently (no info printed)
+ *          if nonzero.
+ *     'f': open FILE where to print information. May be
+ *          NULL in which case 'stdout' is used.
+ *
+ * RETURNS:
+ *       0: success; TLB entry is VALID
+ *      +1: success but TLB entry is INVALID
+ *     < 0: error (-1: invalid argument)
+ *                (-2: driver not initialized)
+ */
+int
+bsp_mmu_update(bsp_tlb_idx_t key, bool quiet, FILE *f)
+{
+  rtems_interrupt_level  lvl;
+  bsp_tlb_entry_t*       tlb;
+  bsp_tlb_idx_t          idx;
+
+  idx = key;
+
+  if ( idx < 0 || idx > NTLBS-1 )
+    return -1;
+
+  if (!bsp_mmu_cache)
+    return -2;
+
+  tlb = bsp_mmu_cache + idx;
+
+  rtems_interrupt_disable(lvl);
+
+  fetch(idx, tlb);
+
+  rtems_interrupt_enable(lvl);
+
+  if ( tlb->hi.v ) {
+    if ( !quiet ) {
+/*
+               "TLB Entry #  0 spans EA range     0x00000000 - 0x00000000
+               "Mapping:     VA     [TID 0x00 / EPN 0x00000] -> RPN 0x00000"
+               "Size:        TSIZE 0x0  (4^sz KB = 000000 KB = 0x00000000 B)
+               "Attributes:  PERM  0x00 (ex/wr/zsel) WIMG 0x00 EU0 0x0"
+*/
+      myprintf(f,
+               "TLB Entry # %2d spans EA range     0x%08x - 0x%08x\n",
+               idx,
+               (tlb->hi.epn << 10),
+               (tlb->hi.epn << 10) + (1024<<(2*tlb->hi.size)) - 1
+               );
+
+      myprintf(f,
+               "Mapping:     VA     [TID 0x%02x / EPN 0x%05x] -> RPN 0x%05"PRIx32"\n",
+               tlb->id.tid, tlb->hi.epn, tlb->lo.rpn
+               );
+      myprintf(f,
+               "Size:        TSIZE 0x%x  (4^sz KB = %6d KB = 0x%08x B)\n",
+               tlb->hi.size, (1<<(2*tlb->hi.size)), (1024<<(2*tlb->hi.size))
+               );
+      myprintf(f,
+               "Attributes:  PERM  0x%02x (ex/wr/zsel) WIMG 0x%02x EU0 0x%01x\n",
+               tlb->lo.perm, tlb->lo.wimg, tlb->hi.att
+               );
+    }
+  } else {
+    if ( !quiet ) {
+      myprintf(f,
+               "TLB Entry # %2d <OFF> (size 0x%x = 0x%xb)\n",
+               idx, tlb->hi.size, (1024<<(2*tlb->hi.size))
+               );
+    }
+    return 1;
+  }
+  return 0;
+}
+
+/* Initialize cache.  Should be done only once although this is not enforced.
+ *
+ * RETURNS: zero on success, nonzero on error; in this case the driver will
+ *          refuse to change TLB entries (other than disabling them).
+ */
+int
+bsp_mmu_initialize()
+{
+  static bsp_tlb_entry_t mmu_cache[NTLBS];
+  bsp_tlb_entry_t*       tlb = mmu_cache;  /* Should malloc if it's not too early */
+  rtems_interrupt_level  lvl;
+
+  bsp_tlb_idx_t idx;
+  rtems_interrupt_disable(lvl);
+  for (idx=0; idx<NTLBS; tlb++, idx++)
+  {
+    fetch(idx, tlb);
+  }
+  rtems_interrupt_enable(lvl);
+
+  bsp_mmu_cache = mmu_cache;
+  return 0;
+}
+
+/* Find first free TLB entry by examining all entries' valid bit.  The first
+ * entry without the valid bit set is returned.
+ *
+ * RETURNS: A free TLB entry number.  -1 if no entry can be found.
+ */
+bsp_tlb_idx_t
+bsp_mmu_find_first_free()
+{
+  bsp_tlb_idx_t   idx;
+  bsp_tlb_entry_t entry;
+
+  for (idx=0; idx<NTLBS; idx++) {
+    register uint32_t tmp;
+    __asm__ volatile ("tlbrehi %[tmp],%[idx]    \n\t"
+                      "stw     %[tmp],4(%[tlb]) \n\t" /* entry.hi */
+                      "sync                     \n\t"
+                      : [tmp]"=&r"(tmp)
+                      : [idx]"r"(idx),
+                        [tlb]"b"(&entry)
+                      : "memory"
+                      );
+    if (!(entry.hi.v))
+      break;
+  }
+  return (idx < NTLBS) ? idx : -1;
+}
+
+/*
+ * Write TLB entry (can also be used to disable an entry).
+ *
+ * The routine checks against the cached data in
+ * bsp_mmu_cache[] to prevent the user from generating
+ * overlapping entries.
+ *
+ *   'idx': TLB entry # to manipulate
+ *    'ea': Effective address (must be page aligned)
+ *    'pa': Physical  address (must be page aligned)
+ *    'sz': Page size selector; page size is
+ *          1024 * 2^(2*sz) bytes.
+ *          'sz' may also be one of the following:
+ *          - page size in bytes ( >= 1024 ); the selector
+ *            value is then computed by this routine.
+ *            However, 'sz' must be a valid page size
+ *            or -1 will be returned.
+ *          - a value < 0 to invalidate/disable the
+ *            TLB entry.
+ *  'flgs': Page's little-endian & user-defined flags, permissions and attributes
+ *   'tid': Translation ID
+ *
+ * RETURNS: 0 on success, nonzero on error:
+ *
+ *         >0: requested mapping would overlap with
+ *             existing mapping in other entry. Return
+ *             value gives conflicting entry + 1; i.e.,
+ *             if a value of 4 is returned then the request
+ *             conflicts with existing mapping in entry 3.
+ *         -1: invalid argument
+ *         -3: driver not initialized (or initialization failed).
+ *         <0: other error
+ */
+bsp_tlb_idx_t
+bsp_mmu_write(bsp_tlb_idx_t idx, uint32_t ea, uint32_t pa, uint sz,
+              uint32_t flgs, uint32_t tid)
+{
+  bsp_tlb_entry_t       tlb;
+  uint32_t              msk;
+  bsp_tlb_idx_t         lkup;
+  rtems_interrupt_level lvl;
+
+  if ( sz >= 1024 ) {
+    /* Assume they literally specify a size */
+    msk = sz;
+    sz  = 0;
+    while ( msk != (1024u<<(2*sz)) ) {
+      if ( ++sz > 7 ) {
+        return -1;
+      }
+    }
+    /* OK, acceptable */
+  }
+
+  msk = sz > 0 ? (1024u<<(2*sz)) - 1 : 0;
+
+  if ( !bsp_mmu_cache && sz > 0 ) {
+    myprintf(stderr,"MMU driver not initialized; refusing to enable any entry\n");
+    return -3;
+  }
+
+  if ( (ea & msk) || (pa & msk) ) {
+    myprintf(stderr,"Misaligned EA (%08x) or PA (%08x) (mask is %08x)\n", ea, pa, msk);
+    return -1;
+  }
+
+  if ( idx < 0 || idx > NTLBS-1 )
+    return -1;
+
+  if ( sz > 7 ) {
+    myprintf(stderr,"Invalid size %u = %08x = %u KB\n", sz, 1024u<<(2*sz), (1024u<<(2*sz))/1024);
+    return -1;
+  }
+
+  if ( sz >=0 ) {
+    lkup = bsp_mmu_match(ea, sz, tid);
+
+    if ( lkup < -1 ) {
+      /* some error */
+      return lkup;
+    }
+    if ( (lkup >= 0) && (lkup != idx) && (bsp_mmu_cache[lkup].hi.v != 0) ) {
+      myprintf(stderr,"TLB #%i overlaps with requested mapping\n", lkup);
+      bsp_mmu_update( lkup, false, stderr);
+      return lkup+1;
+    }
+  }
+
+  /* OK to proceed */
+  tlb.id.tid  = tid;
+  tlb.hi.v    = sz >= 0;
+  tlb.hi.size = sz;
+  tlb.hi.epn  = (ea & (0xfffffc00 << (sz + sz))) >> 10;
+  tlb.lo.rpn  = (pa & (0xfffffc00 << (sz + sz))) >> 10;
+  tlb.hi.att  = (flgs & MMU_M_ATTR) >> MMU_V_ATTR;
+  tlb.lo.perm = (flgs & MMU_M_PERM) >> MMU_V_PERM;
+  tlb.lo.wimg = (flgs & MMU_M_PROP) >> MMU_V_PROP;
+
+  rtems_interrupt_disable(lvl);
+
+  store(idx, &tlb);
+
+  commit();
+
+  rtems_interrupt_enable(lvl);
+
+  /* update cache */
+  bsp_mmu_update(idx, true, 0);
+
+  return 0;
+}
+
+/*
+ * Check if a ea/sz/tid mapping overlaps with an existing entry.
+ *
+ *    'ea': The Effective Address to match against
+ *    'sz': The 'logarithmic' size selector; the page size
+ *          is 1024*2^(2*sz).
+ *   'tid': The TID to match against
+ *
+ * RETURNS:
+ *     >= 0: index of the TLB entry that already provides a mapping
+ *           which overlaps within the ea range.
+ *       -1: SUCCESS (no conflicting entry found)
+ *     <=-2: ERROR (invalid input)
+ */
+bsp_tlb_idx_t
+bsp_mmu_match(uint32_t ea, int sz, uint32_t tid)
+{
+  bsp_tlb_idx_t    idx;
+  uint32_t         m,a;
+  bsp_tlb_entry_t* tlb;
+
+  if ( sz < 0 || sz > 7 )
+    return -4;
+
+  sz = (1024<<(2*sz));
+
+  if ( !bsp_mmu_cache ) {
+    /* cache not initialized */
+    return -3;
+  }
+
+  if ( ea & (sz-1) ) {
+    /* misaligned ea */
+    return -2;
+  }
+
+  for ( idx=0, tlb=bsp_mmu_cache; idx<NTLBS; idx++, tlb++ ) {
+    if ( ! tlb->hi.v )
+      continue;
+    if ( tlb->id.tid && tlb->id.tid != tid )
+      continue;
+    /* TID matches a valid entry */
+    m  = (1024<<(2*tlb->hi.size)) - 1;
+    /* calculate starting address of this entry */
+    a  = tlb->hi.epn << 10;
+    if ( ea <= a + m && ea + sz -1 >= a ) {
+      /* overlap */
+      return idx;
+    }
+  }
+  return -1;
+}
+
+/* Find TLB index that maps 'ea/tid' combination
+ *
+ *    'ea': Effective address to match against
+ *   'tid': The TID to match against
+ *
+ * RETURNS: index 'key' which indicates whether
+ *          the mapping was found.
+ *
+ *          On error (no mapping) -1 is returned.
+ */
+bsp_tlb_idx_t
+bsp_mmu_find(uint32_t ea, uint32_t tid)
+{
+  rtems_interrupt_level  lvl;
+  register uint32_t      pid;
+  register bsp_tlb_idx_t idx;
+  register int           failure;
+
+  rtems_interrupt_disable(lvl);
+
+  __asm__ volatile ("mfpid  %[pid]         \n\t" /* Save PID */
+                    "mtpid  %[tid]         \n\t"
+                    "tlbsx. %[idx],0,%[ea] \n\t" /* Failure changes the index reg randomly. */
+                    "mfcr   %[failure]     \n\t"
+                    "mtpid  %[pid]         \n\t" /* Restore PID */
+                    : [pid]"=r"(pid),
+                      [idx]"=&r"(idx),
+                      [failure]"=&r"(failure)
+                    : [tid]"r"(tid),
+                      [ea]"r"(ea)
+                    : "cc"
+                    );
+
+  rtems_interrupt_enable(lvl);
+
+  return (failure & 0x20000000) ? idx : -1;
+}
+
+/* Mark TLB entry as invalid ('disabled').
+ *
+ * 'key': TLB entry (index).
+ *
+ * RETURNS: zero on success, nonzero on error (TLB unchanged).
+ *
+ * NOTE:  If a TLB entry is disabled the associated
+ *        entry in bsp_mmu_cache[] is also
+ *        marked as disabled.
+ */
+int
+bsp_mmu_invalidate(bsp_tlb_idx_t key)
+{
+  bsp_tlb_idx_t         k0;
+  rtems_interrupt_level lvl;
+  bsp_tlb_entry_t       tlb;
+  uint32_t              msr;
+
+  /* Minimal guard against bad key */
+  if ( key < 0 || key > NTLBS-1 )
+    return -1;
+
+  _CPU_MSR_GET(msr);
+
+  /* While address translation is enabled... */
+  if (msr & (PPC_MSR_IR | PPC_MSR_DR))
+  {
+    /* Must not invalidate page 0 which holds vectors, text etc...  */
+    k0 = bsp_mmu_find(0, 0);
+    if ( -1 == k0 ) {
+      myprintf(stderr,"No mapping for address 0 found\n");
+      return -2;
+    }
+
+    /* NOTE: we assume PID is ignored */
+    if ( k0 == key ) {
+      myprintf(stderr,"Cannot invalidate page holding address 0 (always needed)\n");
+      return -3;
+    }
+  }
+
+  rtems_interrupt_disable(lvl);
+
+  fetch(key, &tlb);
+
+  /* Invalidate old entries */
+  tlb.hi.v = 0;
+
+  store(key, &tlb);
+
+  commit();
+
+  /* update cache */
+  bsp_mmu_cache[ key ].hi.v = tlb.hi.v;
+
+  rtems_interrupt_enable(lvl);
+
+  return 0;
+}
diff --git a/c/src/lib/libbsp/powerpc/virtex4/preinstall.am b/c/src/lib/libbsp/powerpc/virtex4/preinstall.am
index 34b03f1..e441f38 100644
--- a/c/src/lib/libbsp/powerpc/virtex4/preinstall.am
+++ b/c/src/lib/libbsp/powerpc/virtex4/preinstall.am
@@ -69,6 +69,10 @@ $(PROJECT_INCLUDE)/bsp/irq.h: include/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h

+$(PROJECT_INCLUDE)/bsp/mmu.h: include/mmu.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/mmu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/mmu.h
+
 $(PROJECT_INCLUDE)/bsp/vectors.h: ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/vectors.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/vectors.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/vectors.h
diff --git a/c/src/lib/libbsp/powerpc/virtex4/startup/bspstart.c b/c/src/lib/libbsp/powerpc/virtex4/startup/bspstart.c
index 2aab2c2..73c2f84 100644
--- a/c/src/lib/libbsp/powerpc/virtex4/startup/bspstart.c
+++ b/c/src/lib/libbsp/powerpc/virtex4/startup/bspstart.c
@@ -54,20 +54,23 @@
  *  Modifications for PPC405GP by Dennis Ehlin
  *  Modifications for Virtex4 by Richard Claus <claus at slac.stanford.edu>
  */
-
-#include <string.h>
-#include <fcntl.h>
-
-#include <bsp.h>
-#include <bsp/irq.h>
-#include <bsp/vectors.h>
+#include <rtems.h>
+#include <rtems/config.h>
 #include <rtems/bspIo.h>
 #include <rtems/libio.h>
 #include <rtems/libcsupport.h>
-#include <rtems/sptables.h>             /* for RTEMS_VERSION */
+
 #include <libcpu/cpuIdent.h>
 #include <libcpu/spr.h>

+#include <bsp.h>
+#include <bsp/vectors.h>
+#include <bsp/bootcard.h>
+#include <bsp/irq.h>
+
+#include <string.h>
+#include <fcntl.h>
+
 #define DO_DOWN_ALIGN(x,a) ((x) & ~((a)-1))

 #define DO_UP_ALIGN(x,a)   DO_DOWN_ALIGN(((x) + (a) - 1 ),a)
@@ -76,13 +79,6 @@
 #define CPU_UP_ALIGN(x)    DO_UP_ALIGN(x, CPU_ALIGNMENT)


-/* Expected by clock.c */
-uint32_t    bsp_clicks_per_usec;
-bool        bsp_timer_internal_clock;   /* true, when timer runs with CPU clk */
-uint32_t    bsp_timer_least_valid;
-uint32_t    bsp_timer_average_overhead;
-
-
 /* Defined in linkcmds linker script */
 LINKER_SYMBOL(RamBase);
 LINKER_SYMBOL(RamSize);
@@ -96,35 +92,24 @@ LINKER_SYMBOL(WorkAreaBase);
 LINKER_SYMBOL(MsgAreaBase);
 LINKER_SYMBOL(MsgAreaSize);
 LINKER_SYMBOL(__phy_ram_end);
+LINKER_SYMBOL(bsp_exc_vector_base);
+
+
+/* Expected by clock.c */
+uint32_t    bsp_clicks_per_usec;
+bool        bsp_timer_internal_clock;   /* true, when timer runs with CPU clk */
+uint32_t    bsp_timer_least_valid;
+uint32_t    bsp_timer_average_overhead;


 /*
  * Provide weak aliases so that RTEMS distribution builds
  */
 static void _noopfun(void) {}
-static void _bsp_start(void)
-{
-  uintptr_t         intrStackStart = CPU_UP_ALIGN((uint32_t)__bsp_ram_start);
-  uintptr_t         intrStackSize  = rtems_configuration_get_interrupt_stack_size();
-
-  /*
-   * Initialize default raw exception handlers.
-   *
-   * This BSP does not assume anything about firmware possibly loaded in the
-   * FPGA, so the external interrupt should not be enabled in order to avoid
-   * spurious interrupts.
-   */
-  ppc_exc_initialize(PPC_INTERRUPT_DISABLE_MASK_DEFAULT & ~MSR_EE,
-                     intrStackStart,
-                     intrStackSize);
-
-  /* Install our own set of exception vectors */
-  BSP_rtems_irq_mngt_init(0);
-}


 void app_bsp_start(void)
-__attribute__(( weak, alias("_bsp_start") ));
+__attribute__(( weak, alias("_noopfun") ));

 void app_bsp_pretasking_hook(void)
 __attribute__(( weak, alias("_noopfun") ));
@@ -147,20 +132,31 @@ static void __bsp_outchar_to_memory(char c)
 void BSP_ask_for_reset(void)
 {
   printk("\nSystem stopped, issue RESET");
+
   for(;;);
 }


 void BSP_panic(char *s)
 {
-  printk("\n%s PANIC %s\n", _RTEMS_version, s);
+  rtems_interrupt_level level;
+
+  rtems_interrupt_disable(level);
+
+  printk("\n%s PANIC %s\n", rtems_get_version_string(), s);
+
   BSP_ask_for_reset();
 }


 void _BSP_Fatal_error(unsigned int v)
 {
-  printk("\n%s FATAL ERROR %x\n", _RTEMS_version, v);
+  rtems_interrupt_level level;
+
+  rtems_interrupt_disable(level);
+
+  printk("\n%s FATAL ERROR %x\n", rtems_get_version_string(), v);
+
   BSP_ask_for_reset();
 }

@@ -176,13 +172,14 @@ void bsp_start(void)
 {
   uintptr_t          intrStackStart;
   uintptr_t          intrStackSize;
+
   ppc_cpu_id_t       myCpu;
   ppc_cpu_revision_t myCpuRevision;

   /* Set the character output function;  The application may override this */
   BSP_output_char = __bsp_outchar_to_memory;

-  printk("\nWelcome to RTEMS %s\n", _RTEMS_version );
+  printk("RTEMS %s\n", rtems_get_version_string());

   /*
    * Get CPU identification dynamically. Note that the get_ppc_cpu_type()
@@ -208,6 +205,12 @@ void bsp_start(void)
    */
   intrStackStart = CPU_UP_ALIGN((uint32_t)__bsp_ram_start);
   intrStackSize  = rtems_configuration_get_interrupt_stack_size();
+
+  ppc_exc_initialize(PPC_INTERRUPT_DISABLE_MASK_DEFAULT,
+                     intrStackStart,
+                     intrStackSize);
+
+  /* Let the user know what parameters we were compiled with */
   printk("                  Base/Start     End         Size\n"
          "RAM:              0x%08x              0x%x\n"
          "RTEMS:                        0x%08x\n"
@@ -224,6 +227,11 @@ void bsp_start(void)
          (uint32_t)MsgAreaBase,                           (uint32_t)MsgAreaSize,
          (uint32_t)__phy_ram_end);

+  /*
+   * Initialize RTEMS IRQ system
+   */
+  BSP_rtems_irq_mngt_init(0);
+
   /* Continue with application-specific initialization */
   app_bsp_start();
 }
diff --git a/c/src/lib/libbsp/powerpc/virtex4/startup/linkcmds b/c/src/lib/libbsp/powerpc/virtex4/startup/linkcmds
index cff5767..74a10aa 100644
--- a/c/src/lib/libbsp/powerpc/virtex4/startup/linkcmds
+++ b/c/src/lib/libbsp/powerpc/virtex4/startup/linkcmds
@@ -20,16 +20,17 @@ HeapSize          = DEFINED(HeapSize)      ? HeapSize      : 0; /* 0=Use def */

 MEMORY
 {
-  VECTORS         : ORIGIN = 0x00000000, LENGTH = 8K
-  RAM             : ORIGIN = 0x00002000, LENGTH = 128M - 8K
+  VECTORS         : ORIGIN = 0x00000000, LENGTH = 12K
+  RAM             : ORIGIN = 0x00003000, LENGTH = 128M - 12K
 }


 SECTIONS
 {
-  __exeentry      = download_entry;
-  __exestart      = 0x100;
-  .vectors __exestart : { *(.vectors)                           } > VECTORS
+  bsp_exc_vector_base = 0x100;
+  __exeentry          = download_entry;
+  __exestart          = bsp_exc_vector_base;
+  .vectors bsp_exc_vector_base : { *(.vectors)                  } > VECTORS

   /* Read-only sections, merged into text segment: */
   .interp         : { *(.interp)                                } > RAM
@@ -249,7 +250,7 @@ _SDA_BASE_ = __SDATA_START__ + 0x8000;

   /* Message area for capturing early printk output */
   /* Placed here to be easily findable with a debugger */
-  MsgAreaBase     = __bsp_ram_end;
+  MsgAreaBase     = .;
   .              += MsgAreaSize;

   __phy_ram_end   = .;                  /* True end of physical memory */
diff --git a/c/src/lib/libbsp/powerpc/virtex4/startup/start.S b/c/src/lib/libbsp/powerpc/virtex4/startup/start.S
index c3053fb..55d5318 100644
--- a/c/src/lib/libbsp/powerpc/virtex4/startup/start.S
+++ b/c/src/lib/libbsp/powerpc/virtex4/startup/start.S
@@ -166,15 +166,15 @@ startupDow:
         * Tell the processor where the exception vector table will be.
         *------------------------------------------------------------------*/
         .extern SYM(__vectors)
-        lis     r0, __vectors at h    /* set EVPR exc. vector prefix */
-        mtspr   evpr,r0
+        lis     r2, __vectors at h    /* set EVPR exc. vector prefix */
+        mtevpr  r2

        /*-------------------------------------------------------------------
         * Set up the debug register to freeze timers on debug events.
         *------------------------------------------------------------------*/
-        mfdbcr0 r0
-        ori     r0,r0,0x0001
-        mtdbcr0 r0
+        mfdbcr0 r2
+        ori     r2,r2,0x0001
+        mtdbcr0 r2
         isync

         /* Select whether APU, Wait Enable, interrupts/exceptions and address
@@ -182,14 +182,20 @@ startupDow:
         lis     r0,0x00000000 at h   /* SRR1 value */
         mtsrr1  r0                /* Potentially: 0x80000000 >> 6 is APU */

+        /* Configure timer facilities */
+        mttbl   r0                /* Clear Timebase to prevent Fixed Interval.. */
+        mttbu   r0                /* ..timer and Watchdog Timer exceptions */
+        mtpit   r0                /* Programmable interval timer */
+        li      r2,-1             /* -1 to clear TSR */
+        mttsr   r2                /* Timer status register */
+
         /* Clear out stale values in certain registers to avoid confusion */
+        mtcrf   0xff,r0           /* Need for simulation */
+        mtctr   r0                /* Counter register */
         mtxer   r0                /* Fixed-point exception register */
         mtesr   r0                /* Exception syndrome register */
         mtdear  r0                /* Data exception address register */
         mtmcsr  r0                /* Machine check syndrome register */
-        mtpit   r0                /* Programmable interval timer */
-        li      r0,-1             /* -1 to clear TSR */
-        mttsr   r0                /* Timer status register */

         /* Invalidate the data cache */
         li      r2,0              /* Start address */
--
1.7.1




More information about the devel mailing list