New (Submission by Bruce Robinson <brucer@pmccorp.com>)

This commit is contained in:
Ralf Corsepius
2006-03-16 17:34:05 +00:00
parent 128f3d0f9e
commit 15ebdf1f6b
21 changed files with 3722 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
aclocal.m4
autom4te*.cache
config.cache
config.guess
config.log
config.status
config.sub
configure
depcomp
install-sh
Makefile
Makefile.in
missing
mkinstalldirs

View File

@@ -0,0 +1,12 @@
2006-03-16 Ralf Corsépius <ralf.corsepius@rtems.org>
* liblnk/pmon.S, liblnk/regs.S, liblnk/lnklib.S,
README, bsp_specs, configure.ac, startup/inittlb.c,
startup/bspstart.c, startup/idtmem.S, startup/exception.S,
startup/bspclean.c, startup/idttlb.S, startup/linkcmds,
include/tm27.h, include/bsp.h, clock/clockdrv.c, Makefile.am,
start/start.S, console/console-io.c:
New (Submission by Bruce Robinson <brucer@pmccorp.com>).
* The RBTX4925 BSP is for a Toshiba TX4925 evaluation board.

View File

@@ -0,0 +1,114 @@
##
## $Id$
##
ACLOCAL_AMFLAGS = -I ../../../../aclocal
include $(top_srcdir)/../../../../automake/compile.am
include $(top_srcdir)/../../bsp.am
dist_project_lib_DATA = bsp_specs
include_HEADERS = include/bsp.h
include_HEADERS += include/tm27.h
nodist_include_HEADERS = include/bspopts.h
DISTCLEANFILES = include/bspopts.h
noinst_PROGRAMS =
nodist_include_HEADERS += ../../shared/include/coverhd.h
EXTRA_DIST = start/start.S start/regs.S
start.$(OBJEXT): start/start.S
$(CPPASCOMPILE) -DASM -o $@ -c $<
project_lib_DATA = start.$(OBJEXT)
dist_project_lib_DATA += startup/linkcmds
noinst_PROGRAMS += startup.rel
startup_rel_SOURCES = ../../shared/bspclean.c \
../../shared/bsplibc.c ../../shared/bsppost.c startup/bspstart.c \
../../shared/bootcard.c ../../shared/main.c ../../shared/sbrk.c \
../../shared/gnatinstallhandler.c ../../shared/setvec.c \
startup/inittlb.c \
startup/idtmem.S startup/idttlb.S startup/exception.S
startup_rel_CPPFLAGS = $(AM_CPPFLAGS)
startup_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
# FIXME: clockdrv.c and clockdrv_shell.c are structurally flawed
clock_CPPFLAGS = -I$(srcdir)/../../shared
EXTRA_DIST += ../../mips/shared/clockdrv_shell.c
noinst_PROGRAMS += clock.rel
clock_rel_SOURCES = clock/clockdrv.c
clock_rel_CPPFLAGS = $(AM_CPPFLAGS) $(clock_CPPFLAGS)
clock_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
noinst_PROGRAMS += console.rel
console_rel_SOURCES = console/console-io.c
console_rel_CPPFLAGS = $(AM_CPPFLAGS)
console_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
noinst_PROGRAMS += liblnk.rel
liblnk_rel_SOURCES = liblnk/lnklib.S liblnk/pmon.S
liblnk_rel_CPPFLAGS = $(AM_CPPFLAGS)
liblnk_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
noinst_LIBRARIES = libbsp.a
libbsp_a_SOURCES =
libbsp_a_LIBADD = startup.rel clock.rel console.rel liblnk.rel
libbsp_a_LIBADD += ../../../libcpu/@RTEMS_CPU@/shared/cache.rel \
../../../libcpu/@RTEMS_CPU@/shared/interrupts.rel \
../../../libcpu/@RTEMS_CPU@/tx49/timer.rel \
../../../libcpu/@RTEMS_CPU@/tx49/vectorisrs.rel
all-local: $(PREINSTALL_FILES) $(TMPINSTALL_FILES)
PREINSTALL_DIRS =
PREINSTALL_FILES =
TMPINSTALL_FILES =
$(PROJECT_INCLUDE)/$(dirstamp):
@$(mkdir_p) $(PROJECT_INCLUDE)
@: > $(PROJECT_INCLUDE)/$(dirstamp)
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp)
$(PROJECT_LIB)/$(dirstamp):
@$(mkdir_p) $(PROJECT_LIB)
@: > $(PROJECT_LIB)/$(dirstamp)
PREINSTALL_DIRS += $(PROJECT_LIB)/$(dirstamp)
$(PROJECT_LIB)/bsp_specs: bsp_specs $(PROJECT_LIB)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_LIB)/bsp_specs
PREINSTALL_FILES += $(PROJECT_LIB)/bsp_specs
$(PROJECT_INCLUDE)/bsp.h: include/bsp.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp.h
$(PROJECT_INCLUDE)/tm27.h: include/tm27.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/tm27.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/tm27.h
$(PROJECT_INCLUDE)/bspopts.h: include/bspopts.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bspopts.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bspopts.h
$(PROJECT_INCLUDE)/coverhd.h: ../../shared/include/coverhd.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/coverhd.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/coverhd.h
$(PROJECT_LIB)/start.$(OBJEXT): start.$(OBJEXT) $(PROJECT_LIB)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_LIB)/start.$(OBJEXT)
TMPINSTALL_FILES += $(PROJECT_LIB)/start.$(OBJEXT)
$(PROJECT_LIB)/linkcmds: startup/linkcmds $(PROJECT_LIB)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds
PREINSTALL_FILES += $(PROJECT_LIB)/linkcmds
CLEANFILES = $(PREINSTALL_FILES)
DISTCLEANFILES += $(PREINSTALL_DIRS)
CLEANFILES += $(TMPINSTALL_FILES)
include $(top_srcdir)/../../../../automake/local.am

View File

@@ -0,0 +1,46 @@
#
# README,v 1.2 1998/01/16 16:56:31 joel Exp
#
# @(#)README 08/20/96 1.2
#
BSP NAME: rbtx4925
BOARD: Toshiba RBTX4925 SBC
BUS: N/A
CPU FAMILY: mips
CPU: TX4925
COPROCESSORS: N/A
MODE: 32 bit mode
DEBUG MONITOR: PMON
PERIPHERALS
===========
TIMERS: TX4925 internal
SERIAL PORTS: PMON controlled
REAL-TIME CLOCK: none
DMA: none
VIDEO: none
SCSI: none
NETWORKING: none
DRIVER INFORMATION
==================
CLOCK DRIVER: TX4925 internal
IOSUPP DRIVER: N/A
SHMSUPP: N/A
TIMER DRIVER: TX4925 internal
TTY DRIVER: uses PMON
STDIO
=====
PORT: Console port 0
ELECTRICAL: RS-232
BAUD: 9600
BITS PER CHARACTER: 8
PARITY: None
STOP BITS: 1
NOTES
=====

View File

@@ -0,0 +1,21 @@
%rename lib old_lib
%rename endfile old_endfile
%rename startfile old_startfile
%rename link old_link
*lib:
%{!qrtems: %(old_lib)} %{!nostdlib: %{qrtems: --start-group \
%{!qrtems_debug: -lrtemsbsp -lrtemscpu} %{qrtems_debug: -lrtemsbsp_g -lrtemscpu_g} \
-lc -lgcc --end-group \
%{!qnolinkcmds: -T linkcmds%s}}}
*startfile:
%{!qrtems: %(old_startfile)} %{!nostdlib: %{qrtems: \
%{!qrtems_debug: start.o%s} \
%{qrtems_debug: start_g.o%s} crti.o%s crtbegin.o%s }}
*link:
%{!qrtems: %(old_link)} %{qrtems: --oformat=elf32-littlemips -dc -dp -N -e start}
*endfile:
%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s crtn.o%s }

View File

@@ -0,0 +1,112 @@
/*
* Instantiate the clock driver shell.
*
* clockdrv.c,v 1.5 2001/01/09 17:05:57 joel Exp
*/
#include <rtems.h>
#include <libcpu/tx4925.h>
#include <bsp.h>
/* #define CLOCK_DRIVER_USE_FAST_IDLE */
#define CLOCK_VECTOR TX4925_IRQ_TMR0
#define TX4925_TIMER_INTERVAL_MODE 1
#define TX4925_TIMER_PULSE_MODE 2
#define TX4925_TIMER_MODE TX4925_TIMER_INTERVAL_MODE
#if (TX4925_TIMER_MODE == TX4925_TIMER_INTERVAL_MODE)
#define TX4925_TIMER_INTERRUPT_FLAG TIIS
#define Clock_driver_support_initialize_hardware() \
Initialize_timer0_in_interval_mode()
#elif (TX4925_TIMER_MODE == TX4925_TIMER_PULSE_MODE)
#define TX4925_TIMER_INTERRUPT_FLAG TPIBS
#define Clock_driver_support_initialize_hardware() \
Initialize_timer0_in_pulse_mode()
#else
#error "Build Error: need to select timer mode"
#endif
#define Clock_driver_support_install_isr( _new, _old ) \
do { \
_old = set_vector( _new, CLOCK_VECTOR, 1 ); \
} while(0)
#define Clock_driver_support_at_tick() \
do { \
uint32_t interrupt_flag; \
do { \
int loop_count; \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_TISR, 0x0 ); /* Clear timer 0 interrupt */ \
loop_count = 0; \
do { /* Wait until interrupt flag is cleared (this prevents re-entering interrupt) */ \
/* Read back interrupt status register and isolate interval timer flag */ \
interrupt_flag = TX4925_REG_READ( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_TISR ) & TX4925_TIMER_INTERRUPT_FLAG; \
} while (interrupt_flag && (++loop_count < 10)); /* Loop while timer interrupt bit is set, or loop count is lees than 10 */ \
} while(interrupt_flag); \
} while(0)
/* Setup timer in interval mode to generate peiodic interrupts */
#define Initialize_timer0_in_interval_mode() \
do { \
uint32_t temp; \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_TCR, 0x0 ); /* Disable timer */ \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_CCDR, 0x0 ); /* Set register for divide by 2 clock */ \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_ITMR, TIMER_CLEAR_ENABLE_MASK ); /* Set interval timer mode register */ \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_CPRA, 0x30d40 ); /* Set tmier period ,10.0 msec (20 MHz timer clock) */ \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_TCR, 0xC0 ); /* Enable timer in interval mode */ \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_IRQCTL_DM0, 0x0 ); /* Set interrupt controller detection mode */ \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_IRQCTL_LVL2, 0x1000000 ); /* Set interrupt controller level */ \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_IRQCTL_MSK, 0x0 ); /* Set interrupt controller mask */ \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_IRQCTL_DEN, 0x1 ); /* Enable interrupts from controller */ \
temp = TX4925_REG_READ( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_ITMR ); /* Enable interval timer interrupts */ \
temp |= TIMER_INT_ENABLE_MASK; \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_ITMR, temp ); \
} while(0)
/* This mode is used to generate periodic interrupts and also output a pulse on PIO20 pin */
#define Initialize_timer0_in_pulse_mode() \
do { \
uint32_t temp; \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_TCR, 0x0 ); /* Disable timer */ \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_CCDR, 0x0 ); /* Set register for divide by 2 clock */ \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_PGMR, FFI ); /* Set pulse generator mode register */ \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_CPRA, 0x3e8 ); /* Set pulse high duration ,0.05 msec (20 MHz timer clock) */ \
/* TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_CPRB, 0x1388 ); */ /* Set pulse total period, 0.25 msec (20 MHz timer clock) */ \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_CPRB, 0x30d40 ); /* Set pulse total period, 10 msec (20 MHz timer clock) */ \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_TCR, 0xC1 ); /* Enable timer in pulse generator mode */ \
\
/* Enable timer 0 output pulses on PIO20 */ \
temp = TX4925_REG_READ( TX4925_REG_BASE, TX4925_CFG_PCFG ); \
temp = (temp & ~ SELCHI) | SELTMR0; /* Enable timer 0 pulses on PIO20 */ \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_CFG_PCFG, temp ); \
\
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_IRQCTL_DM0, 0x0 ); /* Set interrupt controller detection mode */ \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_IRQCTL_LVL2, 0x1000000 ); /* Set interrupt controller level */ \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_IRQCTL_MSK, 0x0 ); /* Set interrupt controller mask */ \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_IRQCTL_DEN, 0x1 ); /* Enable interrupts from controller */ \
temp = TX4925_REG_READ( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_PGMR ); /* Enable pulse generator interrupt */ \
temp |= TPIBE; /* Only want interrupts on B compare (where clock count is cleared) */ \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_PGMR, temp ); \
} while(0)
#define Clock_driver_support_shutdown_hardware() \
do { \
uint32_t temp; \
temp = TX4925_REG_READ( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_ITMR ); /* Disable interval timer interrupt */ \
temp &= ~TIMER_INT_ENABLE_MASK; \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_ITMR, temp ); \
temp = TX4925_REG_READ( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_PGMR ); /* Disable pulse generator interrupt */ \
temp &= ~(TPIAE | TPIBE); \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_PGMR, temp ); \
TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_TCR, 0x0 ); /* Disable timer */ \
} while(0)
#include "../../../shared/clockdrv_shell.c"

View File

@@ -0,0 +1,21 @@
## Process this file with autoconf to produce a configure script.
##
## configure.ac,v 1.6.2.2 2003/08/11 14:38:01 ralf Exp
AC_PREREQ(2.59)
AC_INIT([rtems-c-src-lib-libbsp-mips-rbtx4925],[_RTEMS_VERSION],[rtems-bugs@rtems.com])
AC_CONFIG_SRCDIR([bsp_specs])
RTEMS_TOP(../../../../../..)
RTEMS_CANONICAL_TARGET_CPU
AM_INIT_AUTOMAKE([no-define nostdinc foreign 1.9])
RTEMS_BSP_CONFIGURE
RTEMS_PROG_CC_FOR_TARGET([-ansi -fasm])
RTEMS_CANONICALIZE_TOOLS
RTEMS_PROG_CCAS
# Explicitly list all Makefiles here
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

View File

@@ -0,0 +1,272 @@
/*
* This file contains the RBTX4925 console IO package.
*
* Author: Craig Lebakken <craigl@transition.com>
*
* COPYRIGHT (c) 1996 by Transition Networks Inc.
*
* 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 Transition Networks not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* Transition Networks makes no representations about the suitability
* of this software for any purpose.
*
* Derived from c/src/lib/libbsp/no_cpu/no_bsp/console/console.c:
*
* 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$
*/
/*
* Rather than deleting this, it is commented out to (hopefully) help
* the submitter send updates.
*
* static char _sccsid[] = "@(#)console.c 08/20/96 1.6\n";
*/
#include <bsp.h>
#include <rtems/libio.h>
#include <ctype.h>
/* PMON entry points */
int mon_read(int fd, char *buf, int cnt); /* stdin is fd=0 */
int mon_write(int fd, char *buf, int cnt); /* stdout is fd=1 */
/* console_initialize
*
* This routine initializes the console IO driver.
*
* Input parameters: NONE
*
* Output parameters: NONE
*
* Return values:
*/
rtems_device_driver console_initialize(
rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg
)
{
rtems_status_code status;
status = rtems_io_register_name(
"/dev/console",
major,
(rtems_device_minor_number) 0
);
if (status != RTEMS_SUCCESSFUL)
rtems_fatal_error_occurred(status);
return RTEMS_SUCCESSFUL;
}
/* is_character_ready
*
* This routine returns TRUE if a character is available.
*
* Input parameters: NONE
*
* Output parameters: NONE
*
* Return values:
*/
rtems_boolean is_character_ready(
char *ch
)
{
*ch = '\0'; /* return NULL for no particular reason */
return(TRUE);
}
/* inbyte
*
* This routine reads a character from the SOURCE.
*
* Input parameters: NONE
*
* Output parameters: NONE
*
* Return values:
* character read from SOURCE
*/
char inbyte( void )
{
char buf[10];
/*
* If polling, wait until a character is available.
*/
mon_read(0, buf, 1); /* stdin is fd=0, read 1 byte */
return (buf[0]);
}
/* outbyte
*
* This routine transmits a character out the SOURCE. It may support
* XON/XOFF flow control.
*
* Input parameters:
* ch - character to be transmitted
*
* Output parameters: NONE
*/
void outbyte(
char ch
)
{
char buf[10];
/*
* If polling, wait for the transmitter to be ready.
* Check for flow control requests and process.
* Then output the character.
*/
buf[0] = ch;
mon_write( 1, buf, 1 ); /* stdout is fd=1, write 1 byte */
}
#if 0
static int console_fd = -1;
#endif
/*
* Open entry point
*/
rtems_device_driver console_open(
rtems_device_major_number major,
rtems_device_minor_number minor,
void * arg
)
{
#if 0
int console_fd = open("tty0", 2); /* open for read/write */
#endif
return RTEMS_SUCCESSFUL;
}
/*
* Close entry point
*/
rtems_device_driver console_close(
rtems_device_major_number major,
rtems_device_minor_number minor,
void * arg
)
{
#if 0
if ( console_fd )
close( console_fd );
#endif
return RTEMS_SUCCESSFUL;
}
/*
* read bytes from the serial port. We only have stdin.
*/
rtems_device_driver console_read(
rtems_device_major_number major,
rtems_device_minor_number minor,
void * arg
)
{
rtems_libio_rw_args_t *rw_args;
char *buffer;
int maximum;
int count = 0;
rw_args = (rtems_libio_rw_args_t *) arg;
buffer = rw_args->buffer;
maximum = rw_args->count;
for (count = 0; count < maximum; count++) {
buffer[ count ] = inbyte();
if (buffer[ count ] == '\n' || buffer[ count ] == '\r') {
buffer[ count++ ] = '\n';
break;
}
}
rw_args->bytes_moved = count;
return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
}
/*
* write bytes to the serial port. Stdout and stderr are the same.
*/
rtems_device_driver console_write(
rtems_device_major_number major,
rtems_device_minor_number minor,
void * arg
)
{
int count;
int maximum;
rtems_libio_rw_args_t *rw_args;
char *buffer;
rw_args = (rtems_libio_rw_args_t *) arg;
buffer = rw_args->buffer;
maximum = rw_args->count;
for (count = 0; count < maximum; count++) {
if ( buffer[ count ] == '\n') {
outbyte('\r');
}
outbyte( buffer[ count ] );
}
rw_args->bytes_moved = maximum;
return 0;
}
/*
* IO Control entry point
*/
rtems_device_driver console_control(
rtems_device_major_number major,
rtems_device_minor_number minor,
void * arg
)
{
return RTEMS_SUCCESSFUL;
}
#include <rtems/bspIo.h>
void RBTX4925_output_char(char c) { outbyte( c ); }
BSP_output_char_function_type BSP_output_char = RBTX4925_output_char;
BSP_polling_getchar_function_type BSP_poll_char = NULL;

View File

@@ -0,0 +1,96 @@
/* bsp.h
*
* This include file contains some definitions specific to the RBTX4925.
*
* COPYRIGHT (c) 1989-2000.
* 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.
*
* bsp.h,v 1.7.6.1 2003/09/04 18:44:49 joel Exp
*/
#ifndef __RBTX4925_h
#define __RBTX4925_h
#ifdef __cplusplus
extern "C" {
#endif
#include <bspopts.h>
#include <rtems.h>
#include <rtems/iosupp.h>
#include <rtems/console.h>
#include <rtems/clockdrv.h>
#include <libcpu/tx4925.h>
/*
* Define the time limits for RTEMS Test Suite test durations.
* Long test and short test duration limits are provided. These
* values are in seconds and need to be converted to ticks for the
* application.
*
*/
#define MAX_LONG_TEST_DURATION 300 /* 5 minutes = 300 seconds */
#define MAX_SHORT_TEST_DURATION 3 /* 3 seconds */
/*
* Define the interrupt mechanism for Time Test 27
*
* NOTE: Following are for XXX and are board independent
*
*/
#define MUST_WAIT_FOR_INTERRUPT 1
#define Install_tm27_vector( handler ) \
do { \
} while(0)
#define Cause_tm27_intr() \
do { \
} while(0)
#define Clear_tm27_intr() \
do { \
} while(0)
#define Lower_tm27_intr() \
do { \
} while(0)
/* Constants */
/* miscellaneous stuff assumed to exist */
extern rtems_configuration_table BSP_Configuration;
/*
* Device Driver Table Entries
*/
/*
* NOTE: Use the standard Console driver entry
*/
/*
* NOTE: Use the standard Clock driver entry
*/
/* functions */
void bsp_cleanup( void );
rtems_isr_entry set_vector(
rtems_isr_entry, rtems_vector_number, int );
#ifdef __cplusplus
}
#endif
#endif
/* end of include file */

View File

@@ -0,0 +1,32 @@
/*
* tm27.h
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* $Id$
*/
#ifndef _RTEMS_TMTEST27
#error "This is an RTEMS internal file you must not include directly."
#endif
#ifndef __tm27_h
#define __tm27_h
/*
* Define the interrupt mechanism for Time Test 27
*/
#define MUST_WAIT_FOR_INTERRUPT 0
#define Install_tm27_vector( handler ) set_vector( (handler), 0, 1 )
#define Cause_tm27_intr() /* empty */
#define Clear_tm27_intr() /* empty */
#define Lower_tm27_intr() /* empty */
#endif

View File

@@ -0,0 +1,62 @@
/*
* lnklib.S,v 1.4 1999/03/31 23:21:19 joel Exp
*/
#include <rtems/mips/iregdef.h>
#include <rtems/mips/idtcpu.h>
#define FRAME(name,frm_reg,offset,ret_reg) \
.globl name; \
.ent name; \
name:; \
.frame frm_reg,offset,ret_reg
#define ENDFRAME(name) \
.end name
#define PROM_LINK(name,entry) \
.globl name; \
.ent name; \
name: la $2,+entry; \
j $2; \
.end name
#define PROM_ENTRY(x) (0xbfc00000+((x)*8))
#define PROM_RESET PROM_ENTRY(0)
#define PROM_NOT_IMP PROM_ENTRY(1)
#define PROM_RESTART PROM_ENTRY(2)
#define PROM_REINIT PROM_ENTRY(3)
#define PROM_GETCHAR PROM_ENTRY(11)
#define PROM_PUTCHAR PROM_ENTRY(12)
#define PROM_SHOWCHAR PROM_ENTRY(13)
#define PROM_PRINTF PROM_ENTRY(16)
#define PROM_RETURN PROM_ENTRY(17)
#define PROM_RGETS PROM_ENTRY(25)
#define PROM_FLUSHCACHE PROM_ENTRY(28)
#define PROM_CLEARCACHE PROM_ENTRY(29)
#define PROM_SETJMP PROM_ENTRY(30)
#define PROM_LONGJMP PROM_ENTRY(31)
.text
PROM_LINK(idtsim_putchar, PROM_PUTCHAR)
PROM_LINK(idtsim_getchar, PROM_GETCHAR)
PROM_LINK(idtsim_showchar, PROM_SHOWCHAR)
PROM_LINK(idtsim__exit, PROM_RETURN)
PROM_LINK(idtsim_reinit, PROM_REINIT)
PROM_LINK(idtsim_restart, PROM_RESTART)
PROM_LINK(idtsim_reset, PROM_RESET)
PROM_LINK(idtsim_promexit, PROM_RETURN)
PROM_LINK(idtsim_setjmp, PROM_SETJMP)
PROM_LINK(idtsim_longjmp, PROM_LONGJMP)
FRAME(idtsim_init_sbrk,sp,0,ra)
j ra
ENDFRAME(idtsim_init_sbrk)
FRAME(idtsim_init_file,sp,0,ra)
j ra
ENDFRAME(idtsim_init_file)

View File

@@ -0,0 +1,180 @@
/*
* pmon.S -- low-level entry points into PMON monitor.
*
* Copyright (c) 1996, 1997 Cygnus Support
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
#ifdef __mips16
/* This file contains 32 bit assembly code. */
.set nomips16
#endif
#if __mips < 3
/* This machine does not support 64-bit operations. */
#define ADDU addu
#define SUBU subu
#else
/* This machine supports 64-bit operations. */
#define ADDU daddu
#define SUBU dsubu
#endif
#include "regs.S"
.text
.align 2
#ifdef LSI
#define PMON_VECTOR 0xbfc00200
#else
#define PMON_VECTOR 0xbfc00500
#endif
#ifndef __mips_eabi
/* Provide named functions for entry into the monitor: */
#define INDIRECT(name,index) \
.globl name; \
.ent name; \
.set noreorder; \
name: la $2,+(PMON_VECTOR+((index)*4)); \
lw $2,0($2); \
j $2; \
nop; \
.set reorder; \
.end name
#else
#define INDIRECT(name,index) \
.globl name; \
.ent name; \
.set noreorder; \
name: la $2,+(PMON_VECTOR+((index)*4)); \
lw $2,0($2); \
SUBU sp,sp,0x40; \
sd ra,0x38(sp); \
sd fp,0x30(sp); \
jal $2; \
move fp,sp; \
ld ra,0x38(sp); \
ld fp,0x30(sp); \
j ra; \
ADDU sp,sp,0x40; \
.set reorder; \
.end name
#endif
/* The following magic numbers are for the slots into the PMON monitor */
/* The first are used as the lo-level library run-time: */
INDIRECT(mon_read,0)
INDIRECT(mon_write,1)
INDIRECT(mon_open,2)
INDIRECT(mon_close,3)
/* The following are useful monitor routines: */
INDIRECT(mon_ioctl,4)
INDIRECT(mon_printf,5)
INDIRECT(mon_vsprintf,6)
INDIRECT(mon_ttctl,7)
INDIRECT(mon_cliexit,8)
INDIRECT(mon_getenv,9)
INDIRECT(mon_onintr,10)
INDIRECT(mon_flush_cache,11)
INDIRECT(mon_exception,12)
INDIRECT(mon_fpgaconfig,21)
#if 0
/* The following routine is required by the "print()" function: */
.globl pmon_outbyte
.ent pmon_outbyte
.set noreorder
pmon_outbyte:
subu sp,sp,0x20 /* allocate stack space for string */
sd ra,0x18(sp) /* stack return address */
sd fp,0x10(sp) /* stack frame-pointer */
move fp,sp /* take a copy of the stack pointer */
/* We leave so much space on the stack for the string (16
characters), since the call to mon_printf seems to corrupt
the 8bytes at offset 8 into the string/stack. */
sb a0,0x00(sp) /* character to print */
sb z0,0x01(sp) /* NUL terminator */
jal mon_printf /* and output the string */
move a0,sp /* take a copy of the string pointer {DELAY SLOT} */
move sp,fp /* recover stack pointer */
ld ra,0x18(sp) /* recover return address */
ld fp,0x10(sp) /* recover frame-pointer */
j ra /* return to the caller */
addu sp,sp,0x20 /* dump the stack space {DELAY SLOT} */
.set reorder
.end pmon_outbyte
/* The following routine is required by the "sbrk()" function: */
.globl get_mem_info
.ent get_mem_info
.set noreorder
get_mem_info:
# in: a0 = pointer to 3 word structure
# out: void
subu sp,sp,0x18 /* create some stack space */
sd ra,0x00(sp) /* stack return address */
sd fp,0x08(sp) /* stack frame-pointer */
sd a0,0x10(sp) /* stack structure pointer */
move fp,sp /* take a copy of the stack pointer */
# The monitor has already sized memory, but unfortunately we
# do not have access to the data location containing the
# memory size.
jal __sizemem
nop
ld a0,0x10(sp) # recover structure pointer
sw v0,0(a0) # amount of memory available
# Deal with getting the cache size information:
mfc0 a1, C0_CONFIG
nop
nop
andi a2,a1,0x7 << 9 # bits 11..9 for instruction cache size
sll a2,a2,12 - 8
sw a2,4(a0)
andi a2,a1,0x7 << 6 # bits 8..6 for data cache size
sll a2,a2,12 - 5
sw a2,8(a0) # data cache size
#
move sp,fp /* recover stack pointer */
ld ra,0x00(sp) /* recover return address */
ld fp,0x08(sp) /* recover frame-pointer */
j ra /* return to the caller */
addu sp,sp,0x18 /* restore stack pointer {DELAY SLOT} */
.set reorder
.end get_mem_info
#ifdef LSI
# For the LSI MiniRISC board, we can safely assume that we have
# at least one megabyte of RAM.
.globl __sizemem
.ent __sizemem
__sizemem:
li v0,0x100000
j ra
.end __sizemem
#else
#endif
#endif
/* EOF pmon.S */

View File

@@ -0,0 +1,137 @@
/*
* regs.S -- standard MIPS register names.
*
* Copyright (c) 1995 Cygnus Support
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
/* Standard MIPS register names: */
#define zero $0
#define z0 $0
#define v0 $2
#define v1 $3
#define a0 $4
#define a1 $5
#define a2 $6
#define a3 $7
#define t0 $8
#define t1 $9
#define t2 $10
#define t3 $11
#define t4 $12
#define t5 $13
#define t6 $14
#define t7 $15
#define s0 $16
#define s1 $17
#define s2 $18
#define s3 $19
#define s4 $20
#define s5 $21
#define s6 $22
#define s7 $23
#define t8 $24
#define t9 $25
#define k0 $26 /* kernel private register 0 */
#define k1 $27 /* kernel private register 1 */
#define gp $28 /* global data pointer */
#define sp $29 /* stack-pointer */
#define fp $30 /* frame-pointer */
#define ra $31 /* return address */
#define pc $pc /* pc, used on mips16 */
#define fp0 $f0
#define fp1 $f1
/* Useful memory constants: */
#define K0BASE 0x80000000
#ifndef __mips64
#define K1BASE 0xA0000000
#else
#define K1BASE 0xFFFFFFFFA0000000LL
#endif
#define PHYS_TO_K1(a) ((unsigned)(a) | K1BASE)
/* Standard Co-Processor 0 register numbers: */
#define C0_COUNT $9 /* Count Register */
#define C0_SR $12 /* Status Register */
#define C0_CAUSE $13 /* last exception description */
#define C0_EPC $14 /* Exception error address */
#define C0_CONFIG $16 /* CPU configuration */
/* Standard Status Register bitmasks: */
#define SR_CU1 0x20000000 /* Mark CP1 as usable */
#define SR_FR 0x04000000 /* Enable MIPS III FP registers */
#define SR_BEV 0x00400000 /* Controls location of exception vectors */
#define SR_PE 0x00100000 /* Mark soft reset (clear parity error) */
#define SR_KX 0x00000080 /* Kernel extended addressing enabled */
#define SR_SX 0x00000040 /* Supervisor extended addressing enabled */
#define SR_UX 0x00000020 /* User extended addressing enabled */
/* Standard (R4000) cache operations. Taken from "MIPS R4000
Microprocessor User's Manual" 2nd edition: */
#define CACHE_I (0) /* primary instruction */
#define CACHE_D (1) /* primary data */
#define CACHE_SI (2) /* secondary instruction */
#define CACHE_SD (3) /* secondary data (or combined instruction/data) */
#define INDEX_INVALIDATE (0) /* also encodes WRITEBACK if CACHE_D or CACHE_SD */
#define INDEX_LOAD_TAG (1)
#define INDEX_STORE_TAG (2)
#define CREATE_DIRTY_EXCLUSIVE (3) /* CACHE_D and CACHE_SD only */
#define HIT_INVALIDATE (4)
#define CACHE_FILL (5) /* CACHE_I only */
#define HIT_WRITEBACK_INVALIDATE (5) /* CACHE_D and CACHE_SD only */
#define HIT_WRITEBACK (6) /* CACHE_I, CACHE_D and CACHE_SD only */
#define HIT_SET_VIRTUAL (7) /* CACHE_SI and CACHE_SD only */
#define BUILD_CACHE_OP(o,c) (((o) << 2) | (c))
/* Individual cache operations: */
#define INDEX_INVALIDATE_I BUILD_CACHE_OP(INDEX_INVALIDATE,CACHE_I)
#define INDEX_WRITEBACK_INVALIDATE_D BUILD_CACHE_OP(INDEX_INVALIDATE,CACHE_D)
#define INDEX_INVALIDATE_SI BUILD_CACHE_OP(INDEX_INVALIDATE,CACHE_SI)
#define INDEX_WRITEBACK_INVALIDATE_SD BUILD_CACHE_OP(INDEX_INVALIDATE,CACHE_SD)
#define INDEX_LOAD_TAG_I BUILD_CACHE_OP(INDEX_LOAD_TAG,CACHE_I)
#define INDEX_LOAD_TAG_D BUILD_CACHE_OP(INDEX_LOAD_TAG,CACHE_D)
#define INDEX_LOAD_TAG_SI BUILD_CACHE_OP(INDEX_LOAD_TAG,CACHE_SI)
#define INDEX_LOAD_TAG_SD BUILD_CACHE_OP(INDEX_LOAD_TAG,CACHE_SD)
#define INDEX_STORE_TAG_I BUILD_CACHE_OP(INDEX_STORE_TAG,CACHE_I)
#define INDEX_STORE_TAG_D BUILD_CACHE_OP(INDEX_STORE_TAG,CACHE_D)
#define INDEX_STORE_TAG_SI BUILD_CACHE_OP(INDEX_STORE_TAG,CACHE_SI)
#define INDEX_STORE_TAG_SD BUILD_CACHE_OP(INDEX_STORE_TAG,CACHE_SD)
#define CREATE_DIRTY_EXCLUSIVE_D BUILD_CACHE_OP(CREATE_DIRTY_EXCLUSIVE,CACHE_D)
#define CREATE_DIRTY_EXCLUSIVE_SD BUILD_CACHE_OP(CREATE_DIRTY_EXCLUSIVE,CACHE_SD)
#define HIT_INVALIDATE_I BUILD_CACHE_OP(HIT_INVALIDATE,CACHE_I)
#define HIT_INVALIDATE_D BUILD_CACHE_OP(HIT_INVALIDATE,CACHE_D)
#define HIT_INVALIDATE_SI BUILD_CACHE_OP(HIT_INVALIDATE,CACHE_SI)
#define HIT_INVALIDATE_SD BUILD_CACHE_OP(HIT_INVALIDATE,CACHE_SD)
#define CACHE_FILL_I BUILD_CACHE_OP(CACHE_FILL,CACHE_I)
#define HIT_WRITEBACK_INVALIDATE_D BUILD_CACHE_OP(HIT_WRITEBACK_INVALIDATE,CACHE_D)
#define HIT_WRITEBACK_INVALIDATE_SD BUILD_CACHE_OP(HIT_WRITEBACK_INVALIDATE,CACHE_SD)
#define HIT_WRITEBACK_I BUILD_CACHE_OP(HIT_WRITEBACK,CACHE_I)
#define HIT_WRITEBACK_D BUILD_CACHE_OP(HIT_WRITEBACK,CACHE_D)
#define HIT_WRITEBACK_SD BUILD_CACHE_OP(HIT_WRITEBACK,CACHE_SD)
#define HIT_SET_VIRTUAL_SI BUILD_CACHE_OP(HIT_SET_VIRTUAL,CACHE_SI)
#define HIT_SET_VIRTUAL_SD BUILD_CACHE_OP(HIT_SET_VIRTUAL,CACHE_SD)
/*> EOF regs.S <*/

View File

@@ -0,0 +1,361 @@
/*
Based upon IDT provided code with the following release:
This source code has been made available to you by IDT on an AS-IS
basis. Anyone receiving this source is licensed under IDT copyrights
to use it in any way he or she deems fit, including copying it,
modifying it, compiling it, and redistributing it either with or
without modifications. No license under IDT patents or patent
applications is to be implied by the copyright license.
Any user of this software should understand that IDT cannot provide
technical support for this software and will not be responsible for
any consequences resulting from the use of this software.
Any person who transfers this source code or any derivative work must
include the IDT copyright notice, this paragraph, and the preceeding
two paragraphs in the transferred software.
COPYRIGHT IDT CORPORATION 1996
LICENSED MATERIAL - PROGRAM PROPERTY OF IDT
$Id$
*/
/*************************************************************************
**
** Copyright 1991-95 Integrated Device Technology, Inc.
** All Rights Reserved
**
** idt_csu.S -- IDT stand alone startup code
**
**************************************************************************/
#include <rtems/mips/iregdef.h>
#include <rtems/mips/idtcpu.h>
#include <rtems/asm.h>
.extern mon_flush_cache
#if 0
.extern _fdata,4 /* this is defined by the linker */
.extern _edata,4 /* this is defined by the linker */
.extern _idata,4 /* this is defined by the linker */
#endif
.extern _fbss,4 /* this is defined by the linker */
.extern end,4 /* this is defined by the linker */
.lcomm sim_mem_cfg_struct,12
.text
#define HARD_CODED_MEM_SIZE 0x1000000 /* RBTX4925 has 16 megabytes of RAM */
#define PMON_VECTOR 0xbfc00500
#define TMP_STKSIZE 1024
/*
** P_STACKSIZE is the size of the Prom Stack.
** the prom stack grows downward
*/
#define P_STACKSIZE 0x2000 /* sets stack size to 8k */
/**************************************************************************
**
** start - Typical standalone start up code required for R3000/R4000
**
**
** 1) Initialize the STATUS Register
** a) Clear parity error bit
** b) Set co_processor 1 usable bit ON
** c) Clear all IntMask Enables
** d) Set kernel/disabled mode
** 2) Initialize Cause Register
** a) clear software interrupt bits
** 3) Determine FPU installed or not
** if not, clear CoProcessor 1 usable bit
** 4) Initialize data areas. Clear bss area.
** 5) MUST allocate temporary stack until memory size determined
** It MUST be uncached to prevent overwriting when caches are cleared
** 6) Install exception handlers
** 7) Determine memory and cache sizes
** 8) Establish permanent stack (cached or uncached as defined by bss)
** 9) Flush Instruction and Data caches
** 10) If there is a Translation Lookaside Buffer, Clear the TLB
** 11) Execute initialization code if the IDT/c library is to be used
**
** 12) Jump to user's "main()"
** 13) Jump to promexit
**
** IDT/C 5.x defines _R3000, IDT/C 6.x defines _R4000 internally.
** This is used to mark code specific to R3xxx or R4xxx processors.
** IDT/C 6.x defines __mips to be the ISA level for which we're
** generating code. This is used to make sure the stack etc. is
** double word aligned, when using -mips3 (default) or -mips2,
** when compiling with IDT/C6.x
**
***************************************************************************/
FRAME(start,sp,0,ra)
.set noreorder
#if __mips_fpr == 64
li v0,SR_CU1|SR_FR /* initally clear ERL, enable FPU with 64 bit regs */
#else
li v0,SR_CU1 /* initally clear ERL, enable FPU with 32 bit regs */
#endif
mtc0 v0,C0_SR /* clr IntMsks/ kernel/disabled mode */
nop
mtc0 zero,C0_CAUSE /* clear software interrupts */
nop
li v0,CFG_C_NONCOHERENT /* initialise default cache mode */
mtc0 v0,C0_CONFIG
/*
** check to see if a fpu is really plugged in
*/
li t3,0xaaaa5555 /* put a's and 5's in t3 */
mtc1 t3,fp0 /* try to write them into fp0 */
mtc1 zero,fp1 /* try to write zero in fp */
mfc1 t0,fp0
mfc1 t1,fp1
nop
bne t0,t3,1f /* branch if no match */
nop
bne t1,zero,1f /* double check for positive id */
nop
/* We have a FPU. clear fcsr */
ctc1 zero, fcr31
j 2f /* status register already correct */
nop
1:
li v0,0x0 /* clear ERL and disable FPA */
mtc0 v0, C0_SR /* reset status register */
2:
la gp, _gp /* Initialize gp register (pointer to "small" data)*/
#if 0
/* Initialize data sections from "rom" copy */
la t0,_idata /* address of initialization data (copy of data sections placed in ROM) */
la t1,_fdata /* start of initialized data section */
la t2,_edata /* end of initialized data section */
3:
lw t3,0(t0)
sw t3,0(t1)
addiu t1,t1,4
bne t1,t2,3b
addiu t0,t0,4
#endif
/* clear bss before using it */
la v0,_fbss /* start of bss */
la v1,end /* end of bss */
4: sw zero,0(v0)
bltu v0,v1,4b
add v0,4
/************************************************************************
**
** Temporary Stack - needed to handle stack saves until
** memory size is determined and permanent stack set
**
** MUST be uncached to avoid confusion at cache
** switching during memory sizing
**
*************************************************************************/
/* For MIPS 3, we need to be sure that the stack is aligned on a
* double word boundary.
*/
andi t0, v0, 0x7
beqz t0, 11f /* Last three bits Zero, already aligned */
nop
add v0, 4
11:
or v0, K1BASE /* switch to uncached */
add v1, v0, TMP_STKSIZE /* end of bss + length of tmp stack */
sub v1, v1, (4*4) /* overhead */
move sp, v1 /* set sp to top of stack */
4: sw zero, 0(v0)
bltu v0, v1, 4b /* clear out temp stack */
add v0, 4
/* jal init_exc_vecs */ /* install exception handlers */
/* nop */ /* MUST do before memory probes */
/* Force processor into uncached space during memory/cache probes */
la v0, 5f
li v1, K1BASE
or v0, v1
j v0
nop
5:
li a0, HARD_CODED_MEM_SIZE /* Set memory size global */
jal set_memory_size
nop
la a0, sim_mem_cfg_struct
jal get_mem_conf /* Make call to get mem size */
nop
la a0, sim_mem_cfg_struct
lw a0, 0(a0) /* Get memory size from struct */
jal config_cache /* determine size of D & I caches */
nop
move v0, a0 /* mem_size */
/* For MIPS 3, we need to be sure that the stack (and hence v0
* here) is aligned on a double word boundary.
*/
andi t0, v0, 0x7
beqz t0, 12f /* Last three bits Zero, already aligned */
nop
subu v0, 4 /* mem_size was not aligned on doubleword bdry????*/
12:
/**************************************************************************
**
** Permanent Stack - now know top of memory, put permanent stack there
**
***************************************************************************/
la t2, _fbss /* cache mode as linked */
and t2, 0xF0000000 /* isolate segment */
la t1, 6f
j t1 /* back to original cache mode */
nop
6:
or v0, t2 /* stack back to original cache mode */
addiu v0,v0,-16 /* overhead */
move sp, v0 /* now replace count w top of memory */
move v1, v0
subu v1, P_STACKSIZE /* clear requested stack size */
7: sw zero, 0(v1) /* clear P_STACKSIZE stack */
bltu v1,v0,7b
add v1, 4
/* Invalidate data cache*/
lui t0, 0x8000 /* Set starting address */
addi t1, t0, 0x2000 /* Calculate end address (assume worst case of 32 KByte / 4 Way cache) */
/* D-Cache Writeback and Invalidate */
1: bge t0, t1, 2f /* if(t0>=end_addr) then exit */
nop
cache 1, 0(t0) /* Index_Writeback_Inv_D way 0 */
cache 1, 1(t0) /* Index_Writeback_Inv_D way 1 */
cache 1, 2(t0) /* Index_Writeback_Inv_D way 2 */
cache 1, 3(t0) /* Index_Writeback_Inv_D way 3 */
b 1b
addi t0, t0, 32
2:
/* Invalidate instruction cache*/
lui t0, 0x8000 /* Set starting address */
addi t1, t0, 0x2000 /* Calculate end address (assume worst case of 32 KByte / 4 Way cache) */
/* I-Cache Disable */
mfc0 t2, C0_CONFIG /* get C0_Config */
lui t3, 0x2 /* C0_CONFIG#17 ICE# */
or t3, t2, t3 /* set ICE# bit */
mtc0 t3, C0_CONFIG /* set C_Config */
b 1f /* stop streaming */
nop
/* I-Cache Invalidate */
1: bge t0, t1, 2f /* if(t0>=end_addr) then exit */
nop
cache 0, 0(t0) /* Index_Invalidate_I way 0 */
cache 0, 1(t0) /* Index_Invalidate_I way 1 */
cache 0, 2(t0) /* Index_Invalidate_I way 2 */
cache 0, 3(t0) /* Index_Invalidate_I way 3 */
b 1b
addi t0, t0, 32
/* I-Cache Enable */
2: mtc0 t2, C0_CONFIG /* set C0_Config */
nop
/* Lock first 4k of PMON into instruction cache. This includes interrupt service code which
we don't want to run out of slow flash device. */
la t0,0x9fc00000
li t1, 0x1000
move t3, t0
addu t1, t0, t1
1: bge t0, t1, 2f
nop
lui t2, 0x1fff /* MASK */
ori t2, t2, 0xf000
and t2, t3, t2 /* virtual->physical */
srl t2, t2, 4 /* [31:12] --> [35:8] */
ori t2, t2, 0x00c4 /* Set Valid & Lock Bits */
mtc0 t2, C0_TAGLO /* Load data to TagLo reg. */
nop
cache 0x08, 3(t0) /* 2(I)=0x08: Index_Store_Tag(I$) Way3*/
nop
cache 0x14, 3(t0) /* 5(I)=0x14: Fill(Memory->Cache) Way3*/
b 1b
addi t0, t0, 32
2: nop
.set reorder
/*
** Clear Translation Lookaside Buffer (TLB)
*/
jal init_tlb /* clear the tlb */
/*
** End of CPU initialization, ready to start kernel
*/
move a0,zero /* Set argc passed to main */
move a1,zero /* Set argv passed to main */
jal boot_card
nop
/* Kernel has been shutdown, jump to the "exit" routine */
jal _sys_exit
move a0,v0 # pass through the exit code
1:
beq zero,zero,1b
nop
ENDFRAME(start)
/*
* _sys_exit -- Exit from the application. Normally we cause a user trap
* to return to the ROM monitor for another run. NOTE: This is
* the only other routine we provide in the crt0.o object, since
* it may be tied to the "_start" routine. It also allows
* executables that contain a complete world to be linked with
* just the crt0.o object.
*/
FRAME(_sys_exit,sp,0,ra)
break 1023
nop
13:
b 13b # but loop back just in-case
nop
ENDFRAME(_sys_exit)
.globl __sizemem
.ent __sizemem
__sizemem:
li v0,HARD_CODED_MEM_SIZE
j ra
nop
.end __sizemem

View File

@@ -0,0 +1,16 @@
/*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* bspclean.c,v 1.2.2.1 2003/09/04 18:44:49 joel Exp
*/
void bsp_cleanup( void )
{
extern void _sys_exit(int);
_sys_exit(0);
}

View File

@@ -0,0 +1,104 @@
/*
* 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.
*
* COPYRIGHT (c) 1989-2000.
* 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.
*
* bspstart.c,v 1.4.2.1 2003/09/04 18:44:49 joel Exp
*/
#include <string.h>
#include <bsp.h>
#include <rtems/libio.h>
#include <rtems/libcsupport.h>
#define LIBC_HEAP_SIZE (64 * 1024)
extern int end; /* defined by linker */
/*
* The original table from the application and our copy of it with
* some changes.
*/
extern rtems_configuration_table Configuration;
rtems_configuration_table BSP_Configuration;
rtems_cpu_table Cpu_table;
char *rtems_progname;
/*
* Use the shared implementations of the following routines
*/
void bsp_postdriver_hook(void);
void bsp_libc_init( void *, uint32_t, int );
void init_exc_vecs(void);
/*
* 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)
{
uint32_t heap_start;
heap_start = (uint32_t) &end;
if (heap_start & (CPU_ALIGNMENT-1))
heap_start = (heap_start + CPU_ALIGNMENT) & ~(CPU_ALIGNMENT-1);
bsp_libc_init((void *) heap_start, LIBC_HEAP_SIZE, 0);
#ifdef RTEMS_DEBUG
rtems_debug_enable( RTEMS_DEBUG_ALL_MASK );
#endif
}
/*
* bsp_start
*
* This routine does the bulk of the system initialization.
*/
void bsp_start( void )
{
extern int WorkspaceBase;
extern void mips_install_isr_entries(void);
/* Configure Number of Register Caches */
Cpu_table.pretasking_hook = bsp_pretasking_hook; /* init libc, etc. */
Cpu_table.postdriver_hook = bsp_postdriver_hook;
Cpu_table.interrupt_stack_size = 4096;
BSP_Configuration.work_space_start =
(void *)((uint64_t)((&end) + LIBC_HEAP_SIZE + 0x100) & ~0x7);
mips_install_isr_entries(); /* Install generic MIPS exception handler */
/* init_exc_vecs(); */ /* Install BSP specific exception handler */
}

View File

@@ -0,0 +1,631 @@
/* exception.S
*
* This file contains a customized MIPS exception handler.
* It hooks into the exception handler present in the resident
* PMON debug monitor.
*
* Author: Bruce Robinson
*
* This code was derived from cpu_asm.S with the following copyright:
*
* COPYRIGHT (c) 1996 by Transition Networks Inc.
*
* 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 Transition Networks not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* Transition Networks makes no representations about the suitability
* of this software for any purpose.
*
* Derived from c/src/exec/score/cpu/no_cpu/cpu_asm.s:
*
* 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$
*/
/* @(#)exception.S 7/27/04 1.00 */
#include <rtems/mips/iregdef.h>
#include <rtems/mips/idtcpu.h>
#define FRAME(name,frm_reg,offset,ret_reg) \
.globl name; \
.ent name; \
name:; \
.frame frm_reg,offset,ret_reg
#define ENDFRAME(name) \
.end name
#if __mips == 3
/* 64 bit register operations */
#define NOP nop
#define ADD dadd
#define STREG sd
#define LDREG ld
#define ADDU addu
#define ADDIU addiu
#define STREGC1 sdc1
#define LDREGC1 ldc1
#define R_SZ 8
#define F_SZ 8
#define SZ_INT 8
#define SZ_INT_POW2 3
/* XXX if we don't always want 64 bit register ops, then another ifdef */
#elif __mips == 1
/* 32 bit register operations*/
#define NOP nop
#define ADD add
#define STREG sw
#define LDREG lw
#define ADDU add
#define ADDIU addi
#define STREGC1 swc1
#define LDREGC1 lwc1
#define R_SZ 4
#define F_SZ 4
#define SZ_INT 4
#define SZ_INT_POW2 2
#else
#error "mips assembly: what size registers do I deal with?"
#endif
#define ISR_VEC_SIZE 4
#define EXCP_STACK_SIZE (NREGS*R_SZ)
#ifdef __GNUC__
#define EXTERN(x,size) .extern x,size
#else
#define EXTERN(x,size)
#endif
EXTERN(_ISR_Nest_level, 4)
EXTERN(_Thread_Dispatch_disable_level,4)
EXTERN(_Context_Switch_necessary,4)
EXTERN(_ISR_Signals_to_thread_executing,4)
.extern _Thread_Dispatch
.extern _ISR_Vector_table
/* void __ISR_Handler()
*
* This routine provides the RTEMS interrupt management.
*
*/
#if 0
void _ISR_Handler()
{
/*
* This discussion ignores a lot of the ugly details in a real
* implementation such as saving enough registers/state to be
* able to do something real. Keep in mind that the goal is
* to invoke a user's ISR handler which is written in C and
* uses a certain set of registers.
*
* Also note that the exact order is to a large extent flexible.
* Hardware will dictate a sequence for a certain subset of
* _ISR_Handler while requirements for setting
*/
/*
* At entry to "common" _ISR_Handler, the vector number must be
* available. On some CPUs the hardware puts either the vector
* number or the offset into the vector table for this ISR in a
* known place. If the hardware does not give us this information,
* then the assembly portion of RTEMS for this port will contain
* a set of distinct interrupt entry points which somehow place
* the vector number in a known place (which is safe if another
* interrupt nests this one) and branches to _ISR_Handler.
*
*/
#endif
FRAME(rbtx4925_ISR_Handler,sp,0,ra)
.set noreorder
#if 0
/* Activate TX4925 PIO19 signal for diagnostics */
lui k0,0xff1f
ori k0,k0,0xf500
lw k0,(k0)
lui k1,0x8
or k1,k1,k0
lui k0,0xff1f
ori k0,k0,0xf500
sw k1,(k0)
#endif
mfc0 k0,C0_CAUSE /* Determine if an interrupt generated this exception */
nop
and k1,k0,CAUSE_EXCMASK
beq k1,zero,_chk_int /* If so, branch to service here */
nop
la k0,_int_esr_link /* Otherwise, jump to next exception handler in PMON exception chain */
lw k0,(k0)
lw k0,4(k0)
j k0
nop
_chk_int:
mfc0 k1,C0_SR
nop
and k0,k1
and k0,(SR_IBIT1 | SR_IBIT2 | SR_IBIT3)
beq k0,zero,_ISR_Handler_quick_exit /* external interrupt not enabled, ignore */
nop
/* For debugging interrupts, clear EXL to allow breakpoints */
#if 0
MFC0 k0, C0_SR
li k1,SR_EXL /* Clear EXL and Set IE to enable interrupts */
not k1
and k0,k1
li k1,SR_IE
or k0, k1
mtc0 k0, C0_SR
NOP
#endif
/*
* save some or all context on stack
* may need to save some special interrupt information for exit
*/
/* Q: _ISR_Handler, not using IDT/SIM ...save extra regs? */
/* wastes a lot of stack space for context?? */
ADDIU sp,sp,-EXCP_STACK_SIZE
STREG ra, R_RA*R_SZ(sp) /* store ra on the stack */
STREG v0, R_V0*R_SZ(sp)
STREG v1, R_V1*R_SZ(sp)
STREG a0, R_A0*R_SZ(sp)
STREG a1, R_A1*R_SZ(sp)
STREG a2, R_A2*R_SZ(sp)
STREG a3, R_A3*R_SZ(sp)
STREG t0, R_T0*R_SZ(sp)
STREG t1, R_T1*R_SZ(sp)
STREG t2, R_T2*R_SZ(sp)
STREG t3, R_T3*R_SZ(sp)
STREG t4, R_T4*R_SZ(sp)
STREG t5, R_T5*R_SZ(sp)
STREG t6, R_T6*R_SZ(sp)
STREG t7, R_T7*R_SZ(sp)
mflo t0
STREG t8, R_T8*R_SZ(sp)
STREG t0, R_MDLO*R_SZ(sp)
STREG t9, R_T9*R_SZ(sp)
mfhi t0
STREG gp, R_GP*R_SZ(sp)
STREG t0, R_MDHI*R_SZ(sp)
STREG fp, R_FP*R_SZ(sp)
.set noat
STREG AT, R_AT*R_SZ(sp)
.set at
mfc0 t0,C0_SR
dmfc0 t1,C0_EPC
STREG t0,R_SR*R_SZ(sp)
STREG t1,R_EPC*R_SZ(sp)
/*
*
* #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
* if ( _ISR_Nest_level == 0 )
* switch to software interrupt stack
* #endif
*/
/*
* _ISR_Nest_level++;
*/
lw t0,_ISR_Nest_level
NOP
add t0,t0,1
sw t0,_ISR_Nest_level
/*
* _Thread_Dispatch_disable_level++;
*/
lw t1,_Thread_Dispatch_disable_level
NOP
add t1,t1,1
sw t1,_Thread_Dispatch_disable_level
/* DEBUG - Add the following code to disable interrupts and clear EXL in status register, this will
allow memory exceptions to occur while servicing the current interrupt */
#if 0
li t0,~CAUSE_IP2_MASK /* Disable interrupts from internal interrupt controller */
mfc0 t1,C0_SR
nop
and t1,t0
mtc0 t1,C0_SR
nop
li t0,~SR_EXL /* Clear EXL in status register to allow memory exceptions to occur */
mfc0 t1,C0_SR
nop
and t1,t0
mtc0 t1,C0_SR
nop
#endif
/*
* Call the CPU model or BSP specific routine to decode the
* interrupt source and actually vector to device ISR handlers.
*/
move a0,sp
jal mips_vector_isr_handlers
NOP
/* Add the following code to disable interrupts (see DEBUG above) */
#if 0
li t0,SR_EXL /* Set EXL to hold off interrupts */
mfc0 t1,C0_SR
nop
or t1,t0
mtc0 t1,C0_SR
nop
li t0,CAUSE_IP2_MASK /* Enable interrupts from internal interrupt controller */
mfc0 t1,C0_SR
nop
or t1,t0
mtc0 t1,C0_SR
nop
#endif
_ISR_Handler_cleanup:
/*
* --_ISR_Nest_level;
*/
lw t2,_ISR_Nest_level
NOP
add t2,t2,-1
sw t2,_ISR_Nest_level
/*
* --_Thread_Dispatch_disable_level;
*/
lw t1,_Thread_Dispatch_disable_level
NOP
add t1,t1,-1
sw t1,_Thread_Dispatch_disable_level
/*
* if ( _Thread_Dispatch_disable_level || _ISR_Nest_level )
* goto the label "exit interrupt (simple case)"
*/
or t0,t2,t1
bne t0,zero,_ISR_Handler_exit
NOP
/*
* #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
* restore stack
* #endif
*
* if ( !_Context_Switch_necessary && !_ISR_Signals_to_thread_executing )
* goto the label "exit interrupt (simple case)"
*/
lw t0,_Context_Switch_necessary
lw t1,_ISR_Signals_to_thread_executing
NOP
or t0,t0,t1
beq t0,zero,_ISR_Handler_exit
NOP
/*
** Turn on interrupts before entering Thread_Dispatch which
** will run for a while, thus allowing new interrupts to
** be serviced. Observe the Thread_Dispatch_disable_level interlock
** that prevents recursive entry into Thread_Dispatch.
*/
mfc0 t0, C0_SR
#if __mips == 3
li t1,SR_EXL /* Clear EXL and Set IE to enable interrupts */
not t1
and t0,t1
li t1,SR_IE
#elif __mips == 1
li t1,SR_IEC
#endif
or t0, t1
mtc0 t0, C0_SR
NOP
/* save off our stack frame so the context switcher can get to it */
la t0,__exceptionStackFrame
STREG sp,(t0)
jal _Thread_Dispatch
NOP
/* and make sure its clear in case we didn't dispatch. if we did, its
** already cleared */
la t0,__exceptionStackFrame
STREG zero,(t0)
NOP
/*
** turn interrupts back off while we restore context so
** a badly timed interrupt won't accidentally mess things up
*/
mfc0 t0, C0_SR
li t1,SR_IE /* Clear IE first (recommended) */
not t1
and t0,t1
mtc0 t0, C0_SR
li t1,SR_EXL | SR_IE /* Set EXL and IE, this puts status register bits back to interrupted state */
or t0,t1
mtc0 t0, C0_SR
NOP
/*
* prepare to get out of interrupt
* return from interrupt (maybe to _ISR_Dispatch)
*
* LABEL "exit interrupt (simple case):"
* prepare to get out of interrupt
* return from interrupt
*/
_ISR_Handler_exit:
/* restore interrupt context from stack */
LDREG t8, R_MDLO*R_SZ(sp)
LDREG t0, R_T0*R_SZ(sp)
mtlo t8
LDREG t8, R_MDHI*R_SZ(sp)
LDREG t1, R_T1*R_SZ(sp)
mthi t8
LDREG t2, R_T2*R_SZ(sp)
LDREG t3, R_T3*R_SZ(sp)
LDREG t4, R_T4*R_SZ(sp)
LDREG t5, R_T5*R_SZ(sp)
LDREG t6, R_T6*R_SZ(sp)
LDREG t7, R_T7*R_SZ(sp)
LDREG t8, R_T8*R_SZ(sp)
LDREG t9, R_T9*R_SZ(sp)
LDREG gp, R_GP*R_SZ(sp)
LDREG fp, R_FP*R_SZ(sp)
LDREG ra, R_RA*R_SZ(sp)
LDREG a0, R_A0*R_SZ(sp)
LDREG a1, R_A1*R_SZ(sp)
LDREG a2, R_A2*R_SZ(sp)
LDREG a3, R_A3*R_SZ(sp)
LDREG v1, R_V1*R_SZ(sp)
LDREG v0, R_V0*R_SZ(sp)
LDREG k1, R_EPC*R_SZ(sp)
mtc0 k1,C0_EPC
.set noat
LDREG AT, R_AT*R_SZ(sp)
.set at
ADDIU sp,sp,EXCP_STACK_SIZE
_ISR_Handler_quick_exit:
eret
nop
#if 0
.global int7_isr
.extern Interrupt_7_isr
int7_isr:
/* Verify interrupt is from Timer */
la k0,IRCS /* read Interrupt Current Status register */
lw k0,(k0)
nop /* reading from external device */
li k1,IRCS_CAUSE_MASK
and k0,k0,k1 /* isolate interrupt cause */
li k1,INT7INT /* test for interrupt 7 */
subu k1,k0,k1
beq k1,zero,int7_isr1
nop
j ra /* interrupt 7 no longer valid, return without doing anything */
nop
int7_isr1:
j Interrupt_7_isr /* Jump to Interrupt 7 isr */
nop
#endif
.set reorder
ENDFRAME(rbtx4925_ISR_Handler)
FRAME(_BRK_Handler,sp,0,ra)
.set noreorder
#ifdef USC
la k0,INT_CFG3 /* Disable heartbeat interrupt in USC320, it interferes with PMON exception handler */
lw k1,(k0)
li k0,~HBI_MASK
and k1,k1,k0
la k0,INT_CFG3
sw k1,(k0)
#endif
la k0,_brk_esr_link /* Jump to next exception handler in PMON exception chain */
lw k0,(k0)
lw k0,4(k0)
j k0
nop
.set reorder
ENDFRAME(_BRK_Handler)
/**************************************************************************
**
** init_exc_vecs() - moves the exception code into the addresses
** reserved for exception vectors
**
** UTLB Miss exception vector at address 0x80000000
**
** General exception vector at address 0x80000080
**
** RESET exception vector is at address 0xbfc00000
**
***************************************************************************/
FRAME(init_exc_vecs,sp,0,ra)
.set noreorder
.extern mon_onintr
/* Install interrupt handler in PMON exception handling chain */
addiu sp,sp,-8
sw ra,(sp) /* Save ra contents on stack */
move a0,zero
la a1,_int_esr_link
jal mon_onintr /* Make PMON system call to install interrupt exception handler */
nop
li a0,9
la a1,_brk_esr_link
jal mon_onintr /* Make PMON system call to install break exception handler */
nop
lw ra,(sp)
addiu sp,sp,8 /* Restore ra contents from stack */
j ra
nop
.set reorder
ENDFRAME(init_exc_vecs)
#if 0 /* Unused code below */
/*************************************************************
* enable_int7(ints)
* Enable interrupt 7
*/
FRAME(enable_int7,sp,0,ra)
.set noreorder
la t0,IRDM1 # Set interrupt controller detection mode (bits 2-3 = 0 for int 7 active low)
li t1,0x0
sw t1,(t0)
la t0,IRLVL4 # Set interrupt controller level (bit 8-10 = 2 for int 7 at level 2)
li t1,0x200
sw t1,(t0)
la t0,IRMSK # Set interrupt controller mask
li t1,0x0
sw t1,(t0)
la t0,IRDEN # Enable interrupts from controller
li t1,0x1
sw t1,(t0)
j ra
nop
.set reorder
ENDFRAME(enable_int7)
/*************************************************************
* disable_int7(ints)
* Disable interrupt 7
*/
FRAME(disable_int7,sp,0,ra)
.set noreorder
la t0,IRLVL4 # Set interrupt controller level (bit 8-10 = 0 to diasble int 7)
li t1,0x200
sw t1,(t0)
j ra
nop
.set reorder
ENDFRAME(disable_int7)
#endif
/*************************************************************
* tx4925exception:
* Diagnostic code that can be hooked to PMON interrupt handler.
* Generates pulse on PIO22 pin.
* Called from _exception code in PMON (see mips.s of PMON).
* Return address is located in k1.
*/
FRAME(tx4925exception,sp,0,ra)
.set noreorder
la k0,k1tmp
sw k1,(k0)
/* Activate TX4925 PIO22 signal for diagnostics */
lui k0,0xff1f
ori k0,k0,0xf500
lw k0,(k0)
lui k1,0x40
or k1,k1,k0
lui k0,0xff1f
ori k0,k0,0xf500
sw k1,(k0)
nop
/* De-activate TX4925 PIO22 signal for diagnostics */
lui k0,0xff1f
ori k0,k0,0xf500
lw k0,(k0)
lui k1,0x40
not k1
and k1,k1,k0
lui k0,0xff1f
ori k0,k0,0xf500
sw k1,(k0)
nop
la k0,k1tmp
lw k1,(k0)
j k1
.set reorder
ENDFRAME(tx4925exception)
.data
k1tmp: .word 0 /* Temporary strage for K1 during interrupt service */
/*************************************************************
*
* Exception handler links, used in PMON exception handler chains
*/
/* Interrupt exception service routine link */
.global _int_esr_link
_int_esr_link:
.word 0
.word rbtx4925_ISR_Handler
/* Break exception service routine link */
.global _brk_esr_link
_brk_esr_link:
.word 0
.word _BRK_Handler

View File

@@ -0,0 +1,922 @@
/*
Based upon IDT provided code with the following release:
This source code has been made available to you by IDT on an AS-IS
basis. Anyone receiving this source is licensed under IDT copyrights
to use it in any way he or she deems fit, including copying it,
modifying it, compiling it, and redistributing it either with or
without modifications. No license under IDT patents or patent
applications is to be implied by the copyright license.
Any user of this software should understand that IDT cannot provide
technical support for this software and will not be responsible for
any consequences resulting from the use of this software.
Any person who transfers this source code or any derivative work must
include the IDT copyright notice, this paragraph, and the preceeding
two paragraphs in the transferred software.
COPYRIGHT IDT CORPORATION 1996
LICENSED MATERIAL - PROGRAM PROPERTY OF IDT
$Id$
*/
/************************************************************************
**
** idtmem.s - memory and cache functions
**
** Copyright 1991 Integrated Device Technology, Inc.
** All Rights Reserved
**
**************************************************************************/
/*
* 950313: Ketan fixed bugs in mfc0/mtc0 hazards, and removed hack
* to set mem_size.
*/
#include <rtems/mips/iregdef.h>
#include <rtems/mips/idtcpu.h>
#include <rtems/asm.h>
.data
mem_size:
.word 0
dcache_size:
.word 0
icache_size:
#if __mips == 1
.word MINCACHE
#endif
#if __mips == 3
.word 0
#endif
#if __mips == 3
.data
scache_size:
.word 0
icache_linesize:
.word 0
dcache_linesize:
.word 0
scache_linesize:
.word 0
#endif
.text
#if __mips == 1
#define CONFIGFRM ((2*4)+4)
/*************************************************************************
**
** Config_Dcache() -- determine size of Data cache
**
**************************************************************************/
FRAME(config_Dcache,sp, CONFIGFRM, ra)
.set noreorder
subu sp,CONFIGFRM
sw ra,CONFIGFRM-4(sp) /* save return address */
sw s0,4*4(sp) /* save s0 in first regsave slot */
mfc0 s0,C0_SR /* save SR */
nop
mtc0 zero,C0_SR /* disable interrupts */
.set reorder
jal _size_cache /* returns Data cache size in v0 */
sw v0, dcache_size /* save it */
and s0, ~SR_PE /* do not clear PE */
.set noreorder
mtc0 s0,C0_SR /* restore SR */
nop
.set reorder
lw s0, 4*4(sp) /* restore s0 */
lw ra,CONFIGFRM-4(sp) /* restore ra */
addu sp,CONFIGFRM /* pop stack */
j ra
ENDFRAME(config_Dcache)
/*************************************************************************
**
** Config_Icache() -- determine size of Instruction cache
** MUST be run in uncached mode/handled in idt_csu.s
**
**************************************************************************/
FRAME(config_Icache,sp, CONFIGFRM, ra)
.set noreorder
subu sp,CONFIGFRM
sw ra,CONFIGFRM-4(sp) /* save return address */
sw s0,4*4(sp) /* save s0 in first regsave slot */
mfc0 s0,C0_SR /* save SR */
nop
mtc0 zero, C0_SR /* disable interrupts */
li v0,SR_SWC /* swap caches/disable ints */
mtc0 v0,C0_SR
nop
.set reorder
jal _size_cache /* returns instruction cache size */
.set noreorder
mtc0 zero,C0_SR /* swap back caches */
nop
and s0,~SR_PE /* do not inadvertantly clear PE */
mtc0 s0,C0_SR /* restore SR */
nop
.set reorder
sw v0, icache_size /* save it AFTER caches back */
lw s0,4*4(sp) /* restore s0 */
lw ra,CONFIGFRM-4(sp) /* restore ra */
addu sp,CONFIGFRM /* pop stack */
j ra
ENDFRAME(config_Icache)
/************************************************************************
**
** _size_cache()
** returns cache size in v0
**
************************************************************************/
FRAME(_size_cache,sp,0,ra)
.set noreorder
mfc0 t0,C0_SR /* save current sr */
nop
and t0,~SR_PE /* do not inadvertently clear PE */
or v0,t0,SR_ISC /* isolate cache */
mtc0 v0,C0_SR
/*
* First check if there is a cache there at all
*/
move v0,zero
li v1,0xa5a5a5a5 /* distinctive pattern */
sw v1,K0BASE /* try to write into cache */
lw t1,K0BASE /* try to read from cache */
nop
mfc0 t2,C0_SR
nop
.set reorder
and t2,SR_CM
bne t2,zero,3f /* cache miss, must be no cache */
bne v1,t1,3f /* data not equal -> no cache */
/*
* Clear cache size boundries to known state.
*/
li v0,MINCACHE
1:
sw zero,K0BASE(v0)
sll v0,1
ble v0,MAXCACHE,1b
li v0,-1
sw v0,K0BASE(zero) /* store marker in cache */
li v0,MINCACHE /* MIN cache size */
2: lw v1,K0BASE(v0) /* Look for marker */
bne v1,zero,3f /* found marker */
sll v0,1 /* cache size * 2 */
ble v0,MAXCACHE,2b /* keep looking */
move v0,zero /* must be no cache */
.set noreorder
3: mtc0 t0,C0_SR /* restore sr */
j ra
nop
ENDFRAME(_size_cache)
.set reorder
#define FLUSHFRM (2*4)
/***************************************************************************
**
** flush_Dcache() - flush entire Data cache
**
****************************************************************************/
FRAME(flush_Dcache,sp,FLUSHFRM,ra)
lw t2, dcache_size
.set noreorder
mfc0 t3,C0_SR /* save SR */
nop
and t3,~SR_PE /* dont inadvertently clear PE */
beq t2,zero,_Dflush_done /* no D cache, get out! */
nop
li v0, SR_ISC /* isolate cache */
mtc0 v0, C0_SR
nop
.set reorder
li t0,K0BASE /* set loop registers */
or t1,t0,t2
2: sb zero,0(t0)
sb zero,4(t0)
sb zero,8(t0)
sb zero,12(t0)
sb zero,16(t0)
sb zero,20(t0)
sb zero,24(t0)
addu t0,32
sb zero,-4(t0)
bne t0,t1,2b
.set noreorder
_Dflush_done:
mtc0 t3,C0_SR /* restore Status Register */
.set reorder
j ra
ENDFRAME(flush_Dcache)
/***************************************************************************
**
** flush_Icache() - flush entire Instruction cache
**
** NOTE: Icache can only be flushed/cleared when uncached
** Code forces into uncached memory regardless of calling mode
**
****************************************************************************/
FRAME(flush_Icache,sp,FLUSHFRM,ra)
lw t1,icache_size
.set noreorder
mfc0 t3,C0_SR /* save SR */
nop
la v0,1f
li v1,K1BASE
or v0,v1
j v0 /* force into non-cached space */
nop
1:
and t3,~SR_PE /* dont inadvertently clear PE */
beq t1,zero,_Iflush_done /* no i-cache get out */
nop
li v0,SR_ISC|SR_SWC /* disable intr, isolate and swap */
mtc0 v0,C0_SR
li t0,K0BASE
.set reorder
or t1,t0,t1
1: sb zero,0(t0)
sb zero,4(t0)
sb zero,8(t0)
sb zero,12(t0)
sb zero,16(t0)
sb zero,20(t0)
sb zero,24(t0)
addu t0,32
sb zero,-4(t0)
bne t0,t1,1b
.set noreorder
_Iflush_done:
mtc0 t3,C0_SR /* un-isolate, enable interrupts */
.set reorder
j ra
ENDFRAME(flush_Icache)
/**************************************************************************
**
** clear_Dcache(base_addr, byte_count) - flush portion of Data cache
**
** a0 = base address of portion to be cleared
** a1 = byte count of length
**
***************************************************************************/
FRAME(clear_Dcache,sp,0,ra)
lw t2, dcache_size /* Data cache size */
.set noreorder
mfc0 t3,C0_SR /* save SR */
nop
and t3,~SR_PE /* dont inadvertently clear PE */
nop
nop
.set reorder
/*
* flush data cache
*/
.set noreorder
nop
li v0,SR_ISC /* isolate data cache */
mtc0 v0,C0_SR
.set reorder
bltu t2,a1,1f /* cache is smaller than region */
move t2,a1
1: addu t2,a0 /* ending address + 1 */
move t0,a0
1: sb zero,0(t0)
sb zero,4(t0)
sb zero,8(t0)
sb zero,12(t0)
sb zero,16(t0)
sb zero,20(t0)
sb zero,24(t0)
addu t0,32
sb zero,-4(t0)
bltu t0,t2,1b
.set noreorder
mtc0 t3,C0_SR /* un-isolate, enable interrupts */
nop
.set reorder
j ra
ENDFRAME(clear_Dcache)
/**************************************************************************
**
** clear_Icache(base_addr, byte_count) - flush portion of Instruction cache
**
** a0 = base address of portion to be cleared
** a1 = byte count of length
**
** NOTE: Icache can only be flushed/cleared when uncached
** Code forces into uncached memory regardless of calling mode
**
***************************************************************************/
FRAME(clear_Icache,sp,0,ra)
lw t1, icache_size /* Instruction cache size */
/*
* flush text cache
*/
.set noreorder
mfc0 t3,C0_SR /* save SR */
nop
la v0,1f
li v1,K1BASE
or v0,v1
j v0 /* force into non-cached space */
nop
1:
and t3,~SR_PE /* dont inadvertently clear PE */
nop
nop
li v0,SR_ISC|SR_SWC /* disable intr, isolate and swap */
mtc0 v0,C0_SR
.set reorder
bltu t1,a1,1f /* cache is smaller than region */
move t1,a1
1: addu t1,a0 /* ending address + 1 */
move t0,a0
sb zero,0(t0)
sb zero,4(t0)
sb zero,8(t0)
sb zero,12(t0)
sb zero,16(t0)
sb zero,20(t0)
sb zero,24(t0)
addu t0,32
sb zero,-4(t0)
bltu t0,t1,1b
.set noreorder
mtc0 t3,C0_SR /* un-isolate, enable interrupts */
nop
nop
nop /* allow time for caches to swap */
.set reorder
j ra
ENDFRAME(clear_Icache)
/**************************************************************************
**
** get_mem_conf - get memory configuration
**
***************************************************************************/
FRAME(get_mem_conf,sp,0,ra)
lw t6, mem_size
sw t6, 0(a0)
lw t7, icache_size
sw t7, 4(a0)
lw t8, dcache_size
sw t8, 8(a0)
j ra
ENDFRAME(get_mem_conf)
#endif /* __mips == 1 */
#if __mips == 3
#define LEAF(label) FRAME(label,sp,0,ra)
#define XLEAF(label) \
.globl label ; \
label:
/*
* cacheop macro to automate cache operations
* first some helpers...
*/
#define _mincache(size, maxsize) \
bltu size,maxsize,8f ; \
move size,maxsize ; \
8:
#define _align(tmp, minaddr, maxaddr, linesize) \
subu tmp,linesize,1 ; \
not tmp ; \
and minaddr,tmp ; \
addu maxaddr,-1 ; \
and maxaddr,tmp
/* This is a bit of a hack really because it relies on minaddr=a0 */
#define _doop1(op1) \
cache op1,0(a0)
#define _doop2(op1, op2) \
cache op1,0(a0) ; \
cache op2,0(a0)
/* specials for cache initialisation */
#define _doop1lw1(op1) \
cache op1,0(a0) ; \
lw zero,0(a0) ; \
cache op1,0(a0)
#define _doop121(op1,op2) \
cache op1,0(a0) ; \
nop; \
cache op2,0(a0) ; \
nop; \
cache op1,0(a0)
#define _oploopn(minaddr, maxaddr, linesize, tag, ops) \
.set noreorder ; \
7: _doop##tag##ops ; \
bne minaddr,maxaddr,7b ; \
addu minaddr,linesize ; \
.set reorder
/* finally the cache operation macros */
#define icacheopn(kva, n, cache_size, cache_linesize, tag, ops) \
_mincache(n, cache_size); \
blez n,9f ; \
addu n,kva ; \
_align(t1, kva, n, cache_linesize) ; \
_oploopn(kva, n, cache_linesize, tag, ops) ; \
9:
#define vcacheopn(kva, n, cache_size, cache_linesize, tag, ops) \
blez n,9f ; \
addu n,kva ; \
_align(t1, kva, n, cache_linesize) ; \
_oploopn(kva, n, cache_linesize, tag, ops) ; \
9:
#define icacheop(kva, n, cache_size, cache_linesize, op) \
icacheopn(kva, n, cache_size, cache_linesize, 1, (op))
#define vcacheop(kva, n, cache_size, cache_linesize, op) \
vcacheopn(kva, n, cache_size, cache_linesize, 1, (op))
.text
/*
* static void _size_cache() R4000
*
* Internal routine to determine cache sizes by looking at R4000 config
* register. Sizes are returned in registers, as follows:
* t2 icache size
* t3 dcache size
* t6 scache size
* t4 icache line size
* t5 dcache line size
* t7 scache line size
*/
LEAF(_size_cache)
mfc0 t0,C0_CONFIG
and t1,t0,CFG_ICMASK
srl t1,CFG_ICSHIFT
li t2,0x1000
sll t2,t1
and t1,t0,CFG_DCMASK
srl t1,CFG_DCSHIFT
li t3,0x1000
sll t3,t1
li t4,32
and t1,t0,CFG_IB
bnez t1,1f
li t4,16
1:
li t5,32
and t1,t0,CFG_DB
bnez t1,1f
li t5,16
1:
move t6,zero # default to no scache
move t7,zero #
and t1,t0,CFG_C_UNCACHED # test config register
bnez t1,1f # no scache if uncached/non-coherent
li t6,0x100000 # assume 1Mb scache <<-NOTE
and t1,t0,CFG_SBMASK
srl t1,CFG_SBSHIFT
li t7,16
sll t7,t1
1: j ra
ENDFRAME(_size_cache)
/*
* void config_cache() R4000
*
* Work out size of I, D & S caches, assuming they are already initialised.
*/
LEAF(config_cache)
lw t0,icache_size
bgtz t0,8f # already known?
move v0,ra
bal _size_cache
move ra,v0
sw t2,icache_size
sw t3,dcache_size
sw t6,scache_size
sw t4,icache_linesize
sw t5,dcache_linesize
sw t7,scache_linesize
8: j ra
ENDFRAME(config_cache)
/*
* void _init_cache() R4000
*/
LEAF(_init_cache)
/*
* First work out the sizes
*/
move v0,ra
bal _size_cache
move ra,v0
/*
* The caches may be in an indeterminate state,
* so we force good parity into them by doing an
* invalidate, load/fill, invalidate for each line.
*/
/* disable all i/u and cache exceptions */
mfc0 v0,C0_SR
and v1,v0,~SR_IE
or v1,SR_DE
mtc0 v1,C0_SR
mtc0 zero,C0_TAGLO
mtc0 zero,C0_TAGHI
/* assume bottom of RAM will generate good parity for the cache */
li a0,PHYS_TO_K0(0)
move a2,t2 # icache_size
move a3,t4 # icache_linesize
move a1,a2
icacheopn(a0,a1,a2,a3,121,(Index_Store_Tag_I,Fill_I))
li a0,PHYS_TO_K0(0)
move a2,t3 # dcache_size
move a3,t5 # dcache_linesize
move a1,a2
icacheopn(a0,a1,a2,a3,1lw1,(Index_Store_Tag_D))
/* assume unified I & D in scache <<-NOTE */
blez t6,1f
li a0,PHYS_TO_K0(0)
move a2,t6
move a3,t7
move a1,a2
icacheopn(a0,a1,a2,a3,1lw1,(Index_Store_Tag_SD))
1: mtc0 v0,C0_SR
j ra
ENDFRAME(_init_cache)
/*
* void flush_cache (void) R4000
*
* Flush and invalidate all caches
*/
LEAF(flush_cache)
/* secondary cacheops do all the work if present */
lw a2,scache_size
blez a2,1f
lw a3,scache_linesize
li a0,PHYS_TO_K0(0)
move a1,a2
icacheop(a0,a1,a2,a3,Index_Writeback_Inv_SD)
b 2f
1:
lw a2,icache_size
blez a2,2f
lw a3,icache_linesize
li a0,PHYS_TO_K0(0)
move a1,a2
icacheop(a0,a1,a2,a3,Index_Invalidate_I)
lw a2,dcache_size
lw a3,dcache_linesize
li a0,PHYS_TO_K0(0)
move a1,a2
icacheop(a0,a1,a2,a3,Index_Writeback_Inv_D)
2: j ra
ENDFRAME(flush_cache)
/*
* void flush_cache_nowrite (void) R4000
*
* Invalidate all caches
*/
LEAF(flush_cache_nowrite)
mfc0 v0,C0_SR
and v1,v0,~SR_IE
mtc0 v1,C0_SR
mtc0 zero,C0_TAGLO
mtc0 zero,C0_TAGHI
lw a2,icache_size
blez a2,2f
lw a3,icache_linesize
li a0,PHYS_TO_K0(0)
move a1,a2
icacheop(a0,a1,a2,a3,Index_Invalidate_I)
lw a2,dcache_size
lw a3,dcache_linesize
li a0,PHYS_TO_K0(0)
move a1,a2
icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
lw a2,scache_size
blez a2,2f
lw a3,scache_linesize
li a0,PHYS_TO_K0(0)
move a1,a2
icacheop(a0,a1,a2,a3,Index_Store_Tag_SD)
2: mtc0 v0,C0_SR
j ra
ENDFRAME(flush_cache_nowrite)
/*
* void clean_cache (unsigned kva, size_t n) R4000
*
* Writeback and invalidate address range in all caches
*/
LEAF(clean_cache)
XLEAF(clear_cache)
/* secondary cacheops do all the work (if fitted) */
lw a2,scache_size
blez a2,1f
lw a3,scache_linesize
vcacheop(a0,a1,a2,a3,Hit_Writeback_Inv_SD)
b 2f
1: lw a2,icache_size
blez a2,2f
lw a3,icache_linesize
/* save kva & n for subsequent loop */
move t8,a0
move t9,a1
vcacheop(a0,a1,a2,a3,Hit_Invalidate_I)
lw a2,dcache_size
lw a3,dcache_linesize
/* restore kva & n */
move a0,t8
move a1,t9
vcacheop(a0,a1,a2,a3,Hit_Writeback_Inv_D)
2: j ra
ENDFRAME(clean_cache)
/*
* void clean_dcache (unsigned kva, size_t n) R4000
*
* Writeback and invalidate address range in primary data cache
*/
LEAF(clean_dcache)
lw a2,dcache_size
blez a2,2f
lw a3,dcache_linesize
vcacheop(a0,a1,a2,a3,Hit_Writeback_Inv_D)
2: j ra
ENDFRAME(clean_dcache)
/*
* void clean_dcache_indexed (unsigned kva, size_t n) R4000
*
* Writeback and invalidate indexed range in primary data cache
*/
LEAF(clean_dcache_indexed)
lw a2,dcache_size
blez a2,2f
lw a3,dcache_linesize
#ifdef CPU_ORION
srl a2,1 # do one set (half cache) at a time
move t8,a0 # save kva & n
move t9,a1
icacheop(a0,a1,a2,a3,Index_Writeback_Inv_D)
addu a0,t8,a2 # do next set
move a1,t9 # restore n
#endif
icacheop(a0,a1,a2,a3,Index_Writeback_Inv_D)
2: j ra
ENDFRAME(clean_dcache_indexed)
/*
* void clean_dcache_nowrite (unsigned kva, size_t n) R4000
*
* Invalidate an address range in primary data cache
*/
LEAF(clean_dcache_nowrite)
lw a2,dcache_size
blez a2,2f
lw a3,dcache_linesize
vcacheop(a0,a1,a2,a3,Hit_Invalidate_D)
2: j ra
ENDFRAME(clean_dcache_nowrite)
/*
* void clean_dcache_nowrite_indexed (unsigned kva, size_t n) R4000
*
* Invalidate indexed range in primary data cache
*/
LEAF(clean_dcache_nowrite_indexed)
mfc0 v0,C0_SR
and v1,v0,~SR_IE
mtc0 v1,C0_SR
mtc0 zero,C0_TAGLO
mtc0 zero,C0_TAGHI
lw a2,dcache_size
blez a2,2f
lw a3,dcache_linesize
#ifdef CPU_ORION
srl a2,1 # do one set (half cache) at a time
move t8,a0 # save kva & n
move t9,a1
icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
addu a0,t8,a2 # do next set
move a1,t9 # restore n
#endif
icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
2: mtc0 v0,C0_SR
j ra
ENDFRAME(clean_dcache_nowrite_indexed)
/*
* void clean_icache (unsigned kva, size_t n) R4000
*
* Invalidate address range in primary instruction cache
*/
LEAF(clean_icache)
lw a2,icache_size
blez a2,2f
lw a3,icache_linesize
vcacheop(a0,a1,a2,a3,Hit_Invalidate_I)
2: j ra
ENDFRAME(clean_icache)
/*
* void clean_icache_indexed (unsigned kva, size_t n) R4000
*
* Invalidate indexed range in primary instruction cache
*/
LEAF(clean_icache_indexed)
lw a2,icache_size
blez a2,2f
lw a3,icache_linesize
#ifdef CPU_ORION
srl a2,1 # do one set (half cache) at a time
move t8,a0 # save kva & n
move t9,a1
icacheop(a0,a1,a2,a3,Index_Invalidate_I)
addu a0,t8,a2 # do next set
move a1,t9 # restore n
#endif
icacheop(a0,a1,a2,a3,Index_Invalidate_I)
2: j ra
ENDFRAME(clean_icache_indexed)
/*
* void clean_scache (unsigned kva, size_t n) R4000
*
* Writeback and invalidate address range in secondary cache
*/
LEAF(clean_scache)
lw a2,scache_size
blez a2,2f
lw a3,scache_linesize
vcacheop(a0,a1,a2,a3,Hit_Writeback_Inv_SD)
2: j ra
ENDFRAME(clean_scache)
/*
* void clean_scache_indexed (unsigned kva, size_t n) R4000
*
* Writeback and invalidate indexed range in secondary cache
*/
LEAF(clean_scache_indexed)
lw a2,scache_size
blez a2,2f
lw a3,scache_linesize
icacheop(a0,a1,a2,a3,Index_Writeback_Inv_SD)
2: j ra
ENDFRAME(clean_scache_indexed)
/*
* void clean_scache_nowrite (unsigned kva, size_t n) R4000
*
* Invalidate an address range in secondary cache
*/
LEAF(clean_scache_nowrite)
lw a2,scache_size
blez a2,2f
lw a3,scache_linesize
vcacheop(a0,a1,a2,a3,Hit_Invalidate_SD)
2: j ra
ENDFRAME(clean_scache_nowrite)
/*
* void clean_scache_nowrite_indexed (unsigned kva, size_t n) R4000
*
* Invalidate indexed range in secondary cache
*/
LEAF(clean_scache_nowrite_indexed)
mfc0 v0,C0_SR
and v1,v0,~SR_IE
mtc0 v1,C0_SR
mtc0 zero,C0_TAGLO
mtc0 zero,C0_TAGHI
lw a2,scache_size
blez a2,2f
lw a3,scache_linesize
icacheop(a0,a1,a2,a3,Index_Store_Tag_SD)
2: mtc0 v0,C0_SR
j ra
ENDFRAME(clean_scache_nowrite_indexed)
/**************************************************************************
**
** get_mem_conf - get memory configuration R4000
**
***************************************************************************/
FRAME(get_mem_conf,sp,0,ra)
lw t6, mem_size
sw t6, 0(a0)
lw t7, icache_size
sw t7, 4(a0)
lw t8, dcache_size
sw t8, 8(a0)
lw t7, scache_size
sw t7, 12(a0)
j ra
ENDFRAME(get_mem_conf)
#endif /* __mips == 3 */
/*
* void set_mem_size (mem_size)
*
* config_memory()'s memory size gets written into mem_size here.
* Now we don't need to call config_cache() with memory size - New to IDTC6.0
*/
FRAME(set_memory_size,sp,0,ra)
sw a0, mem_size
j ra
ENDFRAME(set_memory_size)

View File

@@ -0,0 +1,390 @@
/*
Based upon IDT provided code with the following release:
This source code has been made available to you by IDT on an AS-IS
basis. Anyone receiving this source is licensed under IDT copyrights
to use it in any way he or she deems fit, including copying it,
modifying it, compiling it, and redistributing it either with or
without modifications. No license under IDT patents or patent
applications is to be implied by the copyright license.
Any user of this software should understand that IDT cannot provide
technical support for this software and will not be responsible for
any consequences resulting from the use of this software.
Any person who transfers this source code or any derivative work must
include the IDT copyright notice, this paragraph, and the preceeding
two paragraphs in the transferred software.
COPYRIGHT IDT CORPORATION 1996
LICENSED MATERIAL - PROGRAM PROPERTY OF IDT
idttlb.S,v 1.3 2000/10/24 21:50:37 joel Exp
*/
/*
** idttlb.s - fetch the registers associated with and the contents
** of the tlb.
**
*/
/* 950308: Ketan patched a few tlb functions that would not have worked.*/
#include <rtems/mips/iregdef.h>
#include <rtems/mips/idtcpu.h>
#include <rtems/asm.h>
.text
#if __mips == 1
/*
** ret_tlblo -- returns the 'entrylo' contents for the TLB
** 'c' callable - as ret_tlblo(index) - where index is the
** tlb entry to return the lo value for - if called from assembly
** language then index should be in register a0.
*/
FRAME(ret_tlblo,sp,0,ra)
.set noreorder
mfc0 t0,C0_SR # save sr
nop
and t0,~SR_PE # dont inadvertantly clear PE
mtc0 zero,C0_SR # clear interrupts
mfc0 t1,C0_TLBHI # save pid
sll a0,TLBINX_INXSHIFT # position index
mtc0 a0,C0_INX # write to index register
nop
tlbr # put tlb entry in entrylo and hi
nop
mfc0 v0,C0_TLBLO # get the requested entry lo
mtc0 t1,C0_TLBHI # restore pid
mtc0 t0,C0_SR # restore status register
j ra
nop
.set reorder
ENDFRAME(ret_tlblo)
#endif
#if __mips == 3
/*
** ret_tlblo[01] -- returns the 'entrylo' contents for the TLB
** 'c' callable - as ret_tlblo(index) - where index is the
** tlb entry to return the lo value for - if called from assembly
** language then index should be in register a0.
*/
FRAME(ret_tlblo0,sp,0,ra)
mfc0 t0,C0_SR # save sr
mtc0 zero,C0_SR # clear interrupts
mfc0 t1,C0_TLBHI # save pid
mtc0 a0,C0_INX # write to index register
.set noreorder
nop; nop; nop; nop; nop; nop; nop; nop
.set reorder
tlbr # put tlb entry in entrylo and hi
.set noreorder
nop; nop; nop; nop; nop; nop; nop; nop
.set reorder
mfc0 v0,C0_TLBLO0 # get the requested entry lo
mtc0 t1,C0_TLBHI # restore pid
mtc0 t0,C0_SR # restore status register
j ra
ENDFRAME(ret_tlblo0)
FRAME(ret_tlblo1,sp,0,ra)
mfc0 t0,C0_SR # save sr
mtc0 zero,C0_SR # clear interrupts
mfc0 t1,C0_TLBHI # save pid
mtc0 a0,C0_INX # write to index register
.set noreorder
nop; nop; nop; nop; nop; nop; nop; nop
.set reorder
tlbr # put tlb entry in entrylo and hi
.set noreorder
nop; nop; nop; nop; nop; nop; nop; nop
.set reorder
mfc0 v0,C0_TLBLO1 # get the requested entry lo
mtc0 t1,C0_TLBHI # restore pid
mtc0 t0,C0_SR # restore status register
j ra
ENDFRAME(ret_tlblo1)
/*
** ret_pagemask(index) -- return pagemask contents of tlb entry "index"
*/
FRAME(ret_pagemask,sp,0,ra)
mfc0 t0,C0_SR # save sr
mtc0 zero,C0_SR # disable interrupts
mfc0 t1,C0_TLBHI # save current pid
mtc0 a0,C0_INX # drop it in C0 register
.set noreorder
nop; nop; nop; nop; nop; nop; nop; nop
.set reorder
tlbr # read entry to entry hi/lo
.set noreorder
nop; nop; nop; nop; nop; nop; nop; nop
.set reorder
mfc0 v0,C0_PAGEMASK # to return value
mtc0 t1,C0_TLBHI # restore current pid
mtc0 t0,C0_SR # restore sr
j ra
ENDFRAME(ret_pagemask)
/*
** ret_tlbwired(void) -- return wired register
*/
FRAME(ret_tlbwired,sp,0,ra)
mfc0 v0,C0_WIRED
j ra
ENDFRAME(ret_tlbwired)
#endif
/*
** ret_tlbhi -- return the tlb entry high content for tlb entry
** index
*/
FRAME(ret_tlbhi,sp,0,ra)
#if __mips == 1
.set noreorder
mfc0 t0,C0_SR # save sr
nop
and t0,~SR_PE
mtc0 zero,C0_SR # disable interrupts
mfc0 t1,C0_TLBHI # save current pid
sll a0,TLBINX_INXSHIFT # position index
mtc0 a0,C0_INX # drop it in C0 register
nop
tlbr # read entry to entry hi/lo
nop
mfc0 v0,C0_TLBHI # to return value
mtc0 t1,C0_TLBHI # restore current pid
mtc0 t0,C0_SR # restore sr
j ra
nop
.set reorder
#endif
#if __mips == 3
mfc0 t0,C0_SR # save sr
mtc0 zero,C0_SR # disable interrupts
mfc0 t1,C0_TLBHI # save current pid
mtc0 a0,C0_INX # drop it in C0 register
.set noreorder
nop; nop; nop; nop; nop; nop; nop; nop
.set reorder
tlbr # read entry to entry hi/lo0/lo1/mask
.set noreorder
nop; nop; nop; nop; nop; nop; nop; nop
.set reorder
mfc0 v0,C0_TLBHI # to return value
mtc0 t1,C0_TLBHI # restore current pid
mtc0 t0,C0_SR # restore sr
j ra
#endif
ENDFRAME(ret_tlbhi)
/*
** ret_tlbpid() -- return tlb pid contained in the current entry hi
*/
FRAME(ret_tlbpid,sp,0,ra)
#if __mips == 1
.set noreorder
mfc0 v0,C0_TLBHI # fetch tlb high
nop
and v0,TLBHI_PIDMASK # isolate and position
srl v0,TLBHI_PIDSHIFT
j ra
nop
.set reorder
#endif
#if __mips == 3
mfc0 v0,C0_TLBHI # to return value
nop
and v0,TLBHI_PIDMASK
j ra
#endif
ENDFRAME(ret_tlbpid)
/*
** tlbprobe(address, pid) -- probe the tlb to see if address is currently
** mapped
** a0 = vpn - virtual page numbers are 0=0 1=0x1000, 2=0x2000...
** virtual page numbers for the r3000 are in
** entry hi bits 31-12
** a1 = pid - this is a process id ranging from 0 to 63
** this process id is shifted left 6 bits and or'ed into
** the entry hi register
** returns an index value (0-63) if successful -1 -f not
*/
FRAME(tlbprobe,sp,0,ra)
#if __mips == 1
.set noreorder
mfc0 t0,C0_SR /* fetch status reg */
and a0,TLBHI_VPNMASK /* isolate just the vpn */
and t0,~SR_PE /* don't inadvertantly clear pe */
mtc0 zero,C0_SR
mfc0 t1,C0_TLBHI
sll a1,TLBHI_PIDSHIFT /* possition the pid */
and a1,TLBHI_PIDMASK
or a0,a1 /* build entry hi value */
mtc0 a0,C0_TLBHI
nop
tlbp /* do the probe */
nop
mfc0 v1,C0_INX
li v0,-1
bltz v1,1f
nop
sra v0,v1,TLBINX_INXSHIFT /* get index positioned for return */
1:
mtc0 t1,C0_TLBHI /* restore tlb hi */
mtc0 t0,C0_SR /* restore the status reg */
j ra
nop
.set reorder
#endif
#if __mips == 3
mfc0 t0,C0_SR # save sr
mtc0 zero,C0_SR # disable interrupts
mfc0 t1,C0_TLBHI # save current pid
and a0,TLBHI_VPN2MASK # construct tlbhi for probe
and a1,TLBHI_PIDMASK
or a0,a1
mtc0 a0,C0_TLBHI
.set noreorder
nop; nop; nop; nop; nop; nop; nop; nop
.set reorder
tlbp # probe entry to entry hi/lo0/lo1/mask
.set noreorder
nop; nop; nop; nop; nop; nop; nop; nop
.set reorder
mfc0 v1,C0_INX
li v0,-1
bltz v1,1f
move v0,v1
1: mtc0 t1,C0_TLBHI # restore current pid
mtc0 t0,C0_SR # restore sr
j ra
#endif
ENDFRAME(tlbprobe)
/*
** resettlb(index) Invalidate the TLB entry specified by index
*/
FRAME(resettlb,sp,0,ra)
#if __mips == 1
.set noreorder
mfc0 t0,C0_TLBHI # fetch the current hi
mfc0 v0,C0_SR # fetch the status reg.
li t2,K0BASE&TLBHI_VPNMASK
and v0,~SR_PE # dont inadvertantly clear PE
mtc0 zero,C0_SR
mtc0 t2,C0_TLBHI # set up tlbhi
mtc0 zero,C0_TLBLO
sll a0,TLBINX_INXSHIFT
mtc0 a0,C0_INX
nop
tlbwi # do actual invalidate
nop
mtc0 t0,C0_TLBHI
mtc0 v0,C0_SR
j ra
nop
.set reorder
#endif
#if __mips == 3
li t2,K0BASE&TLBHI_VPN2MASK
mfc0 t0,C0_TLBHI # save current TLBHI
mfc0 v0,C0_SR # save SR and disable interrupts
mtc0 zero,C0_SR
mtc0 t2,C0_TLBHI # invalidate entry
mtc0 zero,C0_TLBLO0
mtc0 zero,C0_TLBLO1
mtc0 a0,C0_INX
.set noreorder
nop; nop; nop; nop; nop; nop; nop; nop
.set reorder
tlbwi
.set noreorder
nop; nop; nop; nop; nop; nop; nop; nop
.set reorder
mtc0 t0,C0_TLBHI
mtc0 v0,C0_SR
j ra
#endif
ENDFRAME(resettlb)
#if __mips == 1
/*
** Setup TLB entry
**
** map_tlb(index, tlbhi, phypage)
** a0 = TLB entry index
** a1 = virtual page number and PID
** a2 = physical page
*/
FRAME(map_tlb,sp,0,ra)
.set noreorder
sll a0,TLBINX_INXSHIFT
mfc0 v0,C0_SR # fetch the current status
mfc0 a3,C0_TLBHI # save the current hi
and v0,~SR_PE # dont inadvertantly clear parity
mtc0 zero,C0_SR
mtc0 a1,C0_TLBHI # set the hi entry
mtc0 a2,C0_TLBLO # set the lo entry
mtc0 a0,C0_INX # load the index
nop
tlbwi # put the hi/lo in tlb entry indexed
nop
mtc0 a3,C0_TLBHI # put back the tlb hi reg
mtc0 v0,C0_SR # restore the status register
j ra
nop
.set reorder
ENDFRAME(map_tlb)
#endif
#if __mips == 3
/*
** Setup R4000 TLB entry
**
** map_tlb4000(mask_index, tlbhi, pte_even, pte_odd)
** a0 = TLB entry index and page mask
** a1 = virtual page number and PID
** a2 = pte -- contents of even pte
** a3 = pte -- contents of odd pte
*/
FRAME(map_tlb4000,sp,0,ra)
and t2,a0,TLBPGMASK_MASK
and a0,TLBINX_INXMASK
mfc0 t1,C0_TLBHI # save current TLBPID
mfc0 v0,C0_SR # save SR and disable interrupts
mtc0 zero,C0_SR
mtc0 t2,C0_PAGEMASK # set
mtc0 a1,C0_TLBHI # set VPN and TLBPID
mtc0 a2,C0_TLBLO0 # set PPN and access bits
mtc0 a3,C0_TLBLO1 # set PPN and access bits
mtc0 a0,C0_INX # set INDEX to wired entry
.set noreorder
nop; nop; nop; nop; nop; nop; nop; nop
.set reorder
tlbwi # drop it in
.set noreorder
nop; nop; nop; nop; nop; nop; nop; nop
.set reorder
mtc0 t1,C0_TLBHI # restore TLBPID
mtc0 v0,C0_SR # restore SR
j ra
ENDFRAME(map_tlb4000)
#endif
/*
** Set current TLBPID. This assumes PID is positioned correctly in reg.
** a0.
*/
FRAME(set_tlbpid,sp,0,ra)
.set noreorder
mtc0 a0,C0_TLBHI
j ra
nop
.set reorder
ENDFRAME(set_tlbpid)

View File

@@ -0,0 +1,16 @@
/*
* inittlb.c,v 1.2 1999/03/31 23:21:19 joel Exp
*/
#include <rtems/mips/idtcpu.h>
extern void resettlb( int i );
void init_tlb(void)
{
int i;
for (i = 0; i < N_TLB_ENTRIES; i++ )
resettlb(i);
}

View File

@@ -0,0 +1,163 @@
/*
* linkcmds,v 1.10 2003/01/20 20:20:11 joel Exp
*
*/
/*
* Declare some sizes.
*/
_RamBase = DEFINED(_RamBase) ? _RamBase : 0x80000000;
_RamSize = DEFINED(_RamSize) ? _RamSize : 4M;
_StackSize = DEFINED(_StackSize) ? _StackSize : 0x1000;
SECTIONS
{
/* 0x80000000 - 0x8001FFFF used by PMON (with 0x80010000 - 0x8001FFFF as heap for symbol storage)
0x80020000 - 0x8002FFFF reserved for shared memory
0x80030000 beginning of text (code) section
*/
.text 0x80030000 :
{
_ftext = . ;
eprol = .;
*(.text)
*(.text.*)
*(.gnu.linkonce.t*)
*(.mips16.fn.*)
*(.mips16.call.*)
PROVIDE (__runtime_reloc_start = .);
*(.rel.sdata)
PROVIDE (__runtime_reloc_stop = .);
/*
* Special FreeBSD sysctl sections.
*/
. = ALIGN (16);
__start_set_sysctl_set = .;
*(set_sysctl_*);
__stop_set_sysctl_set = ABSOLUTE(.);
*(set_domain_*);
*(set_pseudo_*);
*(.gcc_except_table)
*(.eh_frame_hdr)
*(.eh_frame)
}
.init :
{
KEEP(*crti.o(.init))
KEEP(*(.init))
KEEP(*crtn.o(.init))
}
.fini :
{
KEEP(*crti.o(.fini))
KEEP(*(.fini))
KEEP(*crtn.o(.fini))
}
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
/* We don't want to include the .ctor section from
from the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
etext = .;
_etext = .;
}
.rdata : {
*(.rdata)
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r*)
}
_fdata = ALIGN(16);
.data : {
*(.data)
*(.data.*)
*(.gnu.linkonce.d*)
SORT(CONSTRUCTORS)
}
. = ALIGN(8);
.jcr : {
KEEP (*(.jcr))
}
_gp = ALIGN(16) + 0x8000;
__global = _gp;
.sdata : {
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s*)
}
.lit8 : {
*(.lit8)
}
.lit4 : {
*(.lit4)
}
edata = .;
_edata = .;
_fbss = .;
.sbss : {
*(.sbss)
*(.scommon)
}
.bss : {
_bss_start = . ;
*(.bss)
*(.reginfo)
*(COMMON)
. = ALIGN (64);
_stack_limit = .;
. += _StackSize;
__stack = .;
_stack_init = .;
end = .;
_end = .;
}
/* Debug sections. These should never be loadable, but they must have
zero addresses for the debuggers to work correctly. */
.line 0 : { *(.line) }
.debug 0 : { *(.debug) }
.debug_sfnames 0 : { *(.debug_sfnames) }
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_macinfo 0 : { *(.debug_macinfo) }
.debug_pubnames 0 : { *(.debug_pubnames) }
.debug_aranges 0 : { *(.debug_aranges) }
}