diff options
author | Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | 2007-07-04 12:37:36 +0000 |
---|---|---|
committer | Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | 2007-07-04 12:37:36 +0000 |
commit | 862c231785024acbd6c830fb30e0a6a64e6c3318 (patch) | |
tree | fc09530e45e5436192c6286e70b912fbff8bcf16 /c | |
parent | merged individual exception handler code to a common one. (diff) | |
download | rtems-862c231785024acbd6c830fb30e0a6a64e6c3318.tar.bz2 |
added virtex BSP support and some missing files for common PPC
exception handling
Diffstat (limited to 'c')
29 files changed, 5424 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/virtex/ChangeLog b/c/src/lib/libbsp/powerpc/virtex/ChangeLog new file mode 100644 index 0000000000..89b08f5ef0 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/ChangeLog @@ -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 + diff --git a/c/src/lib/libbsp/powerpc/virtex/Makefile.am b/c/src/lib/libbsp/powerpc/virtex/Makefile.am new file mode 100644 index 0000000000..a0695cc434 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/Makefile.am @@ -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 diff --git a/c/src/lib/libbsp/powerpc/virtex/README b/c/src/lib/libbsp/powerpc/virtex/README new file mode 100644 index 0000000000..8c91efa9a6 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/README @@ -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...) + + diff --git a/c/src/lib/libbsp/powerpc/virtex/bsp_specs b/c/src/lib/libbsp/powerpc/virtex/bsp_specs new file mode 100644 index 0000000000..b0c18cde77 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/bsp_specs @@ -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 } + diff --git a/c/src/lib/libbsp/powerpc/virtex/bsp_specs.dl b/c/src/lib/libbsp/powerpc/virtex/bsp_specs.dl new file mode 100644 index 0000000000..24804479a0 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/bsp_specs.dl @@ -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 } + diff --git a/c/src/lib/libbsp/powerpc/virtex/console/consolelite.c b/c/src/lib/libbsp/powerpc/virtex/console/consolelite.c new file mode 100644 index 0000000000..99f40bca02 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/console/consolelite.c @@ -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; + + diff --git a/c/src/lib/libbsp/powerpc/virtex/dlentry/dlentry.S b/c/src/lib/libbsp/powerpc/virtex/dlentry/dlentry.S new file mode 100644 index 0000000000..afca899ef4 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/dlentry/dlentry.S @@ -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 diff --git a/c/src/lib/libbsp/powerpc/virtex/include/bsp.h b/c/src/lib/libbsp/powerpc/virtex/include/bsp.h new file mode 100644 index 0000000000..6ce4d4b1bc --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/include/bsp.h @@ -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 diff --git a/c/src/lib/libbsp/powerpc/virtex/include/bspopts.h.in b/c/src/lib/libbsp/powerpc/virtex/include/bspopts.h.in new file mode 100644 index 0000000000..72e76868df --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/include/bspopts.h.in @@ -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 diff --git a/c/src/lib/libbsp/powerpc/virtex/include/coverhd.h b/c/src/lib/libbsp/powerpc/virtex/include/coverhd.h new file mode 100644 index 0000000000..f39d324eaa --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/include/coverhd.h @@ -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 diff --git a/c/src/lib/libbsp/powerpc/virtex/include/opbintctrl.h b/c/src/lib/libbsp/powerpc/virtex/include/opbintctrl.h new file mode 100644 index 0000000000..f4a1c39bbc --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/include/opbintctrl.h @@ -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 */ diff --git a/c/src/lib/libbsp/powerpc/virtex/include/tm27.h b/c/src/lib/libbsp/powerpc/virtex/include/tm27.h new file mode 100644 index 0000000000..18f3b6b32b --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/include/tm27.h @@ -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 diff --git a/c/src/lib/libbsp/powerpc/virtex/include/xparameters_dflt.h b/c/src/lib/libbsp/powerpc/virtex/include/xparameters_dflt.h new file mode 100644 index 0000000000..6dc91751e0 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/include/xparameters_dflt.h @@ -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 + +/******************************************************************/ + diff --git a/c/src/lib/libbsp/powerpc/virtex/irq/irq.h b/c/src/lib/libbsp/powerpc/virtex/irq/irq.h new file mode 100644 index 0000000000..815fd3e87a --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/irq/irq.h @@ -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 */ diff --git a/c/src/lib/libbsp/powerpc/virtex/irq/irq_init.c b/c/src/lib/libbsp/powerpc/virtex/irq/irq_init.c new file mode 100644 index 0000000000..a3bd21cd31 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/irq/irq_init.c @@ -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"); + } +} + diff --git a/c/src/lib/libbsp/powerpc/virtex/network/xiltemac.c b/c/src/lib/libbsp/powerpc/virtex/network/xiltemac.c new file mode 100644 index 0000000000..a4316148c2 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/network/xiltemac.c @@ -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; +} + diff --git a/c/src/lib/libbsp/powerpc/virtex/network/xiltemac.h b/c/src/lib/libbsp/powerpc/virtex/network/xiltemac.h new file mode 100644 index 0000000000..6a0c821b01 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/network/xiltemac.h @@ -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_*/ diff --git a/c/src/lib/libbsp/powerpc/virtex/opbintctrl/opbintctrl.c b/c/src/lib/libbsp/powerpc/virtex/opbintctrl/opbintctrl.c new file mode 100644 index 0000000000..9d2ed9ac4b --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/opbintctrl/opbintctrl.c @@ -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; +} + diff --git a/c/src/lib/libbsp/powerpc/virtex/preinstall.am b/c/src/lib/libbsp/powerpc/virtex/preinstall.am new file mode 100644 index 0000000000..31983c24d1 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/preinstall.am @@ -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 + diff --git a/c/src/lib/libbsp/powerpc/virtex/startup/bspclean.c b/c/src/lib/libbsp/powerpc/virtex/startup/bspclean.c new file mode 100644 index 0000000000..56699da354 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/startup/bspclean.c @@ -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); +} diff --git a/c/src/lib/libbsp/powerpc/virtex/startup/bspstart.c b/c/src/lib/libbsp/powerpc/virtex/startup/bspstart.c new file mode 100644 index 0000000000..700ac0c812 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/startup/bspstart.c @@ -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(); +} + diff --git a/c/src/lib/libbsp/powerpc/virtex/startup/linkcmds b/c/src/lib/libbsp/powerpc/virtex/startup/linkcmds new file mode 100644 index 0000000000..0e39bf66b7 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/startup/linkcmds @@ -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) } + +} diff --git a/c/src/lib/libbsp/powerpc/virtex/startup/linkcmds.dl b/c/src/lib/libbsp/powerpc/virtex/startup/linkcmds.dl new file mode 100644 index 0000000000..30dd38e63d --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/startup/linkcmds.dl @@ -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) } +} + + diff --git a/c/src/lib/libbsp/powerpc/virtex/startup/setvec.c b/c/src/lib/libbsp/powerpc/virtex/startup/setvec.c new file mode 100644 index 0000000000..af6f68b356 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex/startup/setvec.c @@ -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; +} diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/asm_utils.S b/c/src/lib/libcpu/powerpc/new-exceptions/asm_utils.S new file mode 100644 index 0000000000..45a0f3ea73 --- /dev/null +++ b/c/src/lib/libcpu/powerpc/new-exceptions/asm_utils.S @@ -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 diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/raw_exception.c b/c/src/lib/libcpu/powerpc/new-exceptions/raw_exception.c new file mode 100644 index 0000000000..d412f38008 --- /dev/null +++ b/c/src/lib/libcpu/powerpc/new-exceptions/raw_exception.c @@ -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; +} diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/raw_exception.h b/c/src/lib/libcpu/powerpc/new-exceptions/raw_exception.h new file mode 100644 index 0000000000..1805484f8e --- /dev/null +++ b/c/src/lib/libcpu/powerpc/new-exceptions/raw_exception.h @@ -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 diff --git a/c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.c b/c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.c new file mode 100644 index 0000000000..6a1f810cd0 --- /dev/null +++ b/c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.c @@ -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; +} diff --git a/c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.h b/c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.h new file mode 100644 index 0000000000..4370788108 --- /dev/null +++ b/c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.h @@ -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 */ |