added virtex BSP support and some missing files for common PPC

exception handling
This commit is contained in:
Thomas Doerfler
2007-07-04 12:37:36 +00:00
parent 73cdeb6a51
commit 862c231785
29 changed files with 5424 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
2007-04-1 Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
* bsp_specs, bsp_specs.dl, ChangeLog, configure.ac,
* console/consolelite.c, dlentry/dlentry.S, include/bsp.h,
* include/coverhd.h, include/opbintctrl.h, include/tm27.h,
* include/xparameters_dflt.h, irq/irq.h, irq/irq_init.c,
* Makefile.am, network/xiltemac.c, network/xiltemac.h,
* opbintctrl/opbintctrl.c, preinstall.am, README,
* startup/bspclean.c, startup/bspstart.c, startup/linkcmds,
* startup/linkcmds.dl, startup/setvec.c;
integration of virtex BSP into RTEMS source tree

View File

@@ -0,0 +1,99 @@
##
## $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 =
include_bspdir = $(includedir)/bsp
include_HEADERS += include/coverhd.h
dist_project_lib_DATA += startup/linkcmds startup/linkcmds.dl
noinst_PROGRAMS += startup.rel
startup_rel_SOURCES = startup/bspclean.c ../../shared/bsplibc.c \
../../shared/bsppost.c startup/bspstart.c ../../shared/bootcard.c \
../../shared/sbrk.c startup/setvec.c \
../../shared/gnatinstallhandler.c
startup_rel_CPPFLAGS = $(AM_CPPFLAGS)
startup_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
noinst_PROGRAMS += dlentry.rel
dlentry_rel_SOURCES = dlentry/dlentry.S
dlentry_rel_CPPFLAGS = $(AM_CPPFLAGS)
dlentry_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
noinst_PROGRAMS += bspconsole.rel
bspconsole_rel_SOURCES = console/consolelite.c ../../shared/console.c
bspconsole_rel_CPPFLAGS = $(AM_CPPFLAGS)
bspconsole_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
include_bsp_HEADERS = include/opbintctrl.h
noinst_PROGRAMS += opbintctrl.rel
opbintctrl_rel_SOURCES = opbintctrl/opbintctrl.c
opbintctrl_rel_CPPFLAGS = $(AM_CPPFLAGS)
opbintctrl_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
include_bsp_HEADERS += irq/irq.h
noinst_PROGRAMS += irq.rel
irq_rel_SOURCES = irq/irq_init.c ../shared/irq/irq_asm.S
irq_rel_CPPFLAGS = $(AM_CPPFLAGS)
irq_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
include_bsp_HEADERS += ../../powerpc/shared/vectors/vectors.h
noinst_PROGRAMS += vectors.rel
vectors_rel_SOURCES = ../../powerpc/shared/vectors/vectors.h \
../../powerpc/shared/vectors/vectors_init.c \
../../powerpc/shared/vectors/vectors.S
vectors_rel_CPPFLAGS = $(AM_CPPFLAGS)
vectors_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
if HAS_NETWORKING
network_CPPFLAGS = -D__INSIDE_RTEMS_BSD_TCPIP_STACK__
network_CPPFLAGS += -D__BSD_VISIBLE
noinst_PROGRAMS += network.rel
network_rel_SOURCES = network/xiltemac.c
network_rel_CPPFLAGS = $(AM_CPPFLAGS)
network_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
##RSG Start
## include_HEADERS += include/xiltemac.h
#noinst_PROGRAMS += xiltemac.rel
#xiltemac_rel_SOURCES = network/xiltemac.c
#xiltemac_rel_CPPFLAGS = -D__INSIDE_RTEMS_BSD_TCPIP_STACK__ $(AM_CPPFLAGS) -O0 -g
#xiltemac_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
##RSG End
endif
noinst_LIBRARIES = libbsp.a
libbsp_a_SOURCES =
libbsp_a_LIBADD = startup.rel dlentry.rel bspconsole.rel opbintctrl.rel \
vectors.rel irq.rel network.rel
libbsp_a_LIBADD += ../../../libcpu/@RTEMS_CPU@/@exceptions@/rtems-cpu.rel \
../../../libcpu/@RTEMS_CPU@/@exceptions@/raw_exception.rel \
../../../libcpu/@RTEMS_CPU@/shared/cpuIdent.rel \
../../../libcpu/@RTEMS_CPU@/ppc403/clock.rel \
../../../libcpu/@RTEMS_CPU@/ppc403/timer.rel \
../../../libcpu/@RTEMS_CPU@/ppc403/tty_drv.rel
EXTRA_DIST = times
include $(srcdir)/preinstall.am
include $(top_srcdir)/../../../../automake/local.am

View File

@@ -0,0 +1,91 @@
#
# $Id$
#
# Adapted from vitex BSP
BSP NAME: Virtex
BOARD: Xilinx ML-403 and (hopefully) any vitex/PPC based board
BUS: N/A
CPU FAMILY: ppc
CPU: PowerPC 405GP
COPROCESSORS: N/A
MODE: 32 bit mode
DEBUG MONITOR:
PERIPHERALS
===========
TIMERS: 405GP internal
SERIAL PORTS: Xilinx consolelite
REAL-TIME CLOCK: none
DMA: Xilinx vitex internal
VIDEO: none
SCSI: none
NETWORKING: Xilinx TEMAC
DRIVER INFORMATION
==================
CLOCK DRIVER: PPC Decrementer
IOSUPP DRIVER: N/A
SHMSUPP: N/A
TIMER DRIVER: N/A
TTY DRIVER: consoleelite
STDIO
=====
PORT: Console port 0
ELECTRICAL: RS-232
BAUD: as defined in FPGA design
BITS PER CHARACTER: 8
PARITY: None
STOP BITS: 1
Notes
=====
Board description
-----------------
clock rate: 234 MHz
ROM: 16MByte FLASH
RAM: 64MByte DRAM
virtex only supports single processor operations.
Porting
-------
This board support package is written for a typical virtex/PPC FPGA
system. The rough features of such a board are described above.
When a new virtex FPGA system is created (using the Xilinx design
software), a parameter file "xparameters.h" is also created, which
describes the basic features of the hardware (like peripherals
inculded, interrupt routing etc).
This BSP normally takes its basic HW description for the file
"xparameters_dflt.h", which describes my FPGA system. When this BSP
should run on a different hardware, a path to the proper
"xparameters.h" can be provided on the "configure" command line.
For adapting this BSP to other boards,
the following files should be
modified:
- c/src/lib/libbsp/powerpc/virtex/startup/linkcmds
for the memory layout required
- c/src/lib/libbsp/powerpc/virtex/startup/bspstart.c
for adaption of BSP_Configuration. here you can select
the clock source for the timers and the serial interface
(system clock or external clock pin), the clock rates, initial
baud rate and other stuff
- c/src/lib/libbsp/powerpc/virtex/include/bsp.h
some BSP-related constants
- c/src/lib/libbsp/powerpc/virtex/*
well, they should be generic, so there _should_ be no reason
to mess around there (but who knows...)

View File

@@ -0,0 +1,15 @@
%rename endfile old_endfile
%rename startfile old_startfile
%rename link old_link
*startfile:
%{!qrtems: %(old_startfile)} %{!nostdlib: %{qrtems: \
%{!qrtems_debug: } \
%{qrtems_debug: }ecrti%O%s}}
*endfile:
%{!qrtems: %(old_endfile)} %{qrtems: ecrtn%O%s}
*link:
%{!qrtems: %(old_link)} %{qrtems: -dc -dp -u __vectors -u download_entry -N }

View File

@@ -0,0 +1,23 @@
%rename cpp old_cpp
%rename lib old_lib
%rename endfile old_endfile
%rename startfile old_startfile
%rename link old_link
*cpp:
%(old_cpp) %{qrtems: -D__embedded__} -Asystem(embedded)
*lib:
%{!qrtems: %(old_lib)} %{qrtems: ecrti%O%s --start-group \
%{!qrtems_debug: -lrtemsall} %{qrtems_debug: -lrtemsall_g} \
-lc -lgcc --end-group \
%{!qnolinkcmds: -T linkcmds%s}}
*startfile:
%{!qrtems: %(old_startfile)} %{qrtems: \
%{!qrtems_debug: } \
%{qrtems_debug: }}
*link:
%{!qrtems: %(old_link)} %{qrtems: -dc -dp -u __vectors -u download_entry -N }

View File

@@ -0,0 +1,366 @@
/*
* This file contains the console driver for the xilinx uart lite.
*
* Author: Keith Robertson <kjrobert@alumni.uwaterloo.ca>
* COPYRIGHT (c) 2005 by Linn Products Ltd, Scotland.
*
* Derived from libbsp/no_cpu/no_bsp/console.c and therefore also:
*
* 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.
*
*/
#include <rtems.h>
#include <rtems/libio.h>
#include <bsp/irq.h>
#include <bsp.h>
#include <libchip/serial.h>
#include <libchip/sersupp.h>
/* Status Register Masks */
#define PARITY_ERROR 0x80 /* Parity Error */
#define FRAME_ERROR 0x40 /* Frame Error */
#define OVERRUN_ERROR 0x20 /* Overrun Error */
#define STATUS_REG_ERROR_MASK ( PARITY_ERROR | FRAME_ERROR | OVERRUN_ERROR )
#define INTR_ENABLED 0x10 /* Interrupts are enabled */
#define TX_FIFO_FULL 0x08 /* Transmit FIFO is full */
#define TX_FIFO_EMPTY 0x04 /* Transmit FIFO is empty */
#define RX_FIFO_FULL 0x02 /* Receive FIFO is full */
#define RX_FIFO_VALID_DATA 0x01 /* Receive FIFO has valid data */
/* Control Register Masks*/
#define ENABLE_INTR 0x10 /* Enable interrupts */
#define RST_RX_FIFO 0x02 /* Reset and clear RX FIFO */
#define RST_TX_FIFO 0x01 /* Reset and clear TX FIFO */
/* General Defines */
#define TX_FIFO_SIZE 16
#define RX_FIFO_SIZE 16
#define RECV_REG 0
#define TRAN_REG 4
#define STAT_REG 8
#define CTRL_REG 12
RTEMS_INLINE_ROUTINE uint32_t xlite_uart_control(uint32_t base)
{
uint32_t c = *((volatile uint32_t*)(base+CTRL_REG));
return c;
}
RTEMS_INLINE_ROUTINE uint32_t xlite_uart_status(uint32_t base)
{
uint32_t c = *((volatile uint32_t*)(base+STAT_REG));
return c;
}
RTEMS_INLINE_ROUTINE uint32_t xlite_uart_read(uint32_t base)
{
uint32_t c = *((volatile uint32_t*)(base+RECV_REG));
return c;
}
RTEMS_INLINE_ROUTINE void xlite_uart_write(uint32_t base, char ch)
{
*(volatile uint32_t*)(base+TRAN_REG) = (uint32_t)ch;
return;
}
int xlite_write_char(uint32_t base, char ch)
{
uint32_t retrycount= 0, idler, status;
while( ((status = xlite_uart_status(base)) & TX_FIFO_FULL) != 0 )
{
++retrycount;
/* uart tx is busy */
if( retrycount == 0x4000 )
{
/* retrycount is arbitrary- just make it big enough so the uart is sure to be timed out before it trips */
return -1;
}
/* spin for a bit so we can sample the register rather than
* continually reading it */
for( idler= 0; idler < 0x2000; idler++);
}
xlite_uart_write(base, ch);
return 1;
}
void xlite_init (int minor )
{
uint32_t base = Console_Port_Tbl[minor].ulCtrlPort1;
/* clear status register */
*((volatile uint32_t*)(base+STAT_REG)) = 0;
/* clear control register; reset fifos & interrupt enable */
*((volatile uint32_t*)(base+CTRL_REG)) = RST_RX_FIFO | RST_TX_FIFO;
}
int xlite_open(
int major,
int minor,
void *arg
)
{
uint32_t base = Console_Port_Tbl[minor].ulCtrlPort1;
/* the lite uarts have hardcoded baud & serial parms so no port
* conditioning is needed. We're running polled so no interrupt
* enables either */
/* clear status register */
*((volatile uint32_t*)(base+STAT_REG)) = 0;
/* clear control register; reset fifos & disable interrupts */
*((volatile uint32_t*)(base+CTRL_REG)) = RST_RX_FIFO | RST_TX_FIFO;
return RTEMS_SUCCESSFUL;
}
int xlite_close(
int major,
int minor,
void *arg
)
{
/* no shutdown protocol necessary */
return RTEMS_SUCCESSFUL;
}
int xlite_read_polled (int minor )
{
uint32_t base = Console_Port_Tbl[minor].ulCtrlPort1;
unsigned int status = xlite_uart_status(base);
if(status & RX_FIFO_VALID_DATA)
return (int)xlite_uart_read(base);
else
return -1;
}
int xlite_write_buffer_polled(
int minor,
const char *buf,
int len
)
{
uint32_t base = Console_Port_Tbl[minor].ulCtrlPort1;
int nwrite = 0;
/*
* poll each byte in the string out of the port.
*/
while (nwrite < len)
{
if( xlite_write_char(base, *buf++) < 0 ) break;
nwrite++;
}
/*
* return the number of bytes written.
*/
return nwrite;
}
void xlite_write_char_polled(
int minor,
char c
)
{
uint32_t base = Console_Port_Tbl[minor].ulCtrlPort1;
xlite_write_char(base, c);
return;
}
int xlite_set_attributes(int minor, const struct termios *t)
{
return RTEMS_SUCCESSFUL;
}
console_fns xlite_fns_polled =
{
libchip_serial_default_probe, /* deviceProbe */
xlite_open, /* deviceFirstOpen */
xlite_close, /* deviceLastClose */
xlite_read_polled, /* deviceRead */
xlite_write_buffer_polled, /* deviceWrite */
xlite_init, /* deviceInitialize */
xlite_write_char_polled, /* deviceWritePolled */
xlite_set_attributes, /* deviceSetAttributes */
FALSE, /* deviceOutputUsesInterrupts */
};
/*
** Set ulCtrlPort1 to the base address of each UART Lite instance. Set in vhdl model.
*/
console_tbl Console_Port_Tbl[] = {
{
"/dev/ttyS0", /* sDeviceName */
SERIAL_CUSTOM, /* deviceType */
&xlite_fns_polled, /* pDeviceFns */
NULL, /* deviceProbe, assume it is there */
NULL, /* pDeviceFlow */
16, /* ulMargin */
8, /* ulHysteresis */
(void *) NULL, /* NULL */ /* pDeviceParams */
0x40600000, /* ulCtrlPort1 */
0, /* ulCtrlPort2 */
0, /* ulDataPort */
NULL, /* getRegister */
NULL, /* setRegister */
NULL, /* unused */ /* getData */
NULL, /* unused */ /* setData */
0, /* ulClock */
0 /* ulIntVector -- base for port */
},
{
"/dev/ttyS1", /* sDeviceName */
SERIAL_CUSTOM, /* deviceType */
&xlite_fns_polled, /* pDeviceFns */
NULL, /* deviceProbe, assume it is there */
NULL, /* pDeviceFlow */
16, /* ulMargin */
8, /* ulHysteresis */
(void *) NULL, /* NULL */ /* pDeviceParams */
0x40610000, /* ulCtrlPort1 */
0, /* ulCtrlPort2 */
0, /* ulDataPort */
NULL, /* getRegister */
NULL, /* setRegister */
NULL, /* unused */ /* getData */
NULL, /* unused */ /* setData */
0, /* ulClock */
0 /* ulIntVector -- base for port */
},
{
"/dev/ttyS2", /* sDeviceName */
SERIAL_CUSTOM, /* deviceType */
&xlite_fns_polled, /* pDeviceFns */
NULL, /* deviceProbe, assume it is there */
NULL, /* pDeviceFlow */
16, /* ulMargin */
8, /* ulHysteresis */
(void *) NULL, /* NULL */ /* pDeviceParams */
0x40620000, /* ulCtrlPort1 */
0, /* ulCtrlPort2 */
0, /* ulDataPort */
NULL, /* getRegister */
NULL, /* setRegister */
NULL, /* unused */ /* getData */
NULL, /* unused */ /* setData */
0, /* ulClock */
0 /* ulIntVector -- base for port */
},
{
"/dev/ttyS3", /* sDeviceName */
SERIAL_CUSTOM, /* deviceType */
&xlite_fns_polled, /* pDeviceFns */
NULL, /* deviceProbe, assume it is there */
NULL, /* pDeviceFlow */
16, /* ulMargin */
8, /* ulHysteresis */
(void *) NULL, /* NULL */ /* pDeviceParams */
0x40630000, /* ulCtrlPort1 */
0, /* ulCtrlPort2 */
0, /* ulDataPort */
NULL, /* getRegister */
NULL, /* setRegister */
NULL, /* unused */ /* getData */
NULL, /* unused */ /* setData */
0, /* ulClock */
0 /* ulIntVector -- base for port */
}
};
#define NUM_CONSOLE_PORTS (sizeof(Console_Port_Tbl)/sizeof(console_tbl))
unsigned long Console_Port_Count = NUM_CONSOLE_PORTS;
console_data Console_Port_Data[NUM_CONSOLE_PORTS];
rtems_device_minor_number Console_Port_Minor;
#include <rtems/bspIo.h>
void outputChar(char ch)
{
if (ch == '\n') {
xlite_write_char_polled( 0, '\r' );
}
xlite_write_char_polled( 0, ch );
}
char inputChar()
{
return (char)xlite_read_polled(0);
}
BSP_output_char_function_type BSP_output_char = outputChar;
BSP_polling_getchar_function_type BSP_poll_char = inputChar;

View File

@@ -0,0 +1,156 @@
/* dlentry.s
*
* This file contains the entry code for RTEMS programs starting
* after download to RAM
*
* Author: Thomas Doerfler <td@imd.m.isar.de>
* IMD Ingenieurbuero fuer Microcomputertechnik
*
* COPYRIGHT (c) 1998 by IMD
*
* Changes from IMD are covered by the original distributions terms.
* This file has been derived from the papyrus BSP:
*
* This file contains the entry veneer for RTEMS programs
* downloaded to Papyrus.
*
* Author: Andrew Bray <andy@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.
*
* $Id$
*
* derived from "helas403/dlentry.S":
* Id: dlentry.S,v 1.2 2000/08/02 16:30:57 joel Exp
*/
#include <rtems/asm.h>
/*
* The virtex ELF link scripts support three special sections:
* .entry The actual entry point
* .vectors The section containing the interrupt entry veneers.
*/
/*
* Downloaded code loads the vectors separately to 0x00000100,
* so .entry can be over 256 bytes.
*
* The other sections are linked in the following order:
* .entry
* .text
* .data
* .bss
* see linker command file for section placement
*
* The initial stack is set to stack.end
*
* All the entry veneer has to do is to clear the BSS.
*/
/*
* GDB likes to have debugging information for the entry veneer.
* Here was some DWARF information. IMD removed it, because we
* could not check, whether it was still correct. Sorry.
*/
.section .entry
PUBLIC_VAR (start)
PUBLIC_VAR (download_entry)
PUBLIC_VAR (__rtems_entry_point)
SYM(start):
SYM(download_entry):
SYM(__rtems_entry_point):
bl .startup
base_addr:
/*---------------------------------------------------------------------------
* Parameters from linker
*--------------------------------------------------------------------------*/
toc_pointer:
.long s.got
bss_length:
.long bss.size
bss_addr:
.long bss.start
stack_top:
.long stack.end
PUBLIC_VAR (text_addr)
text_addr:
.long text.start
PUBLIC_VAR (text_length)
text_length:
.long text.size
/*---------------------------------------------------------------------------
* Reset_entry.
*--------------------------------------------------------------------------*/
.startup:
/* Get start address, stack grows down from here... */
mflr r1
/* Assume Bank regs set up..., cache etc. */
bl bssclr
#if 0
.extern SYM(__vectors)
lis r2,__vectors@h /* set EVPR exc. vector prefix */
#else
lis r2,0
#endif
mtspr evpr,r2
/*-------------------------------------------------------------------
* C_setup.
*------------------------------------------------------------------*/
lwz r2,toc_pointer-base_addr(r1) /* set r2 to toc */
lwz r1,stack_top-base_addr(r1) /* set r1 to stack_top */
addi r1,r1,-56-4 /* start stack at text_addr - 56 */
addi r3,r0,0x0 /* clear r3 */
stw r3, 0(r1) /* Clear stack chain */
stw r3, 4(r1)
stw r3, 8(r1)
stw r3, 12(r1)
lis r5,environ@ha
la r5,environ@l(r5) /* environp */
li r4, 0 /* argv */
li r3, 0 /* argc */
.extern SYM (boot_card)
b SYM (boot_card) /* call the first C routine */
/*---------------------------------------------------------------------------
* bssclr.
*--------------------------------------------------------------------------*/
bssclr:
/*-------------------------------------------------------------------
* Data move finished, zero out bss.
*------------------------------------------------------------------*/
lwz r2,bss_addr-base_addr(r1) /* start of bss set by loader */
lwz r3,bss_length-base_addr(r1) /* bss length */
rlwinm. r3,r3,30,0x3FFFFFFF /* form length/4 */
beqlr /* no bss */
mtctr r3 /* set ctr reg */
xor r6,r6,r6 /* r6 = 0 */
clear_bss:
stswi r6,r2,0x4 /* store r6 */
addi r2,r2,0x4 /* update r2 */
bdnz clear_bss /* decrement counter and loop */
blr /* return */
.L_text_e:
.comm environ,4,4

View File

@@ -0,0 +1,123 @@
/* bsp.h
*
* This include file contains all GEN405 board IO definitions.
*
* derived from helas403/include/bsp.h:
* Id: bsp.h,v 1.4 2001/06/18 17:01:48 joel Exp
* Author: Thomas Doerfler <td@imd.m.isar.de>
* IMD Ingenieurbuero fuer Microcomputertechnik
*
* COPYRIGHT (c) 1998 by IMD
*
* Changes from IMD are covered by the original distributions terms.
* This file has been derived from the papyrus BSP.
*
* Author: Andrew Bray <andy@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/libbsp/no_cpu/no_bsp/include/bsp.h
*
* 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.
*
* $Id$
*
*/
#ifndef _BSP_H
#define _BSP_H
#ifdef __cplusplus
extern "C" {
#endif
#include <bspopts.h>
/*
* confdefs.h overrides for this BSP:
* - number of termios serial ports (defaults to 1)
* - Interrupt stack space is not minimum if defined.
*/
/* #define CONFIGURE_NUMBER_OF_TERMIOS_PORTS 2 */
#define CONFIGURE_INTERRUPT_STACK_MEMORY (16 * 1024)
#ifdef ASM
/* Definition of where to store registers in alignment handler */
#define ALIGN_REGS 0x0140
#else
#include <rtems.h>
#include <rtems/console.h>
#include <rtems/clockdrv.h>
#include <rtems/console.h>
#include <rtems/iosupp.h>
#include <rtems/rtems_bsdnet.h>
/* Constants */
extern uint32_t _HeapSize;
extern uint32_t _heap_start;
extern uint32_t _heap_end;
extern uint32_t _top_of_ram;
/* miscellaneous stuff assumed to exist */
extern rtems_configuration_table BSP_Configuration; /* owned by BSP */
extern rtems_cpu_table Cpu_table; /* owned by BSP */
/* Network Defines */
#if 1 /* EB/doe changes */
#define RTEMS_BSP_NETWORK_DRIVER_NAME "eth0"
#else
#include "xiltemac.h"
#define RTEMS_BSP_NETWORK_DRIVER_NAME XILTEMAC_DRIVER_PREFIX
#endif
extern xilTemac_driver_attach(struct rtems_bsdnet_ifconfig*, int );
#define RTEMS_BSP_NETWORK_DRIVER_ATTACH xilTemac_driver_attach
/*
* Device Driver Table Entries
*/
/*
* NOTE: Use the standard Console driver entry
*/
/*
* NOTE: Use the standard Clock driver entry
*/
/* functions */
rtems_isr_entry set_vector( /* returns old vector */
rtems_isr_entry handler, /* isr routine */
rtems_vector_number vector, /* vector number */
int type /* RTEMS or RAW intr */
);
#endif /* ASM */
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,33 @@
/* include/bspopts.h.in. Generated from configure.ac by autoheader. */
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* If defined, then the PowerPC specific code in RTEMS will use some of the
special purpose registers to slightly optimize interrupt response time. The
use of these registers can conflict with other tools like debuggers. */
#undef PPC_USE_SPRG
/* This defines the base address of the exception table. NOTE: Vectors are
actually at 0xFFF00000 but file starts at offset. */
#undef PPC_VECTOR_FILE_BASE
/* This defines the location of the hardware specific "xparameters.h" file. in
the file system. Specify an absolute path. Don't forget the double quotes
*/
#undef RTEMS_XPARAMETERS_H
/* Defines path to Xilinx XPS PPC libraries. */
#undef RTEMS_XPPC_BASE

View File

@@ -0,0 +1,133 @@
/* coverhd.h
*
* This include file has defines to represent the overhead associated
* with calling a particular directive from C. These are used in the
* Timing Test Suite to ignore the overhead required to pass arguments
* to directives. On some CPUs and/or target boards, this overhead
* is significant and makes it difficult to distinguish internal
* RTEMS execution time from that used to call the directive.
* This file should be updated after running the C overhead timing
* test. Once this update has been performed, the RTEMS Time Test
* Suite should be rebuilt to account for these overhead times in the
* timing results.
*
* NOTE: If these are all zero, then the times reported include
* all calling overhead including passing of arguments.
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* $Id$
*/
/*
* Updated for a 25MHz Papyrus by Andrew Bray <andy@i-cubed.co.uk>
*
* Units are 100ns.
*
* These numbers are of questionable use, as they are developed by calling
* the routine many times, thus getting its entry veneer into the (small)
* cache on the 403GA. This in general is not true of the RTEMS timing
* tests, which usually call a routine only once, thus having no cache loaded
* advantage.
*
* Whether the directive times are useful after deducting the function call
* overhead is also questionable. The user is more interested generally
* in the total cost of a directive, not the cost if the procedure call
* is inlined! (In general this is not true).
*
* Andrew Bray 18/08/1995
*
*/
#ifndef __COVERHD_h
#define __COVERHD_h
#ifdef __cplusplus
extern "C" {
#endif
#define CALLING_OVERHEAD_INITIALIZE_EXECUTIVE 1
#define CALLING_OVERHEAD_SHUTDOWN_EXECUTIVE 1
#define CALLING_OVERHEAD_TASK_CREATE 3
#define CALLING_OVERHEAD_TASK_IDENT 1
#define CALLING_OVERHEAD_TASK_START 1
#define CALLING_OVERHEAD_TASK_RESTART 1
#define CALLING_OVERHEAD_TASK_DELETE 1
#define CALLING_OVERHEAD_TASK_SUSPEND 1
#define CALLING_OVERHEAD_TASK_RESUME 1
#define CALLING_OVERHEAD_TASK_SET_PRIORITY 1
#define CALLING_OVERHEAD_TASK_MODE 1
#define CALLING_OVERHEAD_TASK_GET_NOTE 1
#define CALLING_OVERHEAD_TASK_SET_NOTE 1
#define CALLING_OVERHEAD_TASK_WAKE_WHEN 4
#define CALLING_OVERHEAD_TASK_WAKE_AFTER 1
#define CALLING_OVERHEAD_INTERRUPT_CATCH 1
#define CALLING_OVERHEAD_CLOCK_GET 4
#define CALLING_OVERHEAD_CLOCK_SET 3
#define CALLING_OVERHEAD_CLOCK_TICK 1
#define CALLING_OVERHEAD_TIMER_CREATE 1
#define CALLING_OVERHEAD_TIMER_IDENT 1
#define CALLING_OVERHEAD_TIMER_DELETE 1
#define CALLING_OVERHEAD_TIMER_FIRE_AFTER 2
#define CALLING_OVERHEAD_TIMER_FIRE_WHEN 5
#define CALLING_OVERHEAD_TIMER_RESET 1
#define CALLING_OVERHEAD_TIMER_CANCEL 1
#define CALLING_OVERHEAD_SEMAPHORE_CREATE 2
#define CALLING_OVERHEAD_SEMAPHORE_IDENT 1
#define CALLING_OVERHEAD_SEMAPHORE_DELETE 1
#define CALLING_OVERHEAD_SEMAPHORE_OBTAIN 1
#define CALLING_OVERHEAD_SEMAPHORE_RELEASE 1
#define CALLING_OVERHEAD_MESSAGE_QUEUE_CREATE 2
#define CALLING_OVERHEAD_MESSAGE_QUEUE_IDENT 1
#define CALLING_OVERHEAD_MESSAGE_QUEUE_DELETE 1
#define CALLING_OVERHEAD_MESSAGE_QUEUE_SEND 1
#define CALLING_OVERHEAD_MESSAGE_QUEUE_URGENT 1
#define CALLING_OVERHEAD_MESSAGE_QUEUE_BROADCAST 1
#define CALLING_OVERHEAD_MESSAGE_QUEUE_RECEIVE 2
#define CALLING_OVERHEAD_MESSAGE_QUEUE_FLUSH 1
#define CALLING_OVERHEAD_EVENT_SEND 1
#define CALLING_OVERHEAD_EVENT_RECEIVE 2
#define CALLING_OVERHEAD_SIGNAL_CATCH 1
#define CALLING_OVERHEAD_SIGNAL_SEND 1
#define CALLING_OVERHEAD_PARTITION_CREATE 3
#define CALLING_OVERHEAD_PARTITION_IDENT 1
#define CALLING_OVERHEAD_PARTITION_DELETE 1
#define CALLING_OVERHEAD_PARTITION_GET_BUFFER 1
#define CALLING_OVERHEAD_PARTITION_RETURN_BUFFER 1
#define CALLING_OVERHEAD_REGION_CREATE 3
#define CALLING_OVERHEAD_REGION_IDENT 1
#define CALLING_OVERHEAD_REGION_DELETE 1
#define CALLING_OVERHEAD_REGION_GET_SEGMENT 2
#define CALLING_OVERHEAD_REGION_RETURN_SEGMENT 1
#define CALLING_OVERHEAD_PORT_CREATE 2
#define CALLING_OVERHEAD_PORT_IDENT 1
#define CALLING_OVERHEAD_PORT_DELETE 1
#define CALLING_OVERHEAD_PORT_EXTERNAL_TO_INTERNAL 1
#define CALLING_OVERHEAD_PORT_INTERNAL_TO_EXTERNAL 2
#define CALLING_OVERHEAD_IO_INITIALIZE 2
#define CALLING_OVERHEAD_IO_OPEN 2
#define CALLING_OVERHEAD_IO_CLOSE 2
#define CALLING_OVERHEAD_IO_READ 2
#define CALLING_OVERHEAD_IO_WRITE 2
#define CALLING_OVERHEAD_IO_CONTROL 2
#define CALLING_OVERHEAD_FATAL_ERROR_OCCURRED 1
#define CALLING_OVERHEAD_RATE_MONOTONIC_CREATE 1
#define CALLING_OVERHEAD_RATE_MONOTONIC_IDENT 1
#define CALLING_OVERHEAD_RATE_MONOTONIC_DELETE 1
#define CALLING_OVERHEAD_RATE_MONOTONIC_CANCEL 1
#define CALLING_OVERHEAD_RATE_MONOTONIC_PERIOD 1
#define CALLING_OVERHEAD_MULTIPROCESSING_ANNOUNCE 1
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,90 @@
/* opbintctrl.h
*
* This file contains definitions and declarations for the
* Xilinx Off Processor Bus (OPB) Interrupt Controller
*
* Author: Keith Robertson <kjrobert@alumni.uwaterloo.ca>
* COPYRIGHT (c) 2005 by Linn Products Ltd, Scotland
*
* 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.
*/
#ifndef _INCLUDE_OPBINTCTRL_H
#define _INCLUDE_OPBINTCTRL_H
#include <rtems.h>
#include <rtems/system.h>
#include <rtems/score/isr.h>
#include <rtems/irq.h>
#include <bspopts.h>
#include RTEMS_XPARAMETERS_H
#define USE_GREG_INTERRUPTS
#ifdef __cplusplus
extern "C" {
#endif
/* extern XIntc InterruptController;
*/
/* Maximum number of IRQs. Defined in vhdl model */
#define OPB_INTC_IRQ_MAX XPAR_INTC_MAX_NUM_INTR_INPUTS
/* Width of INTC registers. Defined in vhdl model */
#define OPB_INTC_REGISTER_WIDTH 32
/* Base Register address and register offsets. Defined in vhdl model */
#define OPB_INTC_BASE XPAR_INTC_BASEADDR
/* Interrupt Status Register */
#define OPB_INTC_ISR 0x0
/* Interrupt Pending Register (ISR && IER) */
#define OPB_INTC_IPR 0x4
/* Interrupt Enable Register */
#define OPB_INTC_IER 0x8
/* Interrupt Acknowledge Register */
#define OPB_INTC_IAR 0xC
/* Set Interrupt Enable (same as read/mask/write to IER) */
#define OPB_INTC_SIE 0x10
/* Clear Interrupt Enable (same as read/mask/write to IER) */
#define OPB_INTC_CIE 0x14
/* Interrupt Vector Address (highest priority vector number from IPR) */
#define OPB_INTC_IVR 0x18
/* Master Enable Register */
#define OPB_INTC_MER 0x1C
/* Master Enable Register: Hardware Interrupt Enable */
#define OPB_INTC_MER_HIE 0x2
/* Master Enable Register: Master IRQ Enable */
#define OPB_INTC_MER_ME 0x1
/*
* make this fast: is this a opbintc interrupt?
*/
void BSP_irq_enable_at_opbintc (rtems_irq_number irqnum);
void BSP_irq_disable_at_opbintc (rtems_irq_number irqnum);
/*
* IRQ Handler: this is called from the primary exception dispatcher
*/
void BSP_irq_handle_at_opbintc(void);
/*
* activate the interrupt controller
*/
rtems_status_code opb_intc_init(void);
#ifdef __cplusplus
}
#endif
#endif /* _INCLUDE_OPBINTCTRL_H */

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
/*
* Stuff for Time Test 27
*/
#define MUST_WAIT_FOR_INTERRUPT 0
#define Install_tm27_vector( handler ) set_vector( (handler), PPC_IRQ_SCALL, 1 )
#define Cause_tm27_intr() asm volatile ("sc")
#define Clear_tm27_intr() /* empty */
#define Lower_tm27_intr() /* empty */
#endif

View File

@@ -0,0 +1,193 @@
/*******************************************************************
*
* CAUTION: This file is automatically generated by libgen.
* Version: Xilinx EDK 8.2.02 EDK_Im_Sp2.4
* DO NOT EDIT.
*
* Copyright (c) 2005 Xilinx, Inc. All rights reserved.
*
* Description: Driver parameters
*
*******************************************************************/
#define STDIN_BASEADDRESS 0x40600000
#define STDOUT_BASEADDRESS 0x40600000
/******************************************************************/
/* Definitions for driver PLBARB */
#define XPAR_XPLBARB_NUM_INSTANCES 1
/* Definitions for peripheral PLB */
#define XPAR_PLB_BASEADDR 0x00000000
#define XPAR_PLB_HIGHADDR 0x00000000
#define XPAR_PLB_DEVICE_ID 0
#define XPAR_PLB_PLB_NUM_MASTERS 3
/******************************************************************/
/* Definitions for driver OPBARB */
#define XPAR_XOPBARB_NUM_INSTANCES 1
/* Definitions for peripheral OPB */
#define XPAR_OPB_BASEADDR 0xFFFFFFFF
#define XPAR_OPB_HIGHADDR 0x00000000
#define XPAR_OPB_DEVICE_ID 0
#define XPAR_OPB_NUM_MASTERS 1
/******************************************************************/
/* Definitions for driver UARTLITE */
#define XPAR_XUARTLITE_NUM_INSTANCES 1
/* Definitions for peripheral CONSOLE */
#define XPAR_CONSOLE_BASEADDR 0x40600000
#define XPAR_CONSOLE_HIGHADDR 0x4060FFFF
#define XPAR_CONSOLE_DEVICE_ID 0
#define XPAR_CONSOLE_BAUDRATE 115200
#define XPAR_CONSOLE_USE_PARITY 0
#define XPAR_CONSOLE_ODD_PARITY 0
#define XPAR_CONSOLE_DATA_BITS 8
/******************************************************************/
/* Definitions for driver GPIO */
#define XPAR_XGPIO_NUM_INSTANCES 3
/* Definitions for peripheral LEDS */
#define XPAR_LEDS_BASEADDR 0x40000000
#define XPAR_LEDS_HIGHADDR 0x4000FFFF
#define XPAR_LEDS_DEVICE_ID 0
#define XPAR_LEDS_INTERRUPT_PRESENT 0
#define XPAR_LEDS_IS_DUAL 0
/* Definitions for peripheral PBLEDS */
#define XPAR_PBLEDS_BASEADDR 0x40020000
#define XPAR_PBLEDS_HIGHADDR 0x4002FFFF
#define XPAR_PBLEDS_DEVICE_ID 1
#define XPAR_PBLEDS_INTERRUPT_PRESENT 0
#define XPAR_PBLEDS_IS_DUAL 0
/* Definitions for peripheral PUSHBUTTONS */
#define XPAR_PUSHBUTTONS_BASEADDR 0x40040000
#define XPAR_PUSHBUTTONS_HIGHADDR 0x4004FFFF
#define XPAR_PUSHBUTTONS_DEVICE_ID 2
#define XPAR_PUSHBUTTONS_INTERRUPT_PRESENT 1
#define XPAR_PUSHBUTTONS_IS_DUAL 0
/******************************************************************/
/* Definitions for driver TMRCTR */
#define XPAR_XTMRCTR_NUM_INSTANCES 1
/* Definitions for peripheral OPBTIMER */
#define XPAR_OPBTIMER_BASEADDR 0x41C00000
#define XPAR_OPBTIMER_HIGHADDR 0x41C0FFFF
#define XPAR_OPBTIMER_DEVICE_ID 0
/******************************************************************/
#define XPAR_INTC_MAX_NUM_INTR_INPUTS 3
#define XPAR_XINTC_HAS_IPR 1
#define XPAR_XINTC_USE_DCR 0
/* Definitions for driver INTC */
#define XPAR_XINTC_NUM_INSTANCES 1
/* Definitions for peripheral INTC */
#define XPAR_INTC_BASEADDR 0x41200000
#define XPAR_INTC_HIGHADDR 0x4120FFFF
#define XPAR_INTC_DEVICE_ID 0
#define XPAR_INTC_KIND_OF_INTR 0x00000000
/******************************************************************/
#define XPAR_INTC_SINGLE_BASEADDR 0x41200000
#define XPAR_INTC_SINGLE_HIGHADDR 0x4120FFFF
#define XPAR_INTC_SINGLE_DEVICE_ID XPAR_INTC_DEVICE_ID
#define XPAR_OPBTIMER_INTERRUPT_MASK 0X000001
#define XPAR_INTC_OPBTIMER_INTERRUPT_INTR 0
#define XPAR_ETHERNET_IP2INTC_IRPT_MASK 0X000002
#define XPAR_INTC_ETHERNET_IP2INTC_IRPT_INTR 1
#define XPAR_PUSHBUTTONS_IP2INTC_IRPT_MASK 0X000004
#define XPAR_INTC_PUSHBUTTONS_IP2INTC_IRPT_INTR 2
/******************************************************************/
/* Definitions for driver DDR */
#define XPAR_XDDR_NUM_INSTANCES 1
/* Definitions for peripheral DDR_SDRAM_64MX32 */
#define XPAR_DDR_SDRAM_64MX32_ECC_BASEADDR 0xFFFFFFFF
#define XPAR_DDR_SDRAM_64MX32_ECC_HIGHADDR 0x00000000
#define XPAR_DDR_SDRAM_64MX32_DEVICE_ID 0
#define XPAR_DDR_SDRAM_64MX32_INCLUDE_ECC_INTR 0
/******************************************************************/
/* Definitions for peripheral DDR_SDRAM_64MX32 */
#define XPAR_DDR_SDRAM_64MX32_MEM0_BASEADDR 0x00000000
#define XPAR_DDR_SDRAM_64MX32_MEM0_HIGHADDR 0x03FFFFFF
/******************************************************************/
/* Definitions for peripheral HARD_TEMAC_0 */
#define XPAR_HARD_TEMAC_0_PHY_TYPE 1
/******************************************************************/
/* Definitions for driver TEMAC */
#define XPAR_XTEMAC_NUM_INSTANCES 1
/* Definitions for peripheral ETHERNET */
#define XPAR_ETHERNET_DEVICE_ID 0
#define XPAR_ETHERNET_BASEADDR 0x81200000
#define XPAR_ETHERNET_HIGHADDR 0x8120FFFF
#define XPAR_ETHERNET_RXFIFO_DEPTH 32768
#define XPAR_ETHERNET_TXFIFO_DEPTH 32768
#define XPAR_ETHERNET_MAC_FIFO_DEPTH 64
#define XPAR_ETHERNET_DMA_TYPE 1
#define XPAR_ETHERNET_TX_DRE_TYPE 0
#define XPAR_ETHERNET_RX_DRE_TYPE 0
#define XPAR_ETHERNET_INCLUDE_TX_CSUM 0
#define XPAR_ETHERNET_INCLUDE_RX_CSUM 0
/******************************************************************/
/* Definitions for peripheral FLASH */
#define XPAR_FLASH_NUM_BANKS_MEM 1
/******************************************************************/
/* Definitions for peripheral FLASH */
#define XPAR_FLASH_MEM0_BASEADDR 0x06000000
#define XPAR_FLASH_MEM0_HIGHADDR 0x067FFFFF
/******************************************************************/
/* Definitions for peripheral PLB_BRAM_IF_CNTLR_1 */
#define XPAR_PLB_BRAM_IF_CNTLR_1_BASEADDR 0xffff8000
#define XPAR_PLB_BRAM_IF_CNTLR_1_HIGHADDR 0xffffffff
/******************************************************************/
#define XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ 300000000
/******************************************************************/

View File

@@ -0,0 +1,99 @@
/*===============================================================*\
| Project: RTEMS virtex BSP |
+-----------------------------------------------------------------+
| Copyright (c) 2007 |
| Embedded Brains GmbH |
| Obere Lagerstr. 30 |
| D-82178 Puchheim |
| Germany |
| rtems@embedded-brains.de |
+-----------------------------------------------------------------+
| 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. |
| |
+-----------------------------------------------------------------+
| this file declares constants of the interrupt controller |
\*===============================================================*/
#ifndef VIRTEX_IRQ_IRQ_H
#define VIRTEX_IRQ_IRQ_H
#include <rtems/irq.h>
#include <bsp/opbintctrl.h>
/*
* the following definitions specify the indices used
* to interface the interrupt handler API
*/
/*
* Base index for the module specific irq handlers
*/
#define BSP_ASM_IRQ_VECTOR_BASE 0x0
#define BSP_OPBINTC_VECTOR_BASE BSP_ASM_IRQ_VECTOR_BASE
/*
* Peripheral IRQ handlers related definitions
*/
#define BSP_OPBINTC_PER_IRQ_NUMBER XPAR_INTC_MAX_NUM_INTR_INPUTS
#define BSP_OPBINTC_IRQ_LOWEST_OFFSET BSP_OPBINTC_VECTOR_BASE /* 0 */
#define BSP_OPBINTC_IRQ_MAX_OFFSET (BSP_OPBINTC_IRQ_LOWEST_OFFSET\
+BSP_OPBINTC_PER_IRQ_NUMBER-1)
#define BSP_IS_OPBINTC_IRQ(irqnum) \
(((irqnum) >= BSP_OPBINTC_IRQ_LOWEST_OFFSET) && \
((irqnum) <= BSP_OPBINTC_IRQ_MAX_OFFSET))
/*
* Processor IRQ handlers related definitions
*/
#define BSP_PROCESSOR_IRQ_NUMBER 3
#define BSP_PROCESSOR_IRQ_LOWEST_OFFSET (BSP_OPBINTC_IRQ_MAX_OFFSET+1)
#define BSP_PROCESSOR_IRQ_MAX_OFFSET (BSP_PROCESSOR_IRQ_LOWEST_OFFSET\
+BSP_PROCESSOR_IRQ_NUMBER-1)
#define BSP_IS_PROCESSOR_IRQ(irqnum) \
(((irqnum) >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET) && \
((irqnum) <= BSP_PROCESSOR_IRQ_MAX_OFFSET))
/*
* Summary
*/
#define BSP_IRQ_NUMBER (BSP_PROCESSOR_IRQ_MAX_OFFSET+1)
#define BSP_LOWEST_OFFSET BSP_OPBINTC_IRQ_LOWEST_OFFSET
#define BSP_MAX_OFFSET BSP_PROCESSOR_IRQ_MAX_OFFSET
#define BSP_IS_VALID_IRQ(irqnum) \
(BSP_IS_PROCESSOR_IRQ(irqnum) \
|| BSP_IS_OPBINTC_IRQ(irqnum))
#ifndef ASM
#ifdef __cplusplus
extern "C" {
#endif
/*
* index table for the module specific handlers, a few entries are only placeholders
*/
typedef enum {
BSP_OPBINTC_IRQ_FIRST = BSP_OPBINTC_IRQ_LOWEST_OFFSET,
/*
* Note: for this BSP, the peripheral names are derived
* from the Xilinx parameter file
*/
BSP_OPBINTC_IRQ_LAST = BSP_OPBINTC_IRQ_MAX_OFFSET,
BSP_EXT = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + 0,
BSP_PIT = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + 1,
BSP_CRIT = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + 2
} rtems_irq_symbolic_name;
#define BSP_OPBINTC_XPAR(xname) (BSP_OPBINTC_IRQ_LOWEST_OFFSET+xname)
extern rtems_irq_connect_data *BSP_rtems_irq_tbl;
void BSP_rtems_irq_mng_init(unsigned cpuId);
#ifdef __cplusplus
}
#endif
#endif /* ASM */
#endif /* VIRTEX_IRQ_IRQ_H */

View File

@@ -0,0 +1,421 @@
/*===============================================================*\
| Project: RTEMS virtex BSP |
+-----------------------------------------------------------------+
| Partially based on the code references which are named below. |
| Adaptions, modifications, enhancements and any recent parts of |
| the code are: |
| Copyright (c) 2007 |
| Embedded Brains GmbH |
| Obere Lagerstr. 30 |
| D-82178 Puchheim |
| Germany |
| rtems@embedded-brains.de |
+-----------------------------------------------------------------+
| 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. |
| |
+-----------------------------------------------------------------+
| this file contains the irq controller handler |
\*===============================================================*/
#include <libcpu/spr.h>
#include <bsp/irq.h>
#include <bsp.h>
#include <libcpu/raw_exception.h>
#include <rtems/bspIo.h>
#include <rtems/powerpc/powerpc.h>
#include <bsp/vectors.h>
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;
/***********************************************************
* dummy functions for on/off/isOn calls
* 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)
{
/*
* nothing to do
*/
}
void BSP_irq_nop_hdl(void *hdl)
{
/*
* nothing to do
*/
}
int BSP_irq_true_func(const rtems_irq_connect_data *unused)
{
/*
* nothing to do
*/
return TRUE;
}
/***********************************************************
* interrupt handler and its enable/disable functions
***********************************************************/
/***********************************************************
* functions to enable/disable/query external/critical interrupts
*/
void BSP_irqexc_on_fnc(rtems_irq_connect_data *conn_data)
{
uint32_t msr_value;
/*
* get current MSR value
*/
_CPU_MSR_GET(msr_value);
msr_value |= PPC_MSR_EE;
_CPU_MSR_SET(msr_value);
}
void BSP_irqexc_off_fnc(rtems_irq_connect_data *unused)
{
/*
* nothing to do
*/
}
/***********************************************************
* High level IRQ handler called from shared_raw_irq_code_entry
*/
void C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum)
{
/*
* Handle interrupt
*/
switch(excNum) {
#if 0
case ASM_DEC_VECTOR:
_CPU_MSR_GET(msr);
new_msr = msr | MSR_EE;
_CPU_MSR_SET(new_msr);
BSP_rtems_irq_tbl[BSP_DECREMENTER].hdl
(BSP_rtems_irq_tbl[BSP_DECREMENTER].handle);
_CPU_MSR_SET(msr);
break;
#endif
case ASM_EXT_VECTOR:
BSP_irq_handle_at_opbintc();
break;
case ASM_PIT_VECTOR:
BSP_rtems_irq_tbl[BSP_PIT].hdl
(BSP_rtems_irq_tbl[BSP_PIT].handle);
break;
#if 0 /* Critical interrupts not yet supported */
case ASM_CRIT_VECTOR:
break;
#endif
}
}
void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx)
{
/*
* Process pending signals that have not already been
* processed by _Thread_Displatch. This happens quite
* unfrequently : the ISR must have posted an action
* to the current running thread.
*/
if ( _Thread_Do_post_task_switch_extension ||
_Thread_Executing->do_post_task_switch_extension ) {
_Thread_Executing->do_post_task_switch_extension = FALSE;
_API_extensions_Run_postswitch();
}
}
/***********************************************************
* functions to set/get/remove interrupt handlers
***********************************************************/
int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
{
unsigned int level;
/*
* check for valid irq name
* if invalid, print error and return 0
*/
if (!BSP_IS_VALID_IRQ(irq->name)) {
printk("Invalid interrupt vector %d\n",irq->name);
return 0;
}
/*
* disable interrupts
*/
_CPU_ISR_Disable(level);
/*
* check, that default handler is installed now
*/
if (rtemsIrqTbl[irq->name].hdl != BSP_rtems_irq_config->defaultEntry.hdl) {
_CPU_ISR_Enable(level);
printk("IRQ vector %d already connected\n",irq->name);
return 0;
}
/*
* store new handler data
*/
rtemsIrqTbl[irq->name] = *irq;
/*
* enable irq at interrupt controller
*/
if (BSP_IS_OPBINTC_IRQ(irq->name)) {
BSP_irq_enable_at_opbintc(irq->name);
}
/*
* call "on" function to enable interrupt at device
*/
irq->on(irq);
/*
* reenable interrupts
*/
_CPU_ISR_Enable(level);
return 1;
}
int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq)
{
unsigned int level;
/*
* check for valid IRQ name
*/
if (!BSP_IS_VALID_IRQ(irq->name)) {
return 0;
}
_CPU_ISR_Disable(level);
/*
* return current IRQ entry
*/
*irq = rtemsIrqTbl[irq->name];
_CPU_ISR_Enable(level);
return 1;
}
int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
{
unsigned int level;
/*
* check for valid IRQ name
*/
if (!BSP_IS_VALID_IRQ(irq->name)) {
return 0;
}
_CPU_ISR_Disable(level);
/*
* check, that specified handler is really connected now
*/
if (rtemsIrqTbl[irq->name].hdl != irq->hdl) {
_CPU_ISR_Enable(level);
return 0;
}
/*
* disable interrupt at interrupt controller
*/
if (BSP_IS_OPBINTC_IRQ(irq->name)) {
BSP_irq_disable_at_opbintc(irq->name);
}
/*
* disable interrupt at source
*/
irq->off(irq);
/*
* restore default interrupt handler
*/
rtemsIrqTbl[irq->name] = BSP_rtems_irq_config->defaultEntry;
/*
* reenable interrupts
*/
_CPU_ISR_Enable(level);
return 1;
}
/***********************************************************
* functions to set/get the basic interrupt management setup
***********************************************************/
/*
* (Re) get info on current RTEMS interrupt management.
*/
int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** ret_ptr)
{
*ret_ptr = BSP_rtems_irq_config;
return 0;
}
/*
* set management stuff
*/
int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
{
int i;
unsigned int level;
_CPU_ISR_Disable(level);
/*
* store given configuration
*/
BSP_rtems_irq_config = config;
BSP_rtems_irq_tbl = BSP_rtems_irq_config->irqHdlTbl;
/*
* enable any non-empty IRQ entries at OPBINTC
*/
for (i = BSP_OPBINTC_IRQ_LOWEST_OFFSET;
i <= BSP_OPBINTC_IRQ_MAX_OFFSET;
i++) {
if (BSP_rtems_irq_tbl[i].hdl != config->defaultEntry.hdl) {
BSP_irq_enable_at_opbintc(i);
BSP_rtems_irq_tbl[i].on((&BSP_rtems_irq_tbl[i]));
}
else {
BSP_rtems_irq_tbl[i].off(&(BSP_rtems_irq_tbl[i]));
BSP_irq_disable_at_opbintc(i);
}
}
/*
* store any irq-like processor exceptions
*/
for (i = BSP_PROCESSOR_IRQ_LOWEST_OFFSET;
i < BSP_PROCESSOR_IRQ_MAX_OFFSET;
i++) {
if (BSP_rtems_irq_tbl[i].hdl != config->defaultEntry.hdl) {
if (BSP_rtems_irq_tbl[i].on != NULL) {
BSP_rtems_irq_tbl[i].on
(&(BSP_rtems_irq_tbl[i]));
}
}
else {
if (BSP_rtems_irq_tbl[i].off != NULL) {
BSP_rtems_irq_tbl[i].off
(&(BSP_rtems_irq_tbl[i]));
}
}
}
_CPU_ISR_Enable(level);
return 1;
}
/**********************************************
* list of exception vectors to tap for interrupt handlers
*/
static rtems_raw_except_connect_data BSP_vec_desc[] = {
#if 0 /* ppc405 has no decrementer */
{ASM_DEC_VECTOR,
{ASM_DEC_VECTOR,
decrementer_exception_vector_prolog_code,
(size_t)decrementer_exception_vector_prolog_code_size
},
exception_nop_enable,
exception_nop_enable,
exception_always_enabled
},
#endif
{ASM_EXT_VECTOR,
{ASM_EXT_VECTOR,
external_exception_vector_prolog_code,
(size_t)&external_exception_vector_prolog_code_size
},
exception_nop_enable,
exception_nop_enable,
exception_always_enabled
},
{ASM_PIT_VECTOR,
{ASM_PIT_VECTOR,
pit_exception_vector_prolog_code,
(size_t)&pit_exception_vector_prolog_code_size
},
exception_nop_enable,
exception_nop_enable,
exception_always_enabled
}
#if 0 /* Critical interrupts not yet supported */
,{ASM_CRIT_VECTOR,
{ASM_CRIT_VECTOR,
critical_exception_vector_prolog_code,
critical_exception_vector_prolog_code_size
}
BSP_irq_nop_func,
BSP_irq_nop_func,
BSP_irq_true_func
}
#endif
};
/*
* dummy for an empty IRQ handler entry
*/
static rtems_irq_connect_data emptyIrq = {
0, /* Irq Name */
BSP_irq_nop_hdl, /* handler function */
NULL, /* handle passed to handler */
BSP_irq_nop_func, /* on function */
BSP_irq_nop_func, /* off function */
BSP_irq_true_func /* isOn function */
};
static rtems_irq_global_settings initialConfig = {
BSP_IRQ_NUMBER, /* irqNb */
{ 0, /* Irq Name */
BSP_irq_nop_hdl, /* handler function */
NULL, /* handle passed to handler */
BSP_irq_nop_func, /* on function */
BSP_irq_nop_func, /* off function */
BSP_irq_true_func /* isOn function */
}, /* emptyIrq */
rtemsIrqTbl, /* irqHdlTbl */
0, /* irqBase */
NULL /* irqPrioTbl */
};
void BSP_rtems_irq_mng_init(unsigned cpuId)
{
int i;
/*
* connect all exception vectors needed
*/
for (i = 0;
i < (sizeof(BSP_vec_desc) /
sizeof(BSP_vec_desc[0]));
i++) {
if (!ppc_set_exception (&BSP_vec_desc[i])) {
BSP_panic("Unable to initialize RTEMS raw exception\n");
}
}
/*
* setup interrupt handlers table
*/
for (i = 0;
i < BSP_IRQ_NUMBER;
i++) {
rtemsIrqTbl[i] = emptyIrq;
rtemsIrqTbl[i].name = i;
}
/*
* init interrupt controller
*/
opb_intc_init();
/*
* initialize interrupt management
*/
if (!BSP_rtems_irq_mngt_set(&initialConfig)) {
BSP_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
}
}

View File

@@ -0,0 +1,966 @@
/*
* Driver for Xilinx plb temac v3.00a
*
* Author: Keith Robertson <kjrobert@alumni.uwaterloo.ca>
* Copyright (c) 2007 Linn Products Ltd, Scotland.
*
* 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.
*
*/
#define PPC_HAS_CLASSIC_EXCEPTIONS FALSE
#ifndef __INSIDE_RTEMS_BSD_TCPIP_STACK__
#define __INSIDE_RTEMS_BSD_TCPIP_STACK__
#endif
#ifndef __BSD_VISIBLE
#define __BSD_VISIBLE
#endif
#include <rtems.h>
#include <rtems/rtems_bsdnet.h>
#include <sys/param.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <xiltemac.h>
#include <rtems/irq.h>
/* Reading/Writing memory mapped i/o */
#define IN32(aPtr) ((uint32_t)( *((volatile uint32_t *)(aPtr))) )
#define OUT32(aPtr, aValue) (*((volatile uint32_t *)(aPtr)) = (uint32_t)aValue)
#define NUM_XILTEMAC_UNITS 2
extern void printk(char*, ...);
/* Why isn't this defined in stdio.h like it's supposed to be? */
extern int snprintf(char*, size_t, const char*, ...);
void xilTemacInit( void *voidptr );
void xilTemacReset(struct ifnet *ifp);
void xilTemacStop(struct ifnet *ifp);
void xilTemacSend(struct ifnet *ifp);
void xilTemacStart(struct ifnet *ifp);
void xilTemacSetMacAddress(struct ifnet *ifp, unsigned char* aAddr);
void xilTemacPrintStats(struct ifnet *ifp);
void xilTemacRxThread( void *ignore );
void xilTemacTxThread( void *ignore );
static struct XilTemac gXilTemac[ NUM_XILTEMAC_UNITS ];
static rtems_id gXilRxThread = 0;
static rtems_id gXilTxThread = 0;
/*
** Events, one per unit. The event is sent to the rx task from the isr
** or from the stack to the tx task whenever a unit needs service. The
** rx/tx tasks identify the requesting unit(s) by their particular
** events so only requesting units are serviced.
*/
static rtems_event_set gUnitSignals[ NUM_XILTEMAC_UNITS ]= { RTEMS_EVENT_1,
RTEMS_EVENT_2 };
uint32_t xilTemacTxFifoVacancyBytes(uint32_t aBaseAddr)
{
uint32_t ipisr = IN32(aBaseAddr + XTE_IPISR_OFFSET);
uint32_t bytes = 0;
if(ipisr & XTE_IPXR_XMIT_LFIFO_FULL_MASK) {
/* If there's no room in the transmit length fifo, then any room in the
* data fifo is irrelevant, return 0 */
} else {
bytes = IN32(aBaseAddr + XTE_PFIFO_TX_VACANCY_OFFSET);
bytes &= XTE_PFIFO_COUNT_MASK;
bytes *= 8;
}
return bytes;
}
void xilTemacFifoRead64(uint32_t aBaseAddr, uint32_t* aBuf, uint32_t aBytes)
{
uint32_t numqwords = aBytes / 8;
uint32_t xtrabytes = aBytes % 8;
uint32_t i;
for(i = 0; i < numqwords; i++)
{
aBuf[ (i*2) ] = IN32(aBaseAddr + XTE_PFIFO_RX_DATA_OFFSET);
aBuf[ (i*2)+1 ] = IN32(aBaseAddr + XTE_PFIFO_RX_DATA_OFFSET + 4);
}
/* If there was a non qword sized read */
if( xtrabytes != 0 )
{
uint32_t lastdwordMS = IN32(aBaseAddr + XTE_PFIFO_RX_DATA_OFFSET);
uint32_t lastdwordLS = IN32(aBaseAddr + XTE_PFIFO_RX_DATA_OFFSET + 4);
uint8_t* finalbytes = (uint8_t *)&aBuf[ (numqwords*2) ];
uint8_t* ptr8;
int32_t offset = 0;
ptr8 = (uint8_t *)&lastdwordMS;
if( xtrabytes >= 4 )
{
finalbytes[ offset++ ] = ptr8[0];
finalbytes[ offset++ ] = ptr8[1];
finalbytes[ offset++ ] = ptr8[2];
finalbytes[ offset++ ] = ptr8[3];
xtrabytes -= 4;
ptr8 = (uint8_t *)&lastdwordLS;
}
if( xtrabytes == 1 )
{
finalbytes[ offset++ ] = ptr8[0];
}
else if ( xtrabytes == 2 )
{
finalbytes[ offset++ ] = ptr8[0];
finalbytes[ offset++ ] = ptr8[1];
}
else if ( xtrabytes == 3 )
{
finalbytes[ offset++ ] = ptr8[0];
finalbytes[ offset++ ] = ptr8[1];
finalbytes[ offset++ ] = ptr8[2];
}
}
}
void xilTemacFifoWrite64(uint32_t aBaseAddr, uint32_t* aBuf, uint32_t aBytes)
{
uint32_t numqwords = aBytes / 8;
uint32_t xtrabytes = aBytes % 8;
uint32_t i;
for(i = 0; i < numqwords; i++ ) {
OUT32(aBaseAddr + XTE_PFIFO_TX_DATA_OFFSET , aBuf[ (i*2) ]);
OUT32(aBaseAddr + XTE_PFIFO_TX_DATA_OFFSET + 4, aBuf[ (i*2)+1 ]);
}
/* If there was a non word sized write */
if( xtrabytes != 0 ) {
uint32_t lastdwordMS = 0;
uint32_t lastdwordLS = 0;
uint8_t* finalbytes = (uint8_t *)&aBuf[ (numqwords*2) ];
uint8_t* ptr8;
int32_t offset = 0;
ptr8 = (uint8_t *)&lastdwordMS;
if( xtrabytes >= 4 ) {
ptr8[0] = finalbytes[ offset++ ];
ptr8[1] = finalbytes[ offset++ ];
ptr8[2] = finalbytes[ offset++ ];
ptr8[3] = finalbytes[ offset++ ];
xtrabytes -= 4;
ptr8 = (uint8_t *)&lastdwordLS;
}
if( xtrabytes == 1 ) {
ptr8[0] = finalbytes[ offset++ ];
}
else if ( xtrabytes == 2 ) {
ptr8[0] = finalbytes[ offset++ ];
ptr8[1] = finalbytes[ offset++ ];
}
else if ( xtrabytes == 3 ) {
ptr8[0] = finalbytes[ offset++ ];
ptr8[1] = finalbytes[ offset++ ];
ptr8[2] = finalbytes[ offset++ ];
}
OUT32(aBaseAddr + XTE_PFIFO_TX_DATA_OFFSET, lastdwordMS);
OUT32(aBaseAddr + XTE_PFIFO_TX_DATA_OFFSET + 4, lastdwordLS);
}
}
void xilTemacStop(struct ifnet *ifp)
{
struct XilTemac* xilTemac = ifp->if_softc;
uint32_t base = xilTemac->iAddr;
/* Disable ipif interrupts */
OUT32(base + XTE_DGIE_OFFSET, 0);
/* Disable the receiver */
uint32_t rxc1 = IN32(base + XTE_ERXC1_OFFSET);
rxc1 &= ~XTE_ERXC1_RXEN_MASK;
OUT32(base + XTE_ERXC1_OFFSET, rxc1);
/* If receiver was receiving a packet when we disabled it, it will be
* rejected, clear appropriate status bit */
uint32_t ipisr = IN32(base + XTE_IPISR_OFFSET);
if( ipisr & XTE_IPXR_RECV_REJECT_MASK ) {
OUT32(base + XTE_IPISR_OFFSET, XTE_IPXR_RECV_REJECT_MASK);
}
#if PPC_HAS_CLASSIC_EXCEPTIONS
if( xilTemac->iOldHandler )
{
opb_intc_set_vector( xilTemac->iOldHandler, xilTemac->iIsrVector, NULL );
xilTemac->iOldHandler = 0;
}
#else
if( xilTemac->iOldHandler.name != 0)
{
BSP_install_rtems_irq_handler (&xilTemac->iOldHandler);
}
#endif
ifp->if_flags &= ~IFF_RUNNING;
}
void xilTemacStart(struct ifnet *ifp)
{
if( (ifp->if_flags & IFF_RUNNING) == 0 )
{
struct XilTemac* xilTemac = ifp->if_softc;
uint32_t base = xilTemac->iAddr;
/* Reset plb temac */
OUT32(base + XTE_DSR_OFFSET, XTE_DSR_RESET_MASK);
/* Don't have usleep on rtems 4.6
usleep(1);
*/
/* @ fastest ppc clock of 500 MHz = 2ns clk */
uint32_t i = 0;
for( i = 0; i < 1 * 500; i++) {
}
/* Reset hard temac */
OUT32(base + XTE_CR_OFFSET, XTE_CR_HTRST_MASK);
/* Don't have usleep on rtems 4.6
usleep(4);
*/
for( i = 0; i < 4 * 500; i++) {
}
/* Disable the receiver -- no need to disable xmit as we control that ;) */
uint32_t rxc1 = IN32(base + XTE_ERXC1_OFFSET);
rxc1 &= ~XTE_ERXC1_RXEN_MASK;
OUT32(base + XTE_ERXC1_OFFSET, rxc1);
/* If receiver was receiving a packet when we disabled it, it will be
* rejected, clear appropriate status bit */
uint32_t ipisr = IN32(base + XTE_IPISR_OFFSET);
if( ipisr & XTE_IPXR_RECV_REJECT_MASK ) {
OUT32(base + XTE_IPISR_OFFSET, XTE_IPXR_RECV_REJECT_MASK);
}
/* Setup IPIF interrupt enables */
uint32_t dier = XTE_DXR_CORE_MASK | XTE_DXR_DPTO_MASK | XTE_DXR_TERR_MASK;
dier |= XTE_DXR_RECV_FIFO_MASK | XTE_DXR_SEND_FIFO_MASK;
OUT32(base + XTE_DIER_OFFSET, dier);
/* Set the mac address */
xilTemacSetMacAddress( ifp, xilTemac->iArpcom.ac_enaddr);
/* Set the link speed */
uint32_t emcfg = IN32(base + XTE_ECFG_OFFSET);
printk("xiltemacStart, default linkspeed: %08x\n", emcfg);
emcfg |= XTE_ECFG_LINKSPD_100;
OUT32(base + XTE_ECFG_OFFSET, emcfg);
/* Set phy divisor and enable mdio. For a plb bus freq of 150MHz (the
maximum as of Virtex4 Fx), a divisor of 29 gives a mdio clk freq of
2.5MHz (see Xilinx docs for equation), the maximum in the phy standard.
For slower plb frequencies, slower mkdio clks will result. They may not
be optimal, but they should work. */
uint32_t divisor = 29;
OUT32(base + XTE_EMC_OFFSET, divisor | XTE_EMC_MDIO_MASK);
#if PPC_HAS_CLASSIC_EXCEPTIONS /* old connect code */
/* Connect isr vector */
rtems_status_code sc;
extern rtems_isr xilTemacIsr( rtems_vector_number aVector );
sc = opb_intc_set_vector( xilTemacIsr, xilTemac->iIsrVector, &xilTemac->iOldHandler );
if( sc != RTEMS_SUCCESSFUL )
{
xilTemac->iOldHandler = 0;
printk("%s: Could not set interrupt vector for interface '%s' opb_intc_set_vector ret: %d\n", DRIVER_PREFIX, xilTemac->iUnitName, sc );
assert(0);
}
#else
{
extern rtems_isr xilTemacIsr( void *handle );
extern void xilTemacIsrOn(const rtems_irq_connect_data *);
extern void xilTemacIsrOff(const rtems_irq_connect_data *);
extern int xilTemacIsrIsOn(const rtems_irq_connect_data *);
rtems_irq_connect_data IrqConnData;
/*
*get old irq handler
*/
xilTemac->iOldHandler.name = xilTemac->iIsrVector;
if (!BSP_get_current_rtems_irq_handler (&xilTemac->iOldHandler)) {
xilTemac->iOldHandler.name = 0;
printk("%s: Unable to detect previous Irq handler\n",DRIVER_PREFIX);
rtems_fatal_error_occurred(1);
}
IrqConnData.on = xilTemacIsrOn;
IrqConnData.off = xilTemacIsrOff;
IrqConnData.isOn = xilTemacIsrIsOn;
IrqConnData.name = xilTemac->iIsrVector;
IrqConnData.hdl = xilTemacIsr;
IrqConnData.handle = xilTemac;
if (!BSP_install_rtems_irq_handler (&IrqConnData)) {
printk("%s: Unable to connect Irq handler\n",DRIVER_PREFIX);
rtems_fatal_error_occurred(1);
}
}
#endif
/* Enable promiscuous mode -- The temac only supports full duplex, which
means we're plugged into a switch. Thus promiscuous mode simply means
we get all multicast addresses*/
OUT32(base + XTE_EAFM_OFFSET, XTE_EAFM_EPPRM_MASK);
/* Setup and enable receiver */
rxc1 = XTE_ERXC1_RXFCS_MASK | XTE_ERXC1_RXEN_MASK | XTE_ERXC1_RXVLAN_MASK;
OUT32(base + XTE_ERXC1_OFFSET, rxc1);
/* Setup and enable transmitter */
uint32_t txc = XTE_ETXC_TXEN_MASK | XTE_ETXC_TXVLAN_MASK;
OUT32(base + XTE_ETXC_OFFSET, txc);
/* Enable interrupts for temac */
uint32_t ipier = IN32(base + XTE_IPIER_OFFSET);
ipier |= (XTE_IPXR_XMIT_ERROR_MASK);
ipier |= (XTE_IPXR_RECV_ERROR_MASK | XTE_IPXR_RECV_DONE_MASK);
ipier |= (XTE_IPXR_AUTO_NEG_MASK);
OUT32(base + XTE_IPIER_OFFSET, ipier);
printk("%s: xiltemacStart, ipier: %08x\n",DRIVER_PREFIX, ipier);
/* Enable device global interrutps */
OUT32(base + XTE_DGIE_OFFSET, XTE_DGIE_ENABLE_MASK);
ifp->if_flags |= IFF_RUNNING;
}
}
void xilTemacInit( void *voidptr )
{
}
void xilTemacReset(struct ifnet *ifp)
{
xilTemacStop( ifp );
xilTemacStart( ifp );
}
void xilTemacSetMacAddress(struct ifnet *ifp, unsigned char* aAddr)
{
struct XilTemac* xilTemac = ifp->if_softc;
uint32_t base = xilTemac->iAddr;
/* You can't change the mac address while the card is in operation */
if( (ifp->if_flags & IFF_RUNNING) != 0 ) {
printk("%s: attempted to change MAC while up, interface '%s'\n", DRIVER_PREFIX, xilTemac->iUnitName );
assert(0);
}
uint32_t mac;
mac = aAddr[0] & 0x000000FF;
mac |= aAddr[1] << 8;
mac |= aAddr[2] << 16;
mac |= aAddr[3] << 24;
OUT32(base + XTE_EUAW0_OFFSET, mac);
mac = IN32(base + XTE_EUAW1_OFFSET);
mac &= ~XTE_EUAW1_MASK;
mac |= aAddr[4] & 0x000000FF;
mac |= aAddr[5] << 8;
OUT32(base + XTE_EUAW1_OFFSET, mac);
}
void xilTemacPrintStats( struct ifnet *ifp )
{
struct XilTemac* xilTemac = ifp->if_softc;
printf("\n");
printf("%s: Statistics for interface '%s'\n", DRIVER_PREFIX, xilTemac->iUnitName );
printf("%s: Ipif Interrupts: %lu\n", DRIVER_PREFIX, xilTemac->iStats.iInterrupts);
printf("%s: Rx Interrupts: %lu\n", DRIVER_PREFIX, xilTemac->iStats.iRxInterrupts);
printf("%s: Rx Rejected Interrupts: %lu\n", DRIVER_PREFIX, xilTemac->iStats.iRxRejectedInterrupts);
printf("%s: Rx Rej Invalid Frame: %lu\n", DRIVER_PREFIX, xilTemac->iStats.iRxRejectedInvalidFrame);
printf("%s: Rx Rej Data Fifo Full: %lu\n", DRIVER_PREFIX, xilTemac->iStats.iRxRejectedDataFifoFull);
printf("%s:Rx Rej Length Fifo Full: %lu\n", DRIVER_PREFIX, xilTemac->iStats.iRxRejectedLengthFifoFull);
printf("%s: Rx Stray Events: %lu\n", DRIVER_PREFIX, xilTemac->iStats.iRxStrayEvents);
printf("%s: Rx Max Drained: %lu\n", DRIVER_PREFIX, xilTemac->iStats.iRxMaxDrained);
printf("%s: Tx Interrupts: %lu\n", DRIVER_PREFIX, xilTemac->iStats.iTxInterrupts);
printf("%s: Tx Max Drained: %lu\n", DRIVER_PREFIX, xilTemac->iStats.iTxMaxDrained);
printf("\n");
}
void xilTemacIsrSingle(struct XilTemac* xilTemac)
{
uint32_t base = xilTemac->iAddr;
uint32_t disr = IN32( base + XTE_DISR_OFFSET );
struct ifnet* ifp = xilTemac->iIfp;
if( disr && (ifp->if_flags & IFF_RUNNING) == 0 ) {
/* some interrupt status bits are asserted but card is down */
printk("%s: Fatal error, disr 0 or this emac not running\n", DRIVER_PREFIX);
/*assert(0);*/
} else {
/* Handle all error conditions first */
if( disr & (XTE_DXR_DPTO_MASK | XTE_DXR_TERR_MASK |
XTE_DXR_RECV_FIFO_MASK | XTE_DXR_SEND_FIFO_MASK) ) {
printk("%s: Fatal Bus error, disr: %08x\n", DRIVER_PREFIX, disr);
/*assert(0);*/
}
if( disr & XTE_DXR_CORE_MASK ) {
/* Normal case, temac interrupt */
uint32_t ipisr = IN32(base + XTE_IPISR_OFFSET);
uint32_t ipier = IN32(base + XTE_IPIER_OFFSET);
uint32_t newipier = ipier;
uint32_t pending = ipisr & ipier;
xilTemac->iStats.iInterrupts++;
/* Check for all fatal errors, even if that error is not enabled in ipier */
if(ipisr & XTE_IPXR_FIFO_FATAL_ERROR_MASK) {
printk("%s: Fatal Fifo Error ipisr: %08x\n", DRIVER_PREFIX, ipisr);
/*assert(0);*/
}
if(pending & XTE_IPXR_RECV_DONE_MASK) {
/* We've received a packet
- inc stats
- disable rx interrupt
- signal rx thread to empty out fifo
(rx thread must renable interrupt)
*/
xilTemac->iStats.iRxInterrupts++;
newipier &= ~XTE_IPXR_RECV_DONE_MASK;
rtems_event_send(gXilRxThread, xilTemac->iIoEvent);
}
if(pending & XTE_IPXR_XMIT_DONE_MASK) {
/* We've transmitted a packet. This interrupt is only ever enabled in
the ipier if the tx thread didn't have enough space in the data fifo
or the tplr fifo. If that's the case, we:
- inc stats
- disable tx interrupt
- signal tx thread that a transmit has completed and thus there is now
room to send again.
*/
xilTemac->iStats.iTxInterrupts++;
newipier &= ~XTE_IPXR_XMIT_DONE_MASK;
rtems_event_send(gXilTxThread, xilTemac->iIoEvent);
}
if(pending & XTE_IPXR_RECV_DROPPED_MASK) {
/* A packet was dropped (because it was invalid, or receiving it
have overflowed one of the rx fifo's).
- Increment stats.
- Clear interrupt condition.
*/
uint32_t toggle = 0;
if(pending & XTE_IPXR_RECV_REJECT_MASK) {
xilTemac->iStats.iRxRejectedInvalidFrame++;
toggle |= XTE_IPXR_RECV_REJECT_MASK;
}
if(pending & XTE_IPXR_RECV_PFIFO_ABORT_MASK) {
xilTemac->iStats.iRxRejectedDataFifoFull++;
toggle |= XTE_IPXR_RECV_PFIFO_ABORT_MASK;
}
if(pending & XTE_IPXR_RECV_LFIFO_ABORT_MASK) {
xilTemac->iStats.iRxRejectedLengthFifoFull++;
toggle |= XTE_IPXR_RECV_LFIFO_ABORT_MASK;
}
xilTemac->iStats.iRxRejectedInterrupts++;
OUT32(base + XTE_IPISR_OFFSET, toggle);
}
if(pending & XTE_IPXR_AUTO_NEG_MASK) {
printk("%s: Autonegotiation finished\n", DRIVER_PREFIX);
OUT32(base + XTE_IPISR_OFFSET, XTE_IPXR_AUTO_NEG_MASK);
}
if(newipier != ipier) {
OUT32(base + XTE_IPIER_OFFSET, newipier);
}
}
}
}
#if PPC_HAS_CLASSIC_EXCEPTIONS
rtems_isr xilTemacIsr( rtems_vector_number aVector )
{
struct XilTemac* xilTemac;
int i;
for( i=0; i< NUM_XILTEMAC_UNITS; i++ ) {
xilTemac = &gXilTemac[i];
if( xilTemac->iIsPresent ) {
xilTemacIsrSingle(xilTemac);
}
}
}
#else
rtems_isr xilTemacIsr(void *handle )
{
struct XilTemac* xilTemac = (struct XilTemac*)handle;
xilTemacIsrSingle(xilTemac);
}
void xilTemacIsrOn(const rtems_irq_connect_data *unused)
{
}
void xilTemacIsrOff(const rtems_irq_connect_data *unused)
{
}
int xilTemacIsrIsOn(const rtems_irq_connect_data *unused)
{
return 1;
}
#endif
int32_t xilTemacSetMulticastFilter(struct ifnet *ifp)
{
return 0;
}
int xilTemacIoctl(struct ifnet* ifp, ioctl_command_t aCommand, caddr_t aData)
{
struct XilTemac* xilTemac = ifp->if_softc;
int32_t error = 0;
switch(aCommand) {
case SIOCGIFADDR:
case SIOCSIFADDR:
ether_ioctl(ifp, aCommand, aData);
break;
case SIOCSIFFLAGS:
switch(ifp->if_flags & (IFF_UP | IFF_RUNNING))
{
case IFF_RUNNING:
xilTemacStop(ifp);
break;
case IFF_UP:
xilTemacStart(ifp);
break;
case IFF_UP | IFF_RUNNING:
xilTemacReset(ifp);
break;
default:
break;
}
break;
case SIOCADDMULTI:
case SIOCDELMULTI: {
struct ifreq* ifr = (struct ifreq*) aData;
error = ((aCommand == SIOCADDMULTI) ?
( ether_addmulti(ifr, &(xilTemac->iArpcom)) ) :
( ether_delmulti(ifr, &(xilTemac->iArpcom)))
);
/* ENETRESET indicates that driver should update its multicast filters */
if(error == ENETRESET)
{
error = xilTemacSetMulticastFilter( ifp );
}
break;
}
case SIO_RTEMS_SHOW_STATS:
xilTemacPrintStats( ifp );
break;
default:
error = EINVAL;
break;
}
return error;
}
void xilTemacSend(struct ifnet* ifp)
{
struct XilTemac* xilTemac = ifp->if_softc;
/* wake up tx thread w/ outbound interface's signal */
rtems_event_send( gXilTxThread, xilTemac->iIoEvent );
ifp->if_flags |= IFF_OACTIVE;
}
/* align the tx buffer to 32 bytes just for kicks, should make it more
* cache friendly */
static unsigned char gTxBuf[2048] __attribute__ ((aligned (32)));
void xilTemacSendPacket(struct ifnet *ifp, struct mbuf* aMbuf)
{
struct XilTemac *xilTemac = ifp->if_softc;
struct mbuf *n = aMbuf;
uint32_t len = 0;
#ifdef DEBUG
printk("SendPacket\n");
printk("TXD: 0x%08x\n", (int32_t) n->m_data);
#endif
/* assemble the packet into the tx buffer */
for(;;) {
#ifdef DEBUG
uint32_t i = 0;
printk("MBUF: 0x%08x : ", (int32_t) n->m_data);
for (i=0;i<n->m_len;i+=2) {
printk("%02x%02x ", mtod(n, unsigned char*)[i], mtod(n, unsigned char*)[i+1]);
}
printk("\n");
#endif
if( n->m_len > 0 ) {
memcpy( &gTxBuf[ len ], (char *)n->m_data, n->m_len);
len += n->m_len;
}
if( (n = n->m_next) == 0) {
break;
}
}
xilTemacFifoWrite64( xilTemac->iAddr, (uint32_t*)gTxBuf, len );
/* Set the Transmit Packet Length Register which registers the packet
* length, enqueues the packet and signals the xmit unit to start
* sending. */
OUT32(xilTemac->iAddr + XTE_TPLR_OFFSET, len);
#ifdef DEBUG
printk("%s: txpkt, len %d\n", DRIVER_PREFIX, len );
memset(gTxBuf, 0, len);
#endif
}
void xilTemacTxThreadSingle(struct ifnet* ifp)
{
struct XilTemac* xilTemac = ifp->if_softc;
struct mbuf* m;
uint32_t base = xilTemac->iAddr;
#ifdef DEBUG
printk("%s: tx send packet, interface '%s'\n", DRIVER_PREFIX, xilTemac->iUnitName );
#endif
/* Send packets till mbuf queue empty or tx fifo full */
for(;;) {
uint32_t i = 0;
/* 1) clear out any statuses from previously sent tx frames */
while( IN32(base + XTE_IPISR_OFFSET) & XTE_IPXR_XMIT_DONE_MASK ) {
IN32(base + XTE_TSR_OFFSET);
OUT32(base + XTE_IPISR_OFFSET, XTE_IPXR_XMIT_DONE_MASK);
i++;
}
if( i > xilTemac->iStats.iTxMaxDrained ) {
xilTemac->iStats.iTxMaxDrained = i;
}
/* 2) Check if enough space in tx data fifo _and_ tx tplr for an entire
ethernet frame */
if( xilTemacTxFifoVacancyBytes( xilTemac->iAddr ) <= ifp->if_mtu ) {
/* 2a) If not, enable transmit done interrupt and break out of loop to
wait for space */
uint32_t ipier = IN32(base + XTE_IPIER_OFFSET);
ipier |= (XTE_IPXR_XMIT_DONE_MASK);
OUT32(base + XTE_IPIER_OFFSET, ipier);
break;
}
/* 3) Contuine to dequeue mbuf chains till none left */
IF_DEQUEUE( &(ifp->if_snd), m);
if( !m ) {
break;
}
/* 4) Send dequeued mbuf chain */
xilTemacSendPacket( ifp, m );
/* 5) Free mbuf chain */
m_freem( m );
}
ifp->if_flags &= ~IFF_OACTIVE;
}
void xilTemacTxThread( void *ignore )
{
struct XilTemac *xilTemac;
struct ifnet *ifp;
rtems_event_set events;
int i;
for(;;) {
/* Wait for:
- notification from stack of packet to send OR
- notification from interrupt handler that there is space available to
send already queued packets
*/
rtems_bsdnet_event_receive( RTEMS_ALL_EVENTS,
RTEMS_EVENT_ANY | RTEMS_WAIT,
RTEMS_NO_TIMEOUT,
&events );
for(i=0; i< NUM_XILTEMAC_UNITS; i++) {
xilTemac = &gXilTemac[i];
if( xilTemac->iIsPresent ) {
ifp = xilTemac->iIfp;
if( (ifp->if_flags & IFF_RUNNING) ) {
if( events & xilTemac->iIoEvent ) {
xilTemacTxThreadSingle(ifp);
}
} else {
printk("%s: xilTemacTxThread: event received for device: %s, but device not active\n",
DRIVER_PREFIX, xilTemac->iUnitName);
assert(0);
}
}
}
}
}
void xilTemacRxThreadSingle(struct ifnet* ifp)
{
struct XilTemac* xilTemac = ifp->if_softc;
uint32_t npkts = 0;
#ifdef DEBUG
printk("%s: rxthread, packet rx on interface %s\n", DRIVER_PREFIX, xilTemac->iUnitName );
#endif
uint32_t base = xilTemac->iAddr;
/* While RECV_DONE_MASK in ipisr stays set */
while( IN32(base + XTE_IPISR_OFFSET) & XTE_IPXR_RECV_DONE_MASK ) {
/* 1) Read the length of the packet */
uint32_t bytes = IN32(base + XTE_RPLR_OFFSET);
/* 2) Read the Read Status Register (which contains no information). When
* all of these in the fifo have been read, then XTE_IPXR_RECV_DONE_MASK
* will stay turned off, after it's written to */
IN32(base + XTE_RSR_OFFSET);
npkts++;
struct mbuf* m;
struct ether_header* eh;
/* 3) Get some memory from the ip stack to store the packet in */
MGETHDR(m, M_WAIT, MT_DATA);
MCLGET(m, M_WAIT);
m->m_pkthdr.rcvif = ifp;
/* 4) Copy the packet into the ip stack's memory */
xilTemacFifoRead64( base, mtod(m, uint32_t*), bytes);
m->m_len = bytes - sizeof(struct ether_header);
m->m_pkthdr.len = bytes - sizeof(struct ether_header);
eh = mtod(m, struct ether_header*);
m->m_data += sizeof(struct ether_header);
/* 5) Tell the ip stack about the received packet */
ether_input(ifp, eh, m);
/* 6) Try and turn off XTE_IPXR_RECV_DONE bit in the ipisr. If there's
* still more packets (ie RSR ! empty), then it will stay asserted. If
* there's no more packets, this will turn it off.
*/
OUT32(base + XTE_IPISR_OFFSET, XTE_IPXR_RECV_DONE_MASK);
}
/* End) All Rx packets serviced, renable rx interrupt */
uint32_t ipier = IN32(base + XTE_IPIER_OFFSET);
ipier |= XTE_IPXR_RECV_DONE_MASK;
OUT32(base + XTE_IPIER_OFFSET, ipier);
#ifdef DEBUG
printk("%s: rxthread, retrieved %d packets\n", DRIVER_PREFIX, npkts );
#endif
if(npkts > xilTemac->iStats.iRxMaxDrained) {
xilTemac->iStats.iRxMaxDrained = npkts;
}
/* ??) Very very occasionally, under extremely high stress, I get a situation
* where we process no packets. That is, the rx thread was evented, but
* there was no packet available. I'm not sure how this happens. Ideally,
* it shouldn't ocurr, and I suspect a minor bug in the driver. However, for
* me it's happenning 3 times in several hunderd million interrupts. Nothing
* bad happens, as long as we don't read from the rx fifo's if nothing is
* there. It is just not as efficient as possible (rx thread being evented
* pointlessly) and a bit disconcerting about how it's ocurring.
* The best way to reproduce this is to have two clients run:
* $ ping <host> -f -s 65507
* This flood pings the device from two clients with the maximum size ping
* packet. It absolutely hammers the device under test. Eventually, (if
* you leave it running overnight for instance), you'll get a couple of these
* stray rx events. */
if(npkts == 0) {
/*printk("%s: RxThreadSingle: fatal error: event received, but no packets available\n", DRIVER_PREFIX);
assert(0); */
xilTemac->iStats.iRxStrayEvents++;
}
}
void xilTemacRxThread( void *ignore )
{
struct XilTemac* xilTemac;
struct ifnet* ifp;
int i;
rtems_event_set events;
#ifdef DEBUG
printk("%s: xilTemacRxThread running\n", DRIVER_PREFIX );
#endif
for(;;) {
rtems_bsdnet_event_receive( RTEMS_ALL_EVENTS,
RTEMS_WAIT | RTEMS_EVENT_ANY,
RTEMS_NO_TIMEOUT,
&events);
#ifdef DEBUG
printk("%s: rxthread, wakeup\n", DRIVER_PREFIX );
#endif
for(i=0; i< NUM_XILTEMAC_UNITS; i++) {
xilTemac = &gXilTemac[i];
if( xilTemac->iIsPresent ) {
ifp = xilTemac->iIfp;
if( (ifp->if_flags & IFF_RUNNING) != 0 ) {
if( events & xilTemac->iIoEvent ) {
xilTemacRxThreadSingle(ifp);
}
}
else {
printk("%s: rxthread, interface %s present but not running\n", DRIVER_PREFIX, xilTemac->iUnitName );
assert(0);
}
}
}
}
}
int32_t xilTemac_driver_attach(struct rtems_bsdnet_ifconfig* aBsdConfig, int aDummy)
{
struct ifnet* ifp;
int32_t mtu;
int32_t unit;
char* unitName;
struct XilTemac* xilTemac;
unit = rtems_bsdnet_parse_driver_name(aBsdConfig, &unitName);
if(unit < 0 )
{
printk("%s: Interface Unit number < 0\n", DRIVER_PREFIX );
return 0;
}
if( aBsdConfig->bpar == 0 )
{
printk("%s: Did not specify base address for device '%s'", DRIVER_PREFIX, unitName );
return 0;
}
if( aBsdConfig->hardware_address == NULL )
{
printk("%s: No MAC address given for interface '%s'\n", DRIVER_PREFIX, unitName );
return 0;
}
xilTemac = &gXilTemac[ unit ];
memset(xilTemac, 0, sizeof(struct XilTemac));
xilTemac->iIsPresent = 1;
snprintf( xilTemac->iUnitName, MAX_UNIT_BYTES, "%s%d", unitName, unit );
xilTemac->iIfp = &(xilTemac->iArpcom.ac_if);
ifp = &(xilTemac->iArpcom.ac_if);
xilTemac->iAddr = aBsdConfig->bpar;
xilTemac->iIoEvent = gUnitSignals[ unit ];
xilTemac->iIsrVector = aBsdConfig->irno;
memcpy( xilTemac->iArpcom.ac_enaddr, aBsdConfig->hardware_address, ETHER_ADDR_LEN);
if( aBsdConfig->mtu )
{
mtu = aBsdConfig->mtu;
}
else
{
mtu = ETHERMTU;
}
ifp->if_softc = xilTemac;
ifp->if_unit = unit;
ifp->if_name = unitName;
ifp->if_mtu = mtu;
ifp->if_init = xilTemacInit;
ifp->if_ioctl = xilTemacIoctl;
ifp->if_start = xilTemacSend;
ifp->if_output = ether_output;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
if(ifp->if_snd.ifq_maxlen == 0)
{
ifp->if_snd.ifq_maxlen = ifqmaxlen;
}
if_attach(ifp);
ether_ifattach(ifp);
/* create shared rx & tx threads */
if( (gXilRxThread == 0) && (gXilTxThread == 0) )
{
printk("%s: Creating shared RX/TX threads\n", DRIVER_PREFIX );
gXilRxThread = rtems_bsdnet_newproc("xerx", 4096, xilTemacRxThread, NULL );
gXilTxThread = rtems_bsdnet_newproc("xetx", 4096, xilTemacTxThread, NULL );
}
printk("%s: Initializing driver for '%s'\n", DRIVER_PREFIX, xilTemac->iUnitName );
printk("%s: base address 0x%08X, intnum 0x%02X, \n",
DRIVER_PREFIX,
aBsdConfig->bpar,
aBsdConfig->irno );
return 1;
}

View File

@@ -0,0 +1,375 @@
/*
* Driver for plb inteface of the xilinx temac 3.00a
*
* Author: Keith Robertson <kjrobert@alumni.uwaterloo.ca>
* Copyright (c) 2007 Linn Products Ltd, Scotland.
*
* 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.
*
*/
#ifndef _XILINX_TEMAC_
#define _XILINX_TEMAC_
#include <rtems/irq.h>
#define XILTEMAC_DRIVER_PREFIX "xiltemac"
#define DRIVER_PREFIX XILTEMAC_DRIVER_PREFIX
/** IPIF interrupt and reset registers
*/
#define XTE_DISR_OFFSET 0x00000000 /**< Device interrupt status */
#define XTE_DIPR_OFFSET 0x00000004 /**< Device interrupt pending */
#define XTE_DIER_OFFSET 0x00000008 /**< Device interrupt enable */
#define XTE_DIIR_OFFSET 0x00000018 /**< Device interrupt ID */
#define XTE_DGIE_OFFSET 0x0000001C /**< Device global interrupt enable */
#define XTE_IPISR_OFFSET 0x00000020 /**< IP interrupt status */
#define XTE_IPIER_OFFSET 0x00000028 /**< IP interrupt enable */
#define XTE_DSR_OFFSET 0x00000040 /**< Device software reset (write) */
/** IPIF transmit fifo
*/
#define XTE_PFIFO_TX_BASE_OFFSET 0x00002000 /**< Packet FIFO Tx channel */
#define XTE_PFIFO_TX_VACANCY_OFFSET 0x00002004 /**< Packet Fifo Tx Vacancy */
#define XTE_PFIFO_TX_DATA_OFFSET 0x00002100 /**< IPIF Tx packet fifo port */
/** IPIF receive fifo
*/
#define XTE_PFIFO_RX_BASE_OFFSET 0x00002010 /**< Packet FIFO Rx channel */
#define XTE_PFIFO_RX_VACANCY_OFFSET 0x00002014 /**< Packet Fifo Rx Vacancy */
#define XTE_PFIFO_RX_DATA_OFFSET 0x00002200 /**< IPIF Rx packet fifo port */
/** IPIF fifo masks
*/
#define XTE_PFIFO_COUNT_MASK 0x00FFFFFF
/** IPIF transmit and recieve DMA offsets
*/
#define XTE_DMA_SEND_OFFSET 0x00002300 /**< DMA Tx channel */
#define XTE_DMA_RECV_OFFSET 0x00002340 /**< DMA Rx channel */
/** IPIF IPIC_TO_TEMAC Core Registers
*/
#define XTE_CR_OFFSET 0x00001000 /**< Control */
#define XTE_TPLR_OFFSET 0x00001004 /**< Tx packet length (FIFO) */
#define XTE_TSR_OFFSET 0x00001008 /**< Tx status (FIFO) */
#define XTE_RPLR_OFFSET 0x0000100C /**< Rx packet length (FIFO) */
#define XTE_RSR_OFFSET 0x00001010 /**< Receive status */
#define XTE_IFGP_OFFSET 0x00001014 /**< Interframe gap */
#define XTE_TPPR_OFFSET 0x00001018 /**< Tx pause packet */
/** TEMAC Core Registers
* These are registers defined within the device's hard core located in the
* processor block. They are accessed with the host interface. These registers
* are addressed offset by XTE_HOST_IPIF_OFFSET or by the DCR base address
* if so configured.
*/
#define XTE_HOST_IPIF_OFFSET 0x00003000 /**< Offset of host registers when
memory mapped into IPIF */
#define XTE_ERXC0_OFFSET (XTE_HOST_IPIF_OFFSET + 0x00000200) /**< Rx configuration word 0 */
#define XTE_ERXC1_OFFSET (XTE_HOST_IPIF_OFFSET + 0x00000240) /**< Rx configuration word 1 */
#define XTE_ETXC_OFFSET (XTE_HOST_IPIF_OFFSET + 0x00000280) /**< Tx configuration */
#define XTE_EFCC_OFFSET (XTE_HOST_IPIF_OFFSET + 0x000002C0) /**< Flow control configuration */
#define XTE_ECFG_OFFSET (XTE_HOST_IPIF_OFFSET + 0x00000300) /**< EMAC configuration */
#define XTE_EGMIC_OFFSET (XTE_HOST_IPIF_OFFSET + 0x00000320) /**< RGMII/SGMII configuration */
#define XTE_EMC_OFFSET (XTE_HOST_IPIF_OFFSET + 0x00000340) /**< Management configuration */
#define XTE_EUAW0_OFFSET (XTE_HOST_IPIF_OFFSET + 0x00000380) /**< Unicast address word 0 */
#define XTE_EUAW1_OFFSET (XTE_HOST_IPIF_OFFSET + 0x00000384) /**< Unicast address word 1 */
#define XTE_EMAW0_OFFSET (XTE_HOST_IPIF_OFFSET + 0x00000388) /**< Multicast address word 0 */
#define XTE_EMAW1_OFFSET (XTE_HOST_IPIF_OFFSET + 0x0000038C) /**< Multicast address word 1 */
#define XTE_EAFM_OFFSET (XTE_HOST_IPIF_OFFSET + 0x00000390) /**< Promisciuous mode */
#define XTE_EIRS_OFFSET (XTE_HOST_IPIF_OFFSET + 0x000003A0) /**< IRstatus */
#define XTE_EIREN_OFFSET (XTE_HOST_IPIF_OFFSET + 0x000003A4) /**< IRenable */
#define XTE_EMIID_OFFSET (XTE_HOST_IPIF_OFFSET + 0x000003B0) /**< MIIMwrData */
#define XTE_EMIIC_OFFSET (XTE_HOST_IPIF_OFFSET + 0x000003B4) /**< MiiMcnt */
/* Register masks. The following constants define bit locations of various
* control bits in the registers. Constants are not defined for those registers
* that have a single bit field representing all 32 bits. For further
* information on the meaning of the various bit masks, refer to the HW spec.
*/
/** Interrupt status bits for top level interrupts
* These bits are associated with the XTE_DISR_OFFSET, XTE_DIPR_OFFSET,
* and XTE_DIER_OFFSET registers.
*/
#define XTE_DXR_SEND_FIFO_MASK 0x00000040 /**< Send FIFO channel */
#define XTE_DXR_RECV_FIFO_MASK 0x00000020 /**< Receive FIFO channel */
#define XTE_DXR_RECV_DMA_MASK 0x00000010 /**< Receive DMA channel */
#define XTE_DXR_SEND_DMA_MASK 0x00000008 /**< Send DMA channel */
#define XTE_DXR_CORE_MASK 0x00000004 /**< Core */
#define XTE_DXR_DPTO_MASK 0x00000002 /**< Data phase timeout */
#define XTE_DXR_TERR_MASK 0x00000001 /**< Transaction error */
/** Interrupt status bits for MAC interrupts
* These bits are associated with XTE_IPISR_OFFSET and XTE_IPIER_OFFSET
* registers.
*/
#define XTE_IPXR_XMIT_DONE_MASK 0x00000001 /**< Tx complete */
#define XTE_IPXR_RECV_DONE_MASK 0x00000002 /**< Rx complete */
#define XTE_IPXR_AUTO_NEG_MASK 0x00000004 /**< Auto negotiation complete */
#define XTE_IPXR_RECV_REJECT_MASK 0x00000008 /**< Rx packet rejected */
#define XTE_IPXR_XMIT_SFIFO_EMPTY_MASK 0x00000010 /**< Tx status fifo empty */
#define XTE_IPXR_RECV_LFIFO_EMPTY_MASK 0x00000020 /**< Rx length fifo empty */
#define XTE_IPXR_XMIT_LFIFO_FULL_MASK 0x00000040 /**< Tx length fifo full */
#define XTE_IPXR_RECV_LFIFO_OVER_MASK 0x00000080 /**< Rx length fifo overrun
Note that this signal is
no longer asserted by HW
*/
#define XTE_IPXR_RECV_LFIFO_UNDER_MASK 0x00000100 /**< Rx length fifo underrun */
#define XTE_IPXR_XMIT_SFIFO_OVER_MASK 0x00000200 /**< Tx status fifo overrun */
#define XTE_IPXR_XMIT_SFIFO_UNDER_MASK 0x00000400 /**< Tx status fifo underrun */
#define XTE_IPXR_XMIT_LFIFO_OVER_MASK 0x00000800 /**< Tx length fifo overrun */
#define XTE_IPXR_XMIT_LFIFO_UNDER_MASK 0x00001000 /**< Tx length fifo underrun */
#define XTE_IPXR_RECV_PFIFO_ABORT_MASK 0x00002000 /**< Rx packet rejected due to
full packet FIFO */
#define XTE_IPXR_RECV_LFIFO_ABORT_MASK 0x00004000 /**< Rx packet rejected due to
full length FIFO */
#define XTE_IPXR_RECV_DROPPED_MASK \
(XTE_IPXR_RECV_REJECT_MASK | \
XTE_IPXR_RECV_PFIFO_ABORT_MASK | \
XTE_IPXR_RECV_LFIFO_ABORT_MASK) /**< IPXR bits that indicate a dropped
receive frame */
#define XTE_IPXR_XMIT_ERROR_MASK \
(XTE_IPXR_XMIT_SFIFO_OVER_MASK | \
XTE_IPXR_XMIT_SFIFO_UNDER_MASK | \
XTE_IPXR_XMIT_LFIFO_OVER_MASK | \
XTE_IPXR_XMIT_LFIFO_UNDER_MASK) /**< IPXR bits that indicate transmit
errors */
#define XTE_IPXR_RECV_ERROR_MASK \
(XTE_IPXR_RECV_DROPPED_MASK | \
XTE_IPXR_RECV_LFIFO_UNDER_MASK) /**< IPXR bits that indicate receive
errors */
#define XTE_IPXR_FIFO_FATAL_ERROR_MASK \
(XTE_IPXR_XMIT_SFIFO_OVER_MASK | \
XTE_IPXR_XMIT_SFIFO_UNDER_MASK | \
XTE_IPXR_XMIT_LFIFO_OVER_MASK | \
XTE_IPXR_XMIT_LFIFO_UNDER_MASK | \
XTE_IPXR_RECV_LFIFO_UNDER_MASK) /**< IPXR bits that indicate errors with
one of the length or status FIFOs
that is fatal in nature. These bits
can only be cleared by a device
reset */
/** Software reset register (DSR)
*/
#define XTE_DSR_RESET_MASK 0x0000000A /**< Write this value to DSR to
reset entire core */
/** Global interrupt enable register (DGIE)
*/
#define XTE_DGIE_ENABLE_MASK 0x80000000 /**< Write this value to DGIE to
enable interrupts from this
device */
/** Control Register (CR)
*/
#define XTE_CR_HTRST_MASK 0x00000008 /**< Reset hard temac */
#define XTE_CR_BCREJ_MASK 0x00000004 /**< Disable broadcast address
filtering */
#define XTE_CR_MCREJ_MASK 0x00000002 /**< Disable multicast address
filtering */
#define XTE_CR_HDUPLEX_MASK 0x00000001 /**< Enable half duplex operation */
/** Transmit Packet Length Register (TPLR)
*/
#define XTE_TPLR_TXPL_MASK 0x00003FFF /**< Tx packet length in bytes */
/** Transmit Status Register (TSR)
*/
#define XTE_TSR_TXED_MASK 0x80000000 /**< Excess deferral error */
#define XTE_TSR_PFIFOU_MASK 0x40000000 /**< Packet FIFO underrun */
#define XTE_TSR_TXA_MASK 0x3E000000 /**< Transmission attempts */
#define XTE_TSR_TXLC_MASK 0x01000000 /**< Late collision error */
#define XTE_TSR_TPCF_MASK 0x00000001 /**< Transmit packet complete
flag */
#define XTE_TSR_ERROR_MASK \
(XTE_TSR_TXED_MASK | \
XTE_TSR_PFIFOU_MASK | \
XTE_TSR_TXLC_MASK) /**< TSR bits that indicate an
error */
/** Receive Packet Length Register (RPLR)
*/
#define XTE_RPLR_RXPL_MASK 0x00003FFF /**< Rx packet length in bytes */
/** Receive Status Register (RSR)
*/
#define XTE_RSR_RPCF_MASK 0x00000001 /**< Receive packet complete
flag */
/** Interframe Gap Register (IFG)
*/
#define XTE_IFG_IFGD_MASK 0x000000FF /**< IFG delay */
/** Transmit Pause Packet Register (TPPR)
*/
#define XTE_TPPR_TPPD_MASK 0x0000FFFF /**< Tx pause packet data */
/** Receiver Configuration Word 1 (ERXC1)
*/
#define XTE_ERXC1_RXRST_MASK 0x80000000 /**< Receiver reset */
#define XTE_ERXC1_RXJMBO_MASK 0x40000000 /**< Jumbo frame enable */
#define XTE_ERXC1_RXFCS_MASK 0x20000000 /**< FCS not stripped */
#define XTE_ERXC1_RXEN_MASK 0x10000000 /**< Receiver enable */
#define XTE_ERXC1_RXVLAN_MASK 0x08000000 /**< VLAN enable */
#define XTE_ERXC1_RXHD_MASK 0x04000000 /**< Half duplex */
#define XTE_ERXC1_RXLT_MASK 0x02000000 /**< Length/type check disable */
#define XTE_ERXC1_ERXC1_MASK 0x0000FFFF /**< Pause frame source address
bits [47:32]. Bits [31:0]
are stored in register
ERXC0 */
/** Transmitter Configuration (ETXC)
*/
#define XTE_ETXC_TXRST_MASK 0x80000000 /**< Transmitter reset */
#define XTE_ETXC_TXJMBO_MASK 0x40000000 /**< Jumbo frame enable */
#define XTE_ETXC_TXFCS_MASK 0x20000000 /**< Generate FCS */
#define XTE_ETXC_TXEN_MASK 0x10000000 /**< Transmitter enable */
#define XTE_ETXC_TXVLAN_MASK 0x08000000 /**< VLAN enable */
#define XTE_ETXC_TXHD_MASK 0x04000000 /**< Half duplex */
#define XTE_ETXC_TXIFG_MASK 0x02000000 /**< IFG adjust enable */
/** Flow Control Configuration (EFCC)
*/
#define XTE_EFCC_TXFLO_MASK 0x40000000 /**< Tx flow control enable */
#define XTE_EFCC_RXFLO_MASK 0x20000000 /**< Rx flow control enable */
/** EMAC Configuration (ECFG)
*/
#define XTE_ECFG_LINKSPD_MASK 0xC0000000 /**< Link speed */
#define XTE_ECFG_RGMII_MASK 0x20000000 /**< RGMII mode enable */
#define XTE_ECFG_SGMII_MASK 0x10000000 /**< SGMII mode enable */
#define XTE_ECFG_1000BASEX_MASK 0x08000000 /**< 1000BaseX mode enable */
#define XTE_ECFG_HOSTEN_MASK 0x04000000 /**< Host interface enable */
#define XTE_ECFG_TX16BIT 0x02000000 /**< 16 bit Tx client enable */
#define XTE_ECFG_RX16BIT 0x01000000 /**< 16 bit Rx client enable */
#define XTE_ECFG_LINKSPD_10 0x00000000 /**< XTE_ECFG_LINKSPD_MASK for
10 Mbit */
#define XTE_ECFG_LINKSPD_100 0x40000000 /**< XTE_ECFG_LINKSPD_MASK for
100 Mbit */
#define XTE_ECFG_LINKSPD_1000 0x80000000 /**< XTE_ECFG_LINKSPD_MASK for
1000 Mbit */
/** EMAC RGMII/SGMII Configuration (EGMIC)
*/
#define XTE_EGMIC_RGLINKSPD_MASK 0xC0000000 /**< RGMII link speed */
#define XTE_EGMIC_SGLINKSPD_MASK 0x0000000C /**< SGMII link speed */
#define XTE_EGMIC_RGSTATUS_MASK 0x00000002 /**< RGMII link status */
#define XTE_EGMIC_RGHALFDUPLEX_MASK 0x00000001 /**< RGMII half duplex */
#define XTE_EGMIC_RGLINKSPD_10 0x00000000 /**< XTE_EGMIC_RGLINKSPD_MASK
for 10 Mbit */
#define XTE_EGMIC_RGLINKSPD_100 0x40000000 /**< XTE_EGMIC_RGLINKSPD_MASK
for 100 Mbit */
#define XTE_EGMIC_RGLINKSPD_1000 0x80000000 /**< XTE_EGMIC_RGLINKSPD_MASK
for 1000 Mbit */
#define XTE_EGMIC_SGLINKSPD_10 0x00000000 /**< XTE_SGMIC_RGLINKSPD_MASK
for 10 Mbit */
#define XTE_EGMIC_SGLINKSPD_100 0x00000004 /**< XTE_SGMIC_RGLINKSPD_MASK
for 100 Mbit */
#define XTE_EGMIC_SGLINKSPD_1000 0x00000008 /**< XTE_SGMIC_RGLINKSPD_MASK
for 1000 Mbit */
/** EMAC Management Configuration (EMC)
*/
#define XTE_EMC_MDIO_MASK 0x00000040 /**< MII management enable */
#define XTE_EMC_CLK_DVD_MAX 0x3F /**< Maximum MDIO divisor */
/** EMAC Unicast Address Register Word 1 (EUAW1)
*/
#define XTE_EUAW1_MASK 0x0000FFFF /**< Station address bits [47:32]
Station address bits [31:0]
are stored in register
EUAW0 */
/** EMAC Multicast Address Register Word 1 (EMAW1)
*/
#define XTE_EMAW1_CAMRNW_MASK 0x00800000 /**< CAM read/write control */
#define XTE_EMAW1_CAMADDR_MASK 0x00030000 /**< CAM address mask */
#define XTE_EUAW1_MASK 0x0000FFFF /**< Multicast address bits [47:32]
Multicast address bits [31:0]
are stored in register
EMAW0 */
#define XTE_EMAW1_CAMMADDR_SHIFT_MASK 16 /**< Number of bits to shift right
to align with
XTE_EMAW1_CAMADDR_MASK */
/** EMAC Address Filter Mode (EAFM)
*/
#define XTE_EAFM_EPPRM_MASK 0x80000000 /**< Promiscuous mode enable */
/** EMAC MII Management Write Data (EMIID)
*/
#define XTE_EMIID_MIIMWRDATA_MASK 0x0000FFFF /**< Data port */
/** EMAC MII Management Control (EMIIC)
*/
#define XTE_EMIID_MIIMDECADDR_MASK 0x0000FFFF /**< Address port */
struct XilTemacStats
{
volatile uint32_t iInterrupts;
volatile uint32_t iRxInterrupts;
volatile uint32_t iRxRejectedInterrupts;
volatile uint32_t iRxRejectedInvalidFrame;
volatile uint32_t iRxRejectedDataFifoFull;
volatile uint32_t iRxRejectedLengthFifoFull;
volatile uint32_t iRxMaxDrained;
volatile uint32_t iRxStrayEvents;
volatile uint32_t iTxInterrupts;
volatile uint32_t iTxMaxDrained;
};
#define MAX_UNIT_BYTES 50
struct XilTemac
{
struct arpcom iArpcom;
struct XilTemacStats iStats;
struct ifnet* iIfp;
char iUnitName[MAX_UNIT_BYTES];
uint32_t iAddr;
rtems_event_set iIoEvent;
int iIsrVector;
#if PPC_HAS_CLASSIC_EXCEPTIONS
rtems_isr_entry iOldHandler;
#else
rtems_irq_connect_data iOldHandler;
#endif
int iIsPresent;
};
#endif /* _XILINX_EMAC_*/

View File

@@ -0,0 +1,143 @@
/* opbintctrl.c
*
* This file contains definitions and declarations for the
* Xilinx Off Processor Bus (OPB) Interrupt Controller
*
* Author: Keith Robertson <kjrobert@alumni.uwaterloo.ca>
* COPYRIGHT (c) 2005 Linn Products Ltd, Scotland.
*
* 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.
*/
#include <bsp/opbintctrl.h>
#include <rtems.h>
#include <rtems/bspIo.h>
#include <bsp/irq.h>
#include <rtems/powerpc/powerpc.h>
/*
* Acknowledge a mask of interrupts.
*/
RTEMS_INLINE_ROUTINE void set_iar(uint32_t mask)
{
*((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_IAR)) = mask;
}
/*
* Set IER state. Used to (dis)enable a mask of vectors.
* If you only have to do one, use enable/disable_vector.
*/
RTEMS_INLINE_ROUTINE void set_ier(uint32_t mask)
{
*((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_IER)) = mask;
}
/*
* Retrieve contents of Interrupt Pending Register
*/
RTEMS_INLINE_ROUTINE uint32_t get_ipr()
{
uint32_t c = *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_IPR));
return c;
}
void BSP_irq_enable_at_opbintc (rtems_irq_number irqnum)
{
*((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_SIE))
= 1 << (irqnum - BSP_OPBINTC_IRQ_LOWEST_OFFSET);
}
void BSP_irq_disable_at_opbintc (rtems_irq_number irqnum)
{
*((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_CIE))
= 1 << (irqnum - BSP_OPBINTC_IRQ_LOWEST_OFFSET);
}
/*
* IRQ Handler: this is called from the primary exception dispatcher
*/
void BSP_irq_handle_at_opbintc(void)
{
uint32_t ipr, iprcopy, mask, i, c;
rtems_irq_connect_data *tbl_entry;
iprcopy = ipr = get_ipr();
c = 0;
mask = 0;
for (i = 0;
(i < BSP_OPBINTC_PER_IRQ_NUMBER)
&& (ipr != 0);
i++) {
c = (1 << i);
if ((ipr & c) != 0) {
/* interrupt is asserted */
mask |= c;
ipr &= ~c;
tbl_entry = &BSP_rtems_irq_tbl[i+BSP_OPBINTC_IRQ_LOWEST_OFFSET];
if (tbl_entry->hdl != NULL) {
(tbl_entry->hdl) (tbl_entry->handle);
} else {
printk("opbintctrl: Spurious interrupt; IPR 0x%08X, vector 0x%x\n\r",
iprcopy, i);
}
}
}
if (mask) {
/* ack all the interrupts we serviced */
set_iar(mask);
}
}
/*
* activate the interrupt controller
*/
rtems_status_code opb_intc_init(void)
{
uint32_t msr_value;
uint32_t i, mask = 0;
/* mask off all interrupts */
set_ier(0x0);
for (i = 0; i < OPB_INTC_IRQ_MAX; i++) {
mask |= (1 << i);
}
printk("opb_intc_init: mask = 0x%x\n", (unsigned) mask);
/* make sure interupt status register is clear before we enable the interrupt controller */
*((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_ISR)) = 0;
/* acknowledge all interrupt sources */
set_iar(mask);
/* Turn on normal hardware operation of interrupt controller */
*((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_MER)) =
(OPB_INTC_MER_HIE);
/* Enable master interrupt switch for the interrupt controller */
*((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_MER)) =
(OPB_INTC_MER_HIE | OPB_INTC_MER_ME);
#if 0 /* EB: we do it somewhere else */
/*
* enable (non-critical) exceptions
*/
_CPU_MSR_GET(msr_value);
msr_value |= PPC_MSR_EE;
_CPU_MSR_SET(msr_value);
/* install exit handler to close opb_intc when program atexit called */
/* atexit(opb_intc_exit); */
#endif
return RTEMS_SUCCESSFUL;
}

View File

@@ -0,0 +1,79 @@
## Automatically generated by ampolish3 - Do not edit
if AMPOLISH3
$(srcdir)/preinstall.am: Makefile.am
$(AMPOLISH3) $(srcdir)/Makefile.am > $(srcdir)/preinstall.am
endif
PREINSTALL_DIRS =
DISTCLEANFILES += $(PREINSTALL_DIRS)
all-am: $(PREINSTALL_FILES)
PREINSTALL_FILES =
CLEANFILES = $(PREINSTALL_FILES)
$(PROJECT_LIB)/$(dirstamp):
@$(mkdir_p) $(PROJECT_LIB)
@: > $(PROJECT_LIB)/$(dirstamp)
PREINSTALL_DIRS += $(PROJECT_LIB)/$(dirstamp)
$(PROJECT_INCLUDE)/$(dirstamp):
@$(mkdir_p) $(PROJECT_INCLUDE)
@: > $(PROJECT_INCLUDE)/$(dirstamp)
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(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)/bsp/opbintctrl.h: include/opbintctrl.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/opbintctrl.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/opbintctrl.h
$(PROJECT_INCLUDE)/bsp/irq.h: irq/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h
$(PROJECT_INCLUDE)/bsp/vectors.h: ../../powerpc/shared/vectors/vectors.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/vectors.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/vectors.h
$(PROJECT_INCLUDE)/xiltemac.h: network/xiltemac.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/xiltemac.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/xiltemac.h
$(PROJECT_INCLUDE)/xparameters_dflt.h: include/xparameters_dflt.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/xparameters_dflt.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/xparameters_dflt.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: include/coverhd.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/coverhd.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/coverhd.h
$(PROJECT_INCLUDE)/bsp/$(dirstamp):
@$(MKDIR_P) $(PROJECT_INCLUDE)/bsp
@: > $(PROJECT_INCLUDE)/bsp/$(dirstamp)
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(PROJECT_LIB)/linkcmds: startup/linkcmds $(PROJECT_LIB)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds
PREINSTALL_FILES += $(PROJECT_LIB)/linkcmds
$(PROJECT_LIB)/linkcmds.dl: startup/linkcmds.dl $(PROJECT_LIB)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds.dl
PREINSTALL_FILES += $(PROJECT_LIB)/linkcmds.dl

View File

@@ -0,0 +1,43 @@
/* bsp_cleanup()
*
* This routine normally is part of start.s and usually returns
* control to a monitor.
*
* INPUT: NONE
*
* OUTPUT: NONE
*
* Author: Andrew Bray <andy@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/libbsp/no_cpu/no_bsp/startup/bspclean.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.rtems.com/license/LICENSE.
*
* $Id$
*/
#include <rtems.h>
#include <bsp.h>
void bsp_cleanup( void )
{
rtems_fatal_error_occurred(0);
}

View File

@@ -0,0 +1,277 @@
/* bsp_start()
*
* This routine starts the application. It includes application,
* board, and monitor specific initialization and configuration.
* The generic CPU dependent initialization has been performed
* before this routine is invoked.
*
* INPUT: NONE
*
* OUTPUT: NONE
*
* Author: Thomas Doerfler <td@imd.m.isar.de>
* IMD Ingenieurbuero fuer Microcomputertechnik
*
* COPYRIGHT (c) 1998 by IMD
*
* Changes from IMD are covered by the original distributions terms.
* This file has been derived from the papyrus BSP:
*
* Author: Andrew Bray <andy@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.
*
* Modifications for spooling console driver and control of memory layout
* with linker command file by
* Thomas Doerfler <td@imd.m.isar.de>
* for these modifications:
* COPYRIGHT (c) 1997 by IMD, Puchheim, Germany.
*
* 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. IMD makes no representations about the suitability
* of this software for any purpose.
*
* Derived from c/src/lib/libbsp/no_cpu/no_bsp/startup/bspstart.c:
*
* COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
* On-Line Applications Research Corporation (OAR).
*
* Modifications for PPC405GP by Dennis Ehlin
*
* $Id$
*/
#include <string.h>
#include <fcntl.h>
#include <bsp.h>
#include <rtems/libio.h>
#include <rtems/libcsupport.h>
#include <bsp/irq.h>
#include <rtems/bspIo.h>
#include <libcpu/cpuIdent.h>
#include <libcpu/spr.h>
#include <rtems/powerpc/powerpc.h>
SPR_RW(SPRG0)
SPR_RW(SPRG1)
#include RTEMS_XPARAMETERS_H
#include <stdio.h>
/*
* 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;
uint32_t _heap_start;
uint32_t _heap_end;
uint32_t _top_of_ram;
/* Initialize whatever libc we are using
* called from postdriver hook
*/
void bsp_XAssertHandler(const char* file, int line);
void bsp_postdriver_hook(void);
void bsp_libc_init( void *, uint32_t, int );
void bsp_XAssertHandler(const char* file, int line) {
printf("\n***\n*** XAssert Failed! File: %s, Line: %d\n***\n", file, line);
}
/*
*
* bsp_predriver_hook
*
* Before drivers are setup.
*/
void bsp_predriver_hook(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;
uint32_t heap_size;
uint32_t heap_end;
/* round up from the top of workspace to next 64k boundary, get
* default heapsize from linker script */
heap_start = (((uint32_t)BSP_Configuration.work_space_start +
BSP_Configuration.work_space_size) + 0x18000) & 0xffff0000;
heap_end = _heap_start + (uint32_t)&_HeapSize;
heap_size = (heap_end - heap_start);
_heap_start = heap_start;
_heap_end = heap_end;
_top_of_ram = heap_end;
bsp_libc_init((void *) heap_start, heap_size, 0); /* 64 * 1024 */
/*
XAssertSetCallback((XAssertCallback*)bsp_XAssertHandler);
*/
#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 unsigned long *intrStackPtr;
register unsigned char* intrStack;
ppc_cpu_id_t myCpu;
ppc_cpu_revision_t myCpuRevision;
/*
* Get CPU identification dynamically. Note that the get_ppc_cpu_type()
* function store the result in global variables
* so that it can be used latter...
*/
myCpu = get_ppc_cpu_type();
myCpuRevision = get_ppc_cpu_revision();
/*
* initialize the CPU table for this BSP
* NOTE: this must be before the exception initialization,
* because exception code useses some information from Cpu_table
*/
Cpu_table.pretasking_hook = bsp_pretasking_hook; /* init libc, etc. */
Cpu_table.predriver_hook = bsp_predriver_hook;
Cpu_table.postdriver_hook = bsp_postdriver_hook;
Cpu_table.interrupt_stack_size = CONFIGURE_INTERRUPT_STACK_MEMORY;
/* timebase register ticks/microsecond */
Cpu_table.clicks_per_usec = (250000000 / 1000000);
Cpu_table.serial_per_sec = 14625000; /* = (CPU Clock / UART Internal Clock Divisor) */
Cpu_table.serial_external_clock = 0;
Cpu_table.timer_internal_clock = 1;
Cpu_table.serial_xon_xoff = 0;
Cpu_table.serial_cts_rts = 0;
Cpu_table.serial_rate = 115200;
Cpu_table.timer_average_overhead = 2;
Cpu_table.timer_least_valid = 3;
Cpu_table.exceptions_in_RAM = TRUE;
/*
* Initialize some SPRG registers related to irq handling
*/
intrStack = (((unsigned char*)&intrStackPtr) - PPC_MINIMUM_STACK_FRAME_SIZE);
_write_SPRG1((unsigned int)intrStack);
/* signal them that we have fixed PR288 - eventually, this should go away */
_write_SPRG0(PPC_BSP_HAS_FIXED_PR288);
/*
* Initialize default raw exception handlers.
* See shared/vectors/vectors_init.c
*/
initialize_exceptions();
/*
* Install our own set of exception vectors
*/
BSP_rtems_irq_mng_init(0);
/*
* Allocate the memory for the RTEMS Work Space. This can come from
* a variety of places: hard coded address, malloc'ed from outside
* RTEMS world (e.g. simulator or primitive memory manager), or (as
* typically done by stock BSPs) by subtracting the required amount
* of work space from the last physical address on the CPU board.
*/
/*
* Need to "allocate" the memory for the RTEMS Workspace and
* tell the RTEMS configuration where it is. This memory is
* not malloc'ed. It is just "pulled from the air".
*/
/* FIME: plan usage of RAM better:
- make top of ram dynamic,
- make rest of ram to heap...
-remove RAM_END from bsp.h, this cannot be valid...
or must be a function call
*/
{
extern int _end;
/* round _end up to next 64k boundary for start of workspace */
BSP_Configuration.work_space_start = (void *)((((uint32_t)&_end) + 0x18000) & 0xffff0000);
}
}
void BSP_ask_for_reset(void)
{
printk("system stopped, press RESET");
while(1) {};
}
void BSP_panic(char *s)
{
printk("%s PANIC %s\n",_RTEMS_version, s);
BSP_ask_for_reset();
}
void _BSP_Fatal_error(unsigned int v)
{
printk("%s PANIC ERROR %x\n",_RTEMS_version, v);
BSP_ask_for_reset();
}

View File

@@ -0,0 +1,169 @@
/* Greg modifications
* This file contains directives for the GNU linker which are specific
* to the virtex
* This file is intended to be used together with dlentry.s
* it will generate downloadable code
*
* Modifications for gen405 by Dennis Ehlin
* Modifications for virtex by Keith, Greg, and Bob
*
* $Id$
*/
OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc",
"elf32-powerpc")
OUTPUT_ARCH(powerpc)
ENTRY(download_entry)
_HeapSize = DEFINED(_HeapSize) ? _HeapSize : 8M;
MEMORY
{
RAM : ORIGIN = 0, LENGTH = 16M
/*FLASH : ORIGIN = 0xFFE00000, LENGTH = 16M*/
}
SECTIONS
{
.text 0x10000:
{
text.start = . ;
*(.entry)
*(.entry2)
*(.text*)
*(.rodata*)
*(.rodata1)
/*
* Special FreeBSD sysctl sections.
*/
. = ALIGN (16);
__start_set_sysctl_set = .;
*(set_sysctl_*);
__stop_set_sysctl_set = ABSOLUTE(.);
*(set_domain_*);
*(set_pseudo_*);
*(.eh_frame)
*(.gnu.linkonce.r*)
*(.descriptors)
*(rom_ver)
etext = ALIGN(0x10);
_etext = .;
*(.gnu.linkonce.t*)
__CTOR_LIST__ = .;
LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
*(.ctors)
LONG(0)
__CTOR_END__ = .;
__DTOR_LIST__ = .;
LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
*(.dtors)
LONG(0)
__DTOR_END__ = .;
*(.lit)
*(.shdata)
_init = .; __init = .; *(.init)
_fini = .; __fini = .; *(.fini)
_endtext = ALIGN(0x10);
text.end = .;
} > RAM
text.size = text.end - text.start;
/* R/W Data */
.data :
{
*(.data)
*(.data1)
*(.data.* .gnu.linkonce.d*)
PROVIDE (__SDATA_START__ = .);
*(.sdata*)
*(.gnu.linkonce.s.*)
} > RAM
PROVIDE (__EXCEPT_START__ = .);
.gcc_except_table :
{
*(.gcc_except_table)
} >RAM
PROVIDE (__EXCEPT_END__ = .);
__GOT_START__ = .;
.got :
{
s.got = .;
*(.got.plt) *(.got)
} > RAM
__GOT_END__ = .;
.got1 :
{
*(.got1)
} >RAM
PROVIDE (__GOT2_START__ = .);
PROVIDE (_GOT2_START_ = .);
.got2 :
{
*(.got2)
} >RAM
PROVIDE (__GOT2_END__ = .);
PROVIDE (_GOT2_END_ = .);
PROVIDE (__FIXUP_START__ = .);
PROVIDE (_FIXUP_START_ = .);
.fixup : { *(.fixup) } >RAM
PROVIDE (_FIXUP_END_ = .);
PROVIDE (__FIXUP_END__ = .);
PROVIDE (__SDATA2_START__ = .);
.sdata2 : { *(.sdata2) *(.gnu.linkonce.s2.*) } >RAM
.sbss2 : { *(.sbss2) *(.gnu.linkonce.sb2.*) } >RAM
PROVIDE (__SBSS2_END__ = .);
__SBSS_START__ = .;
.bss :
{
bss.start = .;
*(.bss .bss* .gnu.linkonce.b*)
*(.sbss*) *(COMMON)
bss.end = ALIGN(4);
bss.size = bss.end - bss.start;
} > RAM
__SBSS_END__ = .;
/* align bottom of 32k init stack at a 32k boundary */
. = . + 0x4000;
. = ALIGN( 0x8000 );
stack.start = .;
. = . + 0x8000;
stack.end = .;
/*
* Interrupt stack setup
*/
IntrStack_start = ALIGN(0x10);
. += 0x4000;
intrStack = .;
PROVIDE(intrStackPtr = intrStack);
PROVIDE(_end = intrStack);
.line 0 : { *(.line) }
.debug 0 : { *(.debug) }
.debug_sfnames 0 : { *(.debug_sfnames) }
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_pubnames 0 : { *(.debug_pubnames) }
.debug_aranges 0 : { *(.debug_aranges) }
.debug_aregion 0 : { *(.debug_aregion) }
.debug_macinfo 0 : { *(.debug_macinfo) }
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
}

View File

@@ -0,0 +1,154 @@
/*
* This file contains directives for the GNU linker which are specific
* to the helas403
* This file is intended to be used together with dlentry.s
* it will generate downloadable code
*
* $Id$
*/
OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc",
"elf32-powerpc")
OUTPUT_ARCH(powerpc)
ENTRY(download_entry)
MEMORY
{
RAM : ORIGIN = 0, LENGTH = 8M
FLASH : ORIGIN = 0xFFF00000, LENGTH = 512K
}
SECTIONS
{
.vectors : 0x00010100
{
*(.vectors)
} > RAM
.text :
{
text.start = . ;
*(.entry)
*(.entry2)
*(.text*)
*(.rodata)
*(.rodata1)
/*
* Special FreeBSD sysctl sections.
*/
. = ALIGN (16);
__start_set_sysctl_set = .;
*(set_sysctl_*);
__stop_set_sysctl_set = ABSOLUTE(.);
*(set_domain_*);
*(set_pseudo_*);
*.(eh_frame)
*(.descriptors)
*(rom_ver)
etext = ALIGN(0x10);
_etext = .;
__CTOR_LIST__ = .;
LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
*(.ctors)
LONG(0)
__CTOR_END__ = .;
__DTOR_LIST__ = .;
LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
*(.dtors)
LONG(0)
__DTOR_END__ = .;
*(.lit)
*(.shdata)
*(.init)
*(.fini)
_endtext = ALIGN(0x10);
text.end = .;
} > RAM
text.size = text.end - text.start;
/* R/W Data */
.data :
{
*(.data)
*(.data1)
PROVIDE (__SDATA_START__ = .);
*(.sdata*)
} > RAM
PROVIDE (__EXCEPT_START__ = .);
.gcc_except_table :
{
*(.gcc_except_table)
} >RAM
PROVIDE (__EXCEPT_END__ = .);
__GOT_START__ = .;
.got :
{
s.got = .;
*(.got.plt) *(.got)
} > RAM
__GOT_END__ = .;
.got1 :
{
*(.got1)
} >RAM
PROVIDE (__GOT2_START__ = .);
PROVIDE (_GOT2_START_ = .);
.got2 :
{
*(.got2)
} >RAM
PROVIDE (__GOT2_END__ = .);
PROVIDE (_GOT2_END_ = .);
PROVIDE (__FIXUP_START__ = .);
PROVIDE (_FIXUP_START_ = .);
.fixup : { *(.fixup) } >RAM
PROVIDE (_FIXUP_END_ = .);
PROVIDE (__FIXUP_END__ = .);
PROVIDE (__SDATA2_START__ = .);
.sdata2 : { *(.sdata2) } >RAM
.sbss2 : { *(.sbss2) } >RAM
PROVIDE (__SBSS2_END__ = .);
.sbss2 : { *(.sbss2) } >RAM
PROVIDE (__SBSS2_END__ = .);
__SBSS_START__ = .;
.bss :
{
bss.start = .;
*(.bss .bss* .gnu.linkonce.b*)
*(.sbss*) *(COMMON)
bss.end = ALIGN(4);
} > RAM
__SBSS_END__ = .;
bss.size = bss.end - bss.start;
PROVIDE(_end = bss.end);
.line 0 : { *(.line) }
.debug 0 : { *(.debug) }
.debug_sfnames 0 : { *(.debug_sfnames) }
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_pubnames 0 : { *(.debug_pubnames) }
.debug_aranges 0 : { *(.debug_aranges) }
.debug_aregion 0 : { *(.debug_aregion) }
.debug_macinfo 0 : { *(.debug_macinfo) }
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
}

View File

@@ -0,0 +1,56 @@
/* set_vector
*
* This routine installs an interrupt vector on the target Board/CPU.
* This routine is allowed to be as board dependent as necessary.
*
* INPUT:
* handler - interrupt handler entry point
* vector - vector number
* type - 0 indicates raw hardware connect
* 1 indicates RTEMS interrupt connect
*
* RETURNS:
* address of previous interrupt handler
*
* Author: Andrew Bray <andy@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/libbsp/no_cpu/no_bsp/startup/setvec.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.rtems.com/license/LICENSE.
*
* $Id$
*/
#include <rtems.h>
#include <bsp.h>
rtems_isr_entry set_vector( /* returns old vector */
rtems_isr_entry handler, /* isr routine */
rtems_vector_number vector, /* vector number */
int type /* RTEMS or RAW intr */
)
{
rtems_isr_entry previous_isr;
rtems_interrupt_catch( handler, vector, (rtems_isr_entry *) &previous_isr );
return previous_isr;
}

View File

@@ -0,0 +1,63 @@
/*
* asm_utils.s
*
* $Id$
*
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
*
* This file contains the low-level support for moving exception
* exception code to appropriate location.
*
*/
#include <rtems/asm.h>
#include <rtems/score/cpu.h>
.globl codemove
codemove:
.type codemove,@function
/* r3 dest, r4 src, r5 length in bytes, r6 cachelinesize */
cmplw cr1,r3,r4
addi r0,r5,3
srwi. r0,r0,2
beq cr1,4f /* In place copy is not necessary */
beq 7f /* Protect against 0 count */
mtctr r0
bge cr1,2f
la r8,-4(r4)
la r7,-4(r3)
1: lwzu r0,4(r8)
stwu r0,4(r7)
bdnz 1b
b 4f
2: slwi r0,r0,2
add r8,r4,r0
add r7,r3,r0
3: lwzu r0,-4(r8)
stwu r0,-4(r7)
bdnz 3b
/* Now flush the cache: note that we must start from a cache aligned
* address. Otherwise we might miss one cache line.
*/
4: cmpwi r6,0
add r5,r3,r5
beq 7f /* Always flush prefetch queue in any case */
subi r0,r6,1
andc r3,r3,r0
mr r4,r3
5: cmplw r4,r5
dcbst 0,r4
add r4,r4,r6
blt 5b
sync /* Wait for all dcbst to complete on bus */
mr r4,r3
6: cmplw r4,r5
icbi 0,r4
add r4,r4,r6
blt 6b
7: sync /* Wait for all icbi to complete on bus */
isync
blr

View File

@@ -0,0 +1,501 @@
/*
* raw_exception.c - This file contains implementation of C function to
* Instantiate 60x ppc primary exception entries.
* More detailed information can be found on motorola
* site and more precisely in the following book :
*
* MPC750
* Risc Microporcessor User's Manual
* Motorola REF : MPC750UM/AD 8/97
*
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
* Canon Centre Recherche France.
*
* Enhanced by Jay Kulpinski <jskulpin@eng01.gdds.com>
* to support 603, 603e, 604, 604e exceptions
*
* moved to "libcpu/powerpc/new-exceptions and consolidated
* by Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
* to be common for all PPCs with new excpetions
*
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* $Id$
*/
#include <rtems/system.h>
#include <rtems/score/powerpc.h>
#include <rtems/bspIo.h>
#include <libcpu/raw_exception.h>
#include <libcpu/cpuIdent.h>
#include <string.h>
static rtems_raw_except_connect_data* raw_except_table;
static rtems_raw_except_connect_data default_raw_except_entry;
static rtems_raw_except_global_settings* local_settings;
void * codemove(void *, const void *, unsigned int, unsigned long);
static void* ppc_get_vector_addr(rtems_vector vector)
{
unsigned vaddr;
extern rtems_cpu_table Cpu_table;
switch(vector) {
/*
* some vectors are located at odd addresses and only available
* on some CPU derivates. this construct will handle them
* if available
*/
#if defined(PPC_HAS_60X_VECTORS)
/* Special case; altivec unavailable doesn't fit :-( */
case ASM_VEC_VECTOR:
vaddr = ASM_VEC_VECTOR_OFFSET;
break;
#endif
#if defined(ASM_PIT_VECTOR)
case ASM_PIT_VECTOR:
vaddr = ASM_PIT_VECTOR_OFFSET;
break;
#endif
#if defined(ASM_FIT_VECTOR)
case ASM_FIT_VECTOR:
vaddr = ASM_FIT_VECTOR_OFFSET;
break;
#endif
#if defined(ASM_WDOG_VECTOR)
case ASM_WDOG_VECTOR:
vaddr = ASM_WDOG_VECTOR_OFFSET;
break;
#endif
default:
vaddr = ((unsigned)vector) << 8;
break;
}
if ( Cpu_table.exceptions_in_RAM )
return ((void*) vaddr);
return ((void*) (vaddr + 0xfff00000));
}
#if ( defined(mpc860) || defined(mpc821) )
int mpc860_vector_is_valid(rtems_vector vector)
{
switch(vector) {
case ASM_RESET_VECTOR: /* fall through */
case ASM_MACH_VECTOR:
case ASM_PROT_VECTOR:
case ASM_ISI_VECTOR:
case ASM_EXT_VECTOR:
case ASM_ALIGN_VECTOR:
case ASM_PROG_VECTOR:
case ASM_FLOAT_VECTOR:
case ASM_DEC_VECTOR:
case ASM_SYS_VECTOR:
case ASM_TRACE_VECTOR:
case ASM_FLOATASSIST_VECTOR:
case ASM_SOFTEMUL_VECTOR:
case ASM_ITLBMISS_VECTOR:
case ASM_DTLBMISS_VECTOR:
case ASM_ITLBERROR_VECTOR:
case ASM_DTLBERROR_VECTOR:
case ASM_DBREAK_VECTOR:
case ASM_IBREAK_VECTOR:
case ASM_PERIFBREAK_VECTOR:
case ASM_DEVPORT_VECTOR:
return 1;
default: return 0;
}
}
#endif
#if (defined(mpc555) || defined(mpc505))
int ppc_vector_is_valid(rtems_vector vector)
{
switch (current_ppc_cpu) {
case PPC_5XX:
switch(vector) {
case ASM_RESET_VECTOR:
case ASM_MACH_VECTOR:
case ASM_EXT_VECTOR:
case ASM_ALIGN_VECTOR:
case ASM_PROG_VECTOR:
case ASM_FLOAT_VECTOR:
case ASM_DEC_VECTOR:
case ASM_SYS_VECTOR:
case ASM_TRACE_VECTOR:
case ASM_FLOATASSIST_VECTOR:
case ASM_SOFTEMUL_VECTOR:
case ASM_IPROT_VECTOR:
case ASM_DPROT_VECTOR:
case ASM_DBREAK_VECTOR:
case ASM_IBREAK_VECTOR:
case ASM_MEBREAK_VECTOR:
case ASM_NMEBREAK_VECTOR:
return 1;
default:
return 0;
}
default:
printk("Please complete libcpu/powerpc/shared/new-exceptions/raw_exception.c\n");
printk("current_ppc_cpu = %x\n", current_ppc_cpu);
return 0;
}
}
#endif
#if defined(ppc405)
int ppc405_vector_is_valid(rtems_vector vector)
{
switch(vector) {
case ASM_RESET_VECTOR: /* fall through */
case ASM_MACH_VECTOR:
case ASM_PROT_VECTOR:
case ASM_ISI_VECTOR:
case ASM_EXT_VECTOR:
case ASM_ALIGN_VECTOR:
case ASM_PROG_VECTOR:
case ASM_SYS_VECTOR:
case ASM_PIT_VECTOR:
case ASM_ITLBMISS_VECTOR:
case ASM_DTLBMISS_VECTOR:
return 1;
default: return 0;
}
}
#endif /* defined(ppc405) */
#if defined(PPC_HAS_60X_VECTORS) /* 60x style cpu types */
int altivec_vector_is_valid(rtems_vector vector)
{
switch(vector) {
case ASM_VEC_VECTOR:
case ASM_VEC_ASSIST_VECTOR:
return 1;
default:
break;
}
return 0;
}
int mpc750_vector_is_valid(rtems_vector vector)
{
switch(vector) {
case ASM_RESET_VECTOR: /* fall through */
case ASM_MACH_VECTOR:
case ASM_PROT_VECTOR:
case ASM_ISI_VECTOR:
case ASM_EXT_VECTOR:
case ASM_ALIGN_VECTOR:
case ASM_PROG_VECTOR:
case ASM_FLOAT_VECTOR:
case ASM_DEC_VECTOR:
case ASM_SYS_VECTOR:
case ASM_TRACE_VECTOR:
case ASM_ADDR_VECTOR:
case ASM_SYSMGMT_VECTOR:
case ASM_ITM_VECTOR:
return 1;
default: return 0;
}
}
int PSIM_vector_is_valid(rtems_vector vector)
{
switch(vector) {
case ASM_RESET_VECTOR: /* fall through */
case ASM_MACH_VECTOR:
case ASM_PROT_VECTOR:
case ASM_ISI_VECTOR:
case ASM_EXT_VECTOR:
case ASM_ALIGN_VECTOR:
case ASM_PROG_VECTOR:
case ASM_FLOAT_VECTOR:
case ASM_DEC_VECTOR:
return 1;
case ASM_SYS_VECTOR:
return 0;
case ASM_TRACE_VECTOR:
return 1;
case ASM_PERFMON_VECTOR:
return 0;
case ASM_IMISS_VECTOR: /* fall through */
case ASM_DLMISS_VECTOR:
case ASM_DSMISS_VECTOR:
case ASM_ADDR_VECTOR:
case ASM_SYSMGMT_VECTOR:
return 1;
case ASM_ITM_VECTOR:
return 0;
}
return 0;
}
int mpc603_vector_is_valid(rtems_vector vector)
{
switch(vector) {
case ASM_RESET_VECTOR: /* fall through */
case ASM_MACH_VECTOR:
case ASM_PROT_VECTOR:
case ASM_ISI_VECTOR:
case ASM_EXT_VECTOR:
case ASM_ALIGN_VECTOR:
case ASM_PROG_VECTOR:
case ASM_FLOAT_VECTOR:
case ASM_DEC_VECTOR:
case ASM_SYS_VECTOR:
case ASM_TRACE_VECTOR:
return 1;
case ASM_PERFMON_VECTOR:
return 0;
case ASM_IMISS_VECTOR: /* fall through */
case ASM_DLMISS_VECTOR:
case ASM_DSMISS_VECTOR:
case ASM_ADDR_VECTOR:
case ASM_SYSMGMT_VECTOR:
return 1;
case ASM_ITM_VECTOR:
return 0;
}
return 0;
}
int mpc604_vector_is_valid(rtems_vector vector)
{
switch(vector) {
case ASM_RESET_VECTOR: /* fall through */
case ASM_MACH_VECTOR:
case ASM_PROT_VECTOR:
case ASM_ISI_VECTOR:
case ASM_EXT_VECTOR:
case ASM_ALIGN_VECTOR:
case ASM_PROG_VECTOR:
case ASM_FLOAT_VECTOR:
case ASM_DEC_VECTOR:
case ASM_SYS_VECTOR:
case ASM_TRACE_VECTOR:
case ASM_PERFMON_VECTOR:
return 1;
case ASM_IMISS_VECTOR: /* fall through */
case ASM_DLMISS_VECTOR:
case ASM_DSMISS_VECTOR:
return 0;
case ASM_ADDR_VECTOR: /* fall through */
case ASM_SYSMGMT_VECTOR:
return 1;
case ASM_ITM_VECTOR:
return 0;
}
return 0;
}
#endif /* 60x style cpu types */
int ppc_vector_is_valid(rtems_vector vector)
{
switch (current_ppc_cpu) {
#if defined(PPC_HAS_60X_VECTORS)
case PPC_7400:
if ( altivec_vector_is_valid(vector) )
return 1;
/* else fall thru */
case PPC_750:
if (!mpc750_vector_is_valid(vector)) {
return 0;
}
break;
case PPC_7455: /* Kate Feng */
case PPC_7457:
if ( altivec_vector_is_valid(vector) )
return 1;
/* else fall thru */
case PPC_604:
case PPC_604e:
case PPC_604r:
if (!mpc604_vector_is_valid(vector)) {
return 0;
}
break;
case PPC_603:
case PPC_603e:
case PPC_603le:
case PPC_603ev:
case PPC_8260:
/* case PPC_8240: -- same value as 8260 */
case PPC_8245:
if (!mpc603_vector_is_valid(vector)) {
return 0;
}
break;
case PPC_PSIM:
if (!PSIM_vector_is_valid(vector)) {
return 0;
}
break;
#endif
#if ( defined(mpc860) || defined(mpc821) )
case PPC_860:
if (!mpc860_vector_is_valid(vector)) {
return 0;
}
break;
#endif
#if defined(ppc405)
case PPC_405:
if (!ppc405_vector_is_valid(vector)) {
return 0;
}
break;
#endif
default:
printk("Please complete "
"libcpu/powerpc/new-exceptions/raw_exception.c\n"
"current_ppc_cpu = %x\n", current_ppc_cpu);
return 0;
}
return 1;
}
int ppc_set_exception (const rtems_raw_except_connect_data* except)
{
unsigned int level;
if (!ppc_vector_is_valid(except->exceptIndex)) {
printk("ppc_set_exception: vector %d is not valid\n",
except->exceptIndex);
return 0;
}
/*
* Check if default handler is actually connected. If not issue an error.
* You must first get the current handler via mpc60x_get_current_exception
* and then disconnect it using mpc60x_delete_exception.
* RATIONALE : to always have the same transition by forcing the user
* to get the previous handler before accepting to disconnect.
*/
if (memcmp(ppc_get_vector_addr(except->exceptIndex),
(void*)default_raw_except_entry.hdl.raw_hdl,
default_raw_except_entry.hdl.raw_hdl_size)) {
printk("ppc_set_exception: raw vector not installed\n");
return 0;
}
_CPU_ISR_Disable(level);
raw_except_table [except->exceptIndex] = *except;
codemove((void*)ppc_get_vector_addr(except->exceptIndex),
except->hdl.raw_hdl,
except->hdl.raw_hdl_size,
PPC_CACHE_ALIGNMENT);
except->on(except);
_CPU_ISR_Enable(level);
return 1;
}
int ppc_get_current_exception (rtems_raw_except_connect_data* except)
{
if (!ppc_vector_is_valid(except->exceptIndex)){
return 0;
}
*except = raw_except_table [except->exceptIndex];
return 1;
}
int ppc_delete_exception (const rtems_raw_except_connect_data* except)
{
unsigned int level;
if (!ppc_vector_is_valid(except->exceptIndex)){
return 0;
}
/*
* Check if handler passed is actually connected. If not issue an error.
* You must first get the current handler via ppc_get_current_exception
* and then disconnect it using ppc_delete_exception.
* RATIONALE : to always have the same transition by forcing the user
* to get the previous handler before accepting to disconnect.
*/
if (memcmp(ppc_get_vector_addr(except->exceptIndex),
(void*)except->hdl.raw_hdl,
except->hdl.raw_hdl_size)) {
return 0;
}
_CPU_ISR_Disable(level);
except->off(except);
codemove((void*)ppc_get_vector_addr(except->exceptIndex),
default_raw_except_entry.hdl.raw_hdl,
default_raw_except_entry.hdl.raw_hdl_size,
PPC_CACHE_ALIGNMENT);
raw_except_table[except->exceptIndex] = default_raw_except_entry;
raw_except_table[except->exceptIndex].exceptIndex = except->exceptIndex;
_CPU_ISR_Enable(level);
return 1;
}
/*
* Exception global init.
*/
int ppc_init_exceptions (rtems_raw_except_global_settings* config)
{
unsigned i;
unsigned int level;
/*
* store various accelerators
*/
raw_except_table = config->rawExceptHdlTbl;
local_settings = config;
default_raw_except_entry = config->defaultRawEntry;
_CPU_ISR_Disable(level);
for (i=0; i <= LAST_VALID_EXC; i++) {
if (!ppc_vector_is_valid(i)){
continue;
}
codemove((void*)ppc_get_vector_addr(i),
raw_except_table[i].hdl.raw_hdl,
raw_except_table[i].hdl.raw_hdl_size,
PPC_CACHE_ALIGNMENT);
if (raw_except_table[i].hdl.raw_hdl != default_raw_except_entry.hdl.raw_hdl) {
raw_except_table[i].on(&raw_except_table[i]);
}
else {
raw_except_table[i].off(&raw_except_table[i]);
}
}
_CPU_ISR_Enable(level);
return 1;
}
int ppc_get_exception_config (rtems_raw_except_global_settings** config)
{
*config = local_settings;
return 1;
}

View File

@@ -0,0 +1,324 @@
/*
* raw_execption.h
*
* This file contains implementation of C function to
* Instantiate 60x ppc primary exception entries.
* More detailed information can be found on motorola
* site and more precisely in the following book :
*
* MPC750
* Risc Microporcessor User's Manual
* Mtorola REF : MPC750UM/AD 8/97
*
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
* Canon Centre Recherche France.
*
* Enhanced by Jay Kulpinski <jskulpin@eng01.gdds.com>
* to support 603, 603e, 604, 604e exceptions
*
* moved to "libcpu/powerpc/new-exceptions and consolidated
* by Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
* to be common for all PPCs with new excpetions
*
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* $Id$
*/
#ifndef _LIBCPU_RAW_EXCEPTION_H
#define _LIBCPU_RAW_EXCEPTION_H
#include <rtems/powerpc/powerpc.h>
/*
* find out, whether we want to (re)enable the MMU in the assembly code
* FIXME: move this to a better location
*/
#if (defined(ppc403) || defined(ppc405))
#define PPC_USE_MMU 0
#else
#define PPC_USE_MMU 1
#endif
/*
* Exception Vectors and offsets as defined in the MCP750 manual
* used by most PPCs
*/
#define ASM_RESET_VECTOR 0x01
#define ASM_RESET_VECTOR_OFFSET (ASM_RESET_VECTOR << 8)
#define ASM_MACH_VECTOR 0x02
#define ASM_MACH_VECTOR_OFFSET (ASM_MACH_VECTOR << 8)
#define ASM_PROT_VECTOR 0x03
#define ASM_PROT_VECTOR_OFFSET (ASM_PROT_VECTOR << 8)
#define ASM_ISI_VECTOR 0x04
#define ASM_ISI_VECTOR_OFFSET (ASM_ISI_VECTOR << 8)
#define ASM_EXT_VECTOR 0x05
#define ASM_EXT_VECTOR_OFFSET (ASM_EXT_VECTOR << 8)
#define ASM_ALIGN_VECTOR 0x06
#define ASM_ALIGN_VECTOR_OFFSET (ASM_ALIGN_VECTOR << 8)
#define ASM_PROG_VECTOR 0x07
#define ASM_PROG_VECTOR_OFFSET (ASM_PROG_VECTOR << 8)
#define ASM_FLOAT_VECTOR 0x08
#define ASM_FLOAT_VECTOR_OFFSET (ASM_FLOAT_VECTOR << 8)
#define ASM_DEC_VECTOR 0x09
#define ASM_DEC_VECTOR_OFFSET (ASM_DEC_VECTOR << 8)
/* Bummer: Altivec unavailable doesn't fit into this scheme... (0xf20).
* We'd like to avoid reserved vectors but OTOH we don't want to use
* just an available high number because tables (and copies) are of
* size LAST_VALID_EXC.
* So until there is a CPU that uses 0xA we'll just use that :-(
*/
#define ASM_VEC_VECTOR 0x0A
#define ASM_VEC_VECTOR_OFFSET (0xf20)
#define ASM_SYS_VECTOR 0x0C
#define ASM_SYS_VECTOR_OFFSET (ASM_SYS_VECTOR << 8)
#define ASM_TRACE_VECTOR 0x0D
#define ASM_TRACE_VECTOR_OFFSET (ASM_TRACE_VECTOR << 8)
#if defined(ppc405)
/*
* vectors for PPC405
*/
#define ASM_CRIT_VECTOR ASM_RESET_VECTOR
#define ASM_CRIT_VECTOR_OFFSET (ASM_CRIT_VECTOR << 8)
#define ASM_PIT_VECTOR 0x10
#define ASM_PIT_VECTOR_OFFSET (ASM_PIT_VECTOR << 8)
#define ASM_ITLBMISS_VECTOR 0x11
#define ASM_ITLBMISS_VECTOR_OFFSET (ASM_ITLBMISS_VECTOR << 8)
#define ASM_DTLBMISS_VECTOR 0x12
#define ASM_DTLBMISS_VECTOR_OFFSET (ASM_DTLBMISS_VECTOR << 8)
#define ASM_FIT_VECTOR 0x13
#define ASM_FIT_VECTOR_OFFSET (0x1010)
#define ASM_WDOG_VECTOR 0x14
#define ASM_WDOG_VECTOR_OFFSET (0x1020)
#define LAST_VALID_EXC ASM_WDOG_VECTOR
/*
* bit mask of all exception vectors, that are handled
* as "critical" exsceptions (using SRR2/SRR3/rfci)
* this value will be evaluated in the default exception entry/exit
* code to determine, whether to use SRR0/SRR1/rfi or SRR2/SRR3/rfci
*/
#define ASM_VECTORS_CRITICAL \
(( 1 << (31-ASM_CRIT_VECTOR)) \
|(1 << (31-ASM_MACH_VECTOR)) \
|(1 << (31-ASM_WDOG_VECTOR)))
#elif ( defined(mpc860) || defined(mpc821) )
/*
* vectors for MPC8xx
*/
/*
* FIXME: even more vector names might get used in common,
* but the names have diverged between different PPC families
*/
#define ASM_FLOATASSIST_VECTOR 0x0E
#define ASM_FLOATASSIST_VECTOR_OFFSET (ASM_FLOATASSIST_VECTOR << 8)
#define ASM_SOFTEMUL_VECTOR 0x10
#define ASM_SOFTEMUL_VECTOR_OFFSET (ASM_SOFTEMUL_VECTOR << 8)
#define ASM_ITLBMISS_VECTOR 0x11
#define ASM_ITLBMISS_VECTOR_OFFSET (ASM_ITLBMISS_VECTOR << 8)
#define ASM_DTLBMISS_VECTOR 0x12
#define ASM_DTLBMISS_VECTOR_OFFSET (ASM_DTLBMISS_VECTOR << 8)
#define ASM_ITLBERROR_VECTOR 0x13
#define ASM_ITLBERROR_VECTOR_OFFSET (ASM_ITLBERROR_VECTOR << 8)
#define ASM_DTLBERROR_VECTOR 0x14
#define ASM_DTLBERROR_VECTOR_OFFSET (ASM_DTLBERROR_VECTOR << 8)
#define ASM_DBREAK_VECTOR 0x1C
#define ASM_DBREAK_VECTOR_OFFSET (ASM_DBREAK_VECTOR << 8)
#define ASM_IBREAK_VECTOR 0x1D
#define ASM_IBREAK_VECTOR_OFFSET (ASM_IBREAK_VECTOR << 8)
#define ASM_PERIFBREAK_VECTOR 0x1E
#define ASM_PERIFBREAK_VECTOR_OFFSET (ASM_PERIFBREAK_VECTOR << 8)
#define ASM_DEVPORT_VECTOR 0x1F
#define ASM_DEVPORT_VECTOR_OFFSET (ASM_DEVPORT_VECTOR_OFFSET << 8)
#define LAST_VALID_EXC ASM_DEVPORT_VECTOR
#elif (defined(mpc555) || defined(mpc505))
/*
* vectorx for MPC5xx
*/
#define ASM_FLOATASSIST_VECTOR 0x0E
#define ASM_SOFTEMUL_VECTOR 0x10
#define ASM_IPROT_VECTOR 0x13
#define ASM_DPROT_VECTOR 0x14
#define ASM_DBREAK_VECTOR 0x1C
#define ASM_IBREAK_VECTOR 0x1D
#define ASM_MEBREAK_VECTOR 0x1E
#define ASM_NMEBREAK_VECTOR 0x1F
#define LAST_VALID_EXC ASM_NMEBREAK_VECTOR
#else /* 60x style cpu types */
#define PPC_HAS_60X_VECTORS
#define ASM_PERFMON_VECTOR 0x0F
#define ASM_PERFMON_VECTOR_OFFSET (ASM_PERFMON_VECTOR << 8)
#define ASM_IMISS_VECTOR 0x10
#define ASM_DLMISS_VECTOR 0x11
#define ASM_DSMISS_VECTOR 0x12
#define ASM_ADDR_VECTOR 0x13
#define ASM_ADDR_VECTOR_OFFSET (ASM_ADDR_VECTOR << 8)
#define ASM_SYSMGMT_VECTOR 0x14
#define ASM_SYSMGMT_VECTOR_OFFSET (ASM_SYSMGMT_VECTOR << 8)
#define ASM_VEC_ASSIST_VECTOR 0x16
#define ASM_VEC_ASSIST_VECTOR_OFFSET (ASM_VEC_ASSIST_VECTOR << 8)
#define ASM_ITM_VECTOR 0x17
#define ASM_ITM_VECTOR_OFFSET (ASM_ITM_VECTOR << 8)
#define LAST_VALID_EXC ASM_ITM_VECTOR
#endif
/*
* bits to be set in MSR in exception entry code
*/
#if ( PPC_HAS_RI) && ( PPC_USE_MMU)
#define PPC_MSR_EXC_BITS (PPC_MSR_RI | PPC_MSR_DR | PPC_MSR_IR)
#elif ( PPC_HAS_RI) && (!PPC_USE_MMU)
#define PPC_MSR_EXC_BITS (PPC_MSR_RI)
#elif (!PPC_HAS_RI) && ( PPC_USE_MMU)
#define PPC_MSR_EXC_BITS ( PPC_MSR_DR | PPC_MSR_IR)
#else
#endif
#ifndef ASM
/*
* Type definition for raw exceptions.
*/
typedef unsigned char rtems_vector;
struct __rtems_raw_except_connect_data__;
typedef void (*rtems_raw_except_func) (void);
typedef unsigned long rtems_raw_except_hdl_size;
typedef struct {
rtems_vector vector;
rtems_raw_except_func raw_hdl;
rtems_raw_except_hdl_size raw_hdl_size;
}rtems_raw_except_hdl;
typedef void (*rtems_raw_except_enable) (const struct __rtems_raw_except_connect_data__*);
typedef void (*rtems_raw_except_disable) (const struct __rtems_raw_except_connect_data__*);
typedef int (*rtems_raw_except_is_enabled) (const struct __rtems_raw_except_connect_data__*);
typedef struct __rtems_raw_except_connect_data__{
/*
* Exception vector (As defined in the manual)
*/
rtems_vector exceptIndex;
/*
* Exception raw handler. See comment on handler properties below in function prototype.
*/
rtems_raw_except_hdl hdl;
/*
* function for enabling raw exceptions. In order to be consistent
* with the fact that the raw connexion can defined in the
* libcpu library, this library should have no knowledge of
* board specific hardware to manage exceptions and thus the
* "on" routine must enable the except at processor level only.
*
*/
rtems_raw_except_enable on;
/*
* function for disabling raw exceptions. In order to be consistent
* with the fact that the raw connexion can defined in the
* libcpu library, this library should have no knowledge of
* board specific hardware to manage exceptions and thus the
* "on" routine must disable the except both at device and PIC level.
*
*/
rtems_raw_except_disable off;
/*
* function enabling to know what exception may currently occur
*/
rtems_raw_except_is_enabled isOn;
}rtems_raw_except_connect_data;
typedef struct {
/*
* size of all the table fields (*Tbl) described below.
*/
unsigned int exceptSize;
/*
* Default handler used when disconnecting exceptions.
*/
rtems_raw_except_connect_data defaultRawEntry;
/*
* Table containing initials/current value.
*/
rtems_raw_except_connect_data* rawExceptHdlTbl;
}rtems_raw_except_global_settings;
/*
* C callable function enabling to set up one raw idt entry
*/
extern int ppc_set_exception (const rtems_raw_except_connect_data*);
/*
* C callable function enabling to get one current raw idt entry
*/
extern int ppc_get_current_exception (rtems_raw_except_connect_data*);
/*
* C callable function enabling to remove one current raw idt entry
*/
extern int ppc_delete_exception (const rtems_raw_except_connect_data*);
/*
* C callable function enabling to check if vector is valid
*/
extern int ppc_vector_is_valid(rtems_vector vector);
/*
* Exception global init.
*/
extern int ppc_init_exceptions (rtems_raw_except_global_settings* config);
extern int ppc_get_exception_config (rtems_raw_except_global_settings** config);
# endif /* ASM */
#endif

View File

@@ -0,0 +1,292 @@
/* ictrl.c
*
* This routine installs and handles external interrupt vectors for
* PowerPC 403 CPU built-in external interrupt controller
*
* Author: Thomas Doerfler <td@imd.m.isar.de>
*
* COPYRIGHT (c) 1998 by IMD, Puchheim, Germany
*
* 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 IMD not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* IMD makes no representations about the suitability
* of this software for any purpose.
*
* Modifications for PPC405GP by Dennis Ehlin
*
*/
#include "ictrl.h"
#include <rtems.h>
#include <rtems/libio.h>
#include <stdlib.h> /* for atexit() */
/*
* ISR vector table to dispatch external interrupts
*/
rtems_isr_entry ictrl_vector_table[PPC_IRQ_EXT_MAX];
/*
*
* some utilities to access the EXI* registers
*
*/
/*
* clear bits in EXISR that have a bit set in mask
*/
#if defined(ppc405)
RTEMS_INLINE_ROUTINE void
clr_exisr(uint32_t mask)
{
asm volatile ("mtdcr 0xC0,%0"::"r" (mask));/*EXISR*/
}
/*
* get value of EXISR
*/
RTEMS_INLINE_ROUTINE uint32_t
get_exisr(void)
{
uint32_t val;
asm volatile ("mfdcr %0,0xC0":"=r" (val));/*EXISR*/
return val;
}
/*
* get value of EXIER
*/
RTEMS_INLINE_ROUTINE uint32_t
get_exier(void)
{
uint32_t val;
asm volatile ("mfdcr %0,0xC2":"=r" (val));/*EXIER*/
return val;
}
/*
* set value of EXIER
*/
RTEMS_INLINE_ROUTINE void
set_exier(uint32_t val)
{
asm volatile ("mtdcr 0xC2,%0"::"r" (val));/*EXIER*/
}
#else /* not ppc405 */
RTEMS_INLINE_ROUTINE void
clr_exisr(uint32_t mask)
{
asm volatile ("mtdcr 0x40,%0"::"r" (mask));/*EXISR*/
}
/*
* get value of EXISR
*/
RTEMS_INLINE_ROUTINE uint32_t
get_exisr(void)
{
uint32_t val;
asm volatile ("mfdcr %0,0x40":"=r" (val));/*EXISR*/
return val;
}
/*
* get value of EXIER
*/
RTEMS_INLINE_ROUTINE uint32_t
get_exier(void)
{
uint32_t val;
asm volatile ("mfdcr %0,0x42":"=r" (val));/*EXIER*/
return val;
}
/*
* set value of EXIER
*/
RTEMS_INLINE_ROUTINE void
set_exier(uint32_t val)
{
asm volatile ("mtdcr 0x42,%0"::"r" (val));/*EXIER*/
}
#endif /* ppc405 */
/*
* enable an external interrupt, make this interrupt consistent
*/
RTEMS_INLINE_ROUTINE void
enable_ext_irq( uint32_t mask)
{
uint32_t isrlvl;
_CPU_ISR_Disable(isrlvl);
set_exier(get_exier() | ((mask)&PPC_EXI_MASK));
_CPU_ISR_Enable(isrlvl);
}
/*
* disable an external interrupt, make this interrupt consistent
*/
RTEMS_INLINE_ROUTINE void
disable_ext_irq( uint32_t mask)
{
uint32_t isrlvl;
_CPU_ISR_Disable(isrlvl);
set_exier(get_exier() & ~(mask) & PPC_EXI_MASK);
_CPU_ISR_Enable(isrlvl);
}
/*
*
* this function is called, when a external interrupt is present and
* enabled but there is no handler installed. It will clear
* the corresponding enable bits and call the spurious handler
* present in the CPU Configuration Table, if any.
*
*/
void
ictrl_spurious_handler(uint32_t spurious_mask,
CPU_Interrupt_frame *cpu_frame)
{
int v;
for (v=0; v < PPC_IRQ_EXT_MAX; v++) {
if (VEC_TO_EXMSK(v) & spurious_mask) {
clr_exisr(VEC_TO_EXMSK(v));
disable_ext_irq(VEC_TO_EXMSK(v));
#if 0
printf("spurious external interrupt: %d at pc 0x%x; disabling\n",
vector, cpu_frame->Interrupt.pcoqfront);
#endif
if (rtems_cpu_configuration_get_spurious_handler()) {
rtems_cpu_configuration_get_spurious_handler()(v + PPC_IRQ_EXT_BASE,cpu_frame);
}
}
}
}
/*
* ISR Handler: this is called from the primary exception dispatcher
*/
void
ictrl_isr(rtems_vector_number vector,CPU_Interrupt_frame *cpu_frame)
{
uint32_t istat,
mask,
global_vec;
int exvec;
rtems_isr_entry handler;
istat = get_exisr() & get_exier() & PPC_EXI_MASK;
/* FIXME: this may be speeded up using cntlzw instruction */
for (exvec = 0;exvec < PPC_IRQ_EXT_MAX;exvec++) {
mask = VEC_TO_EXMSK(exvec);
if (0 != (istat & mask)) {
/*clr_exisr(mask); too early to ack*/
handler = ictrl_vector_table[exvec];
if (handler) {
istat &= ~mask;
global_vec = exvec + PPC_IRQ_EXT_BASE;
(handler)(global_vec);
}
clr_exisr(mask);/* now we can ack*/
}
}
if (istat != 0) { /* anything left? then we have a spurious interrupt */
ictrl_spurious_handler(istat,cpu_frame);
}
}
/*
*
* the following functions form the user interface
*
*/
/*
*
* install a user vector for one of the external interrupt sources
*
*/
rtems_status_code
ictrl_set_vector(rtems_isr_entry new_handler,
uint32_t vector,
rtems_isr_entry *old_handler
)
{
/*
* We put the actual user ISR address in 'ictrl_vector_table'. This will
* be used by the _ictrl_isr so the user gets control.
*/
/* check for valid vector range */
if ((vector >= PPC_IRQ_EXT_BASE) &&
(vector < PPC_IRQ_EXT_BASE + PPC_IRQ_EXT_MAX)) {
/* return old handler entry */
*old_handler = ictrl_vector_table[vector - PPC_IRQ_EXT_BASE];
if (new_handler != NULL) {
/* store handler function... */
ictrl_vector_table[vector - PPC_IRQ_EXT_BASE] = new_handler;
/* then enable it in EXIER register */
enable_ext_irq(VEC_TO_EXMSK(vector - PPC_IRQ_EXT_BASE));
}
else { /* new_handler == NULL */
/* then disable it in EXIER register */
disable_ext_irq(VEC_TO_EXMSK(vector - PPC_IRQ_EXT_BASE));
ictrl_vector_table[vector - PPC_IRQ_EXT_BASE] = NULL;
}
return RTEMS_SUCCESSFUL;
}
else {
return RTEMS_INVALID_NUMBER;
}
}
/*
* Called via atexit()
* deactivate the interrupt controller
*/
void
ictrl_exit(void)
{
/* mark them all unused */
disable_ext_irq(~0);
clr_exisr(~0);
}
/*
* activate the interrupt controller
*/
rtems_status_code
ictrl_init(void)
{
proc_ptr dummy;
/* mark them all unused */
disable_ext_irq(~0);
clr_exisr(~0);
/* install the external interrupt handler */
_CPU_ISR_install_vector(PPC_IRQ_EXTERNAL,
ictrl_isr,
&dummy);
atexit(ictrl_exit);
return RTEMS_SUCCESSFUL;
}

View File

@@ -0,0 +1,95 @@
/* ictrl.h
*
* This file contains definitions and declarations for the
* PowerPC 403 CPU built-in external interrupt controller
*
*
* Author: Thomas Doerfler <td@imd.m.isar.de>
*
* COPYRIGHT (c) 1998 by IMD, Puchheim, Germany
*
* 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 IMD not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* IMD makes no representations about the suitability
* of this software for any purpose.
*
* Modifications for PPC405GP by Dennis Ehlin
*
*/
#ifndef _ICTRL_H
#define _ICTRL_H
#include <rtems.h>
#include <rtems/system.h>
#include <rtems/score/isr.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* definitions for second level IRQ handler support
* External Interrupts via EXTERNAL/EISR
*/
#define PPC_IRQ_EXT_BASE (PPC_IRQ_LAST+1)
/* mask for external interrupt status in EXIER/EXISR register */
/* note: critical interrupt is in these registers aswell */
#ifndef ppc405
#define PPC_EXI_MASK 0x0FFFFFFF
#else /* ppc405 */
#define PPC_EXI_MASK 0xFFFFFFFF
#endif /* ppc405 */
#ifndef ppc405
#define PPC_IRQ_EXT_SPIR (PPC_IRQ_EXT_BASE+4)
#define PPC_IRQ_EXT_SPIT (PPC_IRQ_EXT_BASE+5)
#else /* ppc405 */
#define PPC_IRQ_EXT_UART0 (PPC_IRQ_EXT_BASE+0)
#define PPC_IRQ_EXT_UART1 (PPC_IRQ_EXT_BASE+1)
#endif /* ppc405 */
#define PPC_IRQ_EXT_JTAGR (PPC_IRQ_EXT_BASE+6)
#define PPC_IRQ_EXT_JTAGT (PPC_IRQ_EXT_BASE+7)
#define PPC_IRQ_EXT_DMA0 (PPC_IRQ_EXT_BASE+8)
#define PPC_IRQ_EXT_DMA1 (PPC_IRQ_EXT_BASE+9)
#define PPC_IRQ_EXT_DMA2 (PPC_IRQ_EXT_BASE+10)
#define PPC_IRQ_EXT_DMA3 (PPC_IRQ_EXT_BASE+11)
#define PPC_IRQ_EXT_0 (PPC_IRQ_EXT_BASE+27)
#define PPC_IRQ_EXT_1 (PPC_IRQ_EXT_BASE+28)
#define PPC_IRQ_EXT_2 (PPC_IRQ_EXT_BASE+29)
#define PPC_IRQ_EXT_3 (PPC_IRQ_EXT_BASE+30)
#define PPC_IRQ_EXT_4 (PPC_IRQ_EXT_BASE+31)
#define PPC_IRQ_EXT_MAX (32)
#define VEC_TO_EXMSK(v) (0x80000000 >> (v))
/*
*
* install a user vector for one of the external interrupt sources
*
*/
rtems_status_code
ictrl_set_vector(rtems_isr_entry new_handler,
uint32_t vector,
rtems_isr_entry *old_handler
);
/*
* activate the interrupt controller
*/
rtems_status_code
ictrl_init(void);
#ifdef __cplusplus
}
#endif
#endif /* _ICTRL_H */
/* end of include file */