diff options
Diffstat (limited to 'c/src/lib/libbsp/powerpc/dmv177')
34 files changed, 5693 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/dmv177/Makefile.in b/c/src/lib/libbsp/powerpc/dmv177/Makefile.in new file mode 100644 index 0000000000..e2cc7c6b24 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/Makefile.in @@ -0,0 +1,23 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +RTEMS_ROOT = @RTEMS_ROOT@ +PROJECT_ROOT = @PROJECT_ROOT@ +RTEMS_CUSTOM = $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg + +include $(RTEMS_CUSTOM) +include $(PROJECT_ROOT)/make/directory.cfg + +SRCS=README + +all: $(SRCS) + +# wrapup is the one that actually builds and installs the library +# from the individual .rel files built in other directories +SUB_DIRS=include clock console startup start timer \ + tod sonic wrapup diff --git a/c/src/lib/libbsp/powerpc/dmv177/README b/c/src/lib/libbsp/powerpc/dmv177/README new file mode 100644 index 0000000000..1625c4a858 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/README @@ -0,0 +1,50 @@ +# +# $Id$ +# + +BSP NAME: psim +BOARD: PowerPC Simulator +BUS: N/A +CPU FAMILY: ppc +CPU: PowerPC 603, 603e, 604 +COPROCESSORS: N/A +MODE: 32 bit mode + +DEBUG MONITOR: BUG mode (emulates Motorola debug monitor) + +PERIPHERALS +=========== +TIMERS: PPC internal Timebase register + RESOLUTION: ??? +SERIAL PORTS: simulated via bug +REAL-TIME CLOCK: PPC internal Decrementer register +DMA: none +VIDEO: none +SCSI: none +NETWORKING: none + +DRIVER INFORMATION +================== +CLOCK DRIVER: PPC internal +IOSUPP DRIVER: N/A +SHMSUPP: N/A +TIMER DRIVER: PPC internal +TTY DRIVER: PPC internal + +STDIO +===== +PORT: Console port 0 +ELECTRICAL: na +BAUD: na +BITS PER CHARACTER: na +PARITY: na +STOP BITS: na + +Notes +===== + +Based on papyrus bsp which only really supports +the PowerOpen ABI with an ELF assembler. + +Need to Modify external_exception_ISR with correct code to read the vector, +and to clear the interrupt.
\ No newline at end of file diff --git a/c/src/lib/libbsp/powerpc/dmv177/STATUS b/c/src/lib/libbsp/powerpc/dmv177/STATUS new file mode 100644 index 0000000000..394412421e --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/STATUS @@ -0,0 +1,82 @@ +# +# This is a status file for the update effort. +# + +make/custom +=========== +dmv17x.cfg + +TOP +=== +README +Makefile.in +bsp_specs + +clock +===== +clock.c +Makefile.in + +console +======= +Changed console from + duart.c + console.c +To + consolebsp.h + console.c + 85c30.c + tbl85c30.c + +Note: Check the number of serial ports and modify + tbl85c30.c values to indicate the correct values. + +Makefile.in - Modified with new file names. + +timer +======= +timer.c +Makefile.in + +include +======= +chain.h +dmv170.h +bsp.h +Makefile +Makefile.in +coverhd.h + +network +======= +Eric's problem + +startup +======= +device-tree - remove +linkcmds +setvec.c - Modified to acount for general purpose vector. +sbrk.c - Ok +rtems-ctor.cc - Ok +bspclean.s - Ok +vmeintr.c +Makefile.in - Added genpvec.c +bspstart.c - Modified with changes from vista bsp. + +Added: +genpvec.c + +Note: Need to add routine which connects the general purpose interupt with the + various interupt handlers. genpvec.c uses this routine and may need + to be modified. +wrapup +======= +wrapup/Makefile.in + +vectors +======= + +start +======= +start/Makefile.in +start/start.s - Made modifications based upon Score603e mods. diff --git a/c/src/lib/libbsp/powerpc/dmv177/bsp_specs b/c/src/lib/libbsp/powerpc/dmv177/bsp_specs new file mode 100644 index 0000000000..6a84054cf5 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/bsp_specs @@ -0,0 +1,18 @@ +%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 ecrtn%O%s --start-group -lrtemsall -lc -lgcc --end-group} + +*startfile: +%{!qrtems: %(old_startfile)} %{qrtems: start.o%s} + +*link: +%{!qrtems: %(old_link)} %{qrtems: -Qy -dp -Bstatic -T linkcmds%s -e _start -u __vectors} + diff --git a/c/src/lib/libbsp/powerpc/dmv177/clock/Makefile.in b/c/src/lib/libbsp/powerpc/dmv177/clock/Makefile.in new file mode 100644 index 0000000000..4c145d2dfc --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/clock/Makefile.in @@ -0,0 +1,62 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +RTEMS_ROOT = @RTEMS_ROOT@ +PROJECT_ROOT = @PROJECT_ROOT@ +RTEMS_CUSTOM = $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg + +PGM=${ARCH}/clock.rel + +# C source names, if any, go here -- minus the .c +C_PIECES=clock +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +H_FILES= + +# Assembly source names, if any, go here -- minus the .s +S_PIECES= +S_FILES=$(S_PIECES:%=%.s) +S_O_FILES=$(S_FILES:%.s=${ARCH}/%.o) + +SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES) +OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES) + +include $(RTEMS_CUSTOM) +include $(PROJECT_ROOT)/make/leaf.cfg + + +# +# (OPTIONAL) Add local stuff here using += +# + +DEFINES += +CPPFLAGS += +CFLAGS += + +LD_PATHS += +LD_LIBS += +LDFLAGS += + +# +# Add your list of files to delete here. The config files +# already know how to delete some stuff, so you may want +# to just run 'make clean' first to see what gets missed. +# 'make clobber' already includes 'make clean' +# + +CLEAN_ADDITIONS += +CLOBBER_ADDITIONS += + +${PGM}: ${SRCS} ${OBJS} + $(make-rel) + +all: ${ARCH} $(SRCS) $(PGM) + +# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile +install: all diff --git a/c/src/lib/libbsp/powerpc/dmv177/clock/clock.c b/c/src/lib/libbsp/powerpc/dmv177/clock/clock.c new file mode 100644 index 0000000000..03059c6cea --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/clock/clock.c @@ -0,0 +1,251 @@ +/* + * Clock Tick Device Driver + * + * This routine utilizes the Decrementer Register common to the PPC family. + * + * The tick frequency is directly programmed to the configured number of + * microseconds per tick. + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <stdlib.h> + +#include <bsp.h> +#include <rtems/libio.h> +#include <assert.h> + +/* + * The Real Time Clock Counter Timer uses this trap type. + */ + +#define CLOCK_VECTOR PPC_IRQ_DECREMENTER + +/* + * Clock ticks since initialization + */ + +volatile rtems_unsigned32 Clock_driver_ticks; + +/* + * This is the value programmed into the count down timer. + */ + +rtems_unsigned32 Clock_Decrementer_value; + +/* + * This is the value of the old isr routine. + */ +rtems_isr_entry Old_ticker; + + +void Clock_exit( void ); + +/* + * These are set by clock driver during its init + */ + +rtems_device_major_number rtems_clock_major = ~0; +rtems_device_minor_number rtems_clock_minor; + +#define PPC_Set_decrementer( _clicks ) \ + do { \ + asm volatile( "mtdec %0" : "=r" ((_clicks)) : "r" ((_clicks)) ); \ + } while (0) + + +/* PAGE + * + * Clock_isr + * + * This is the clock tick interrupt handler. + * + * Input parameters: + * vector - vector number + * + * Output parameters: NONE + * + * Return values: NONE + * + */ + +rtems_isr Clock_isr( + rtems_vector_number vector, + CPU_Interrupt_frame *frame +) +{ + /* + * Set the decrementer. + */ + + PPC_Set_decrementer( Clock_Decrementer_value ); + + /* + * The driver has seen another tick. + */ + + Clock_driver_ticks += 1; + + /* + * Real Time Clock counter/timer is set to automatically reload. + */ + + rtems_clock_tick(); +} + +/* PAGE + * + * Install_clock + * + * This routine actually performs the hardware initialization for the clock. + * + * Input parameters: + * clock_isr - clock interrupt service routine entry point + * + * Output parameters: NONE + * + * Return values: NONE + * + */ + +extern int CLOCK_SPEED; + +void Install_clock( + rtems_isr_entry clock_isr +) +{ + Clock_driver_ticks = 0; + + if ( BSP_Configuration.ticks_per_timeslice ) { + Old_ticker = (rtems_isr_entry) set_vector( clock_isr, CLOCK_VECTOR, 1 ); + + PPC_Set_decrementer( Clock_Decrementer_value ); + + atexit( Clock_exit ); + } +} + +/* PAGE + * + * Clock_exit + * + * This routine allows the clock driver to exit by masking the interrupt and + * disabling the clock's counter. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + * + */ + +void Clock_exit( void ) +{ + if ( BSP_Configuration.ticks_per_timeslice ) { + + /* nothing to do */; + + /* do not restore old vector */ + } +} + +/* PAGE + * + * Clock_initialize + * + * This routine initializes the clock driver. + * + * Input parameters: + * major - clock device major number + * minor - clock device minor number + * parg - pointer to optional device driver arguments + * + * Output parameters: NONE + * + * Return values: + * rtems_device_driver status code + */ + +rtems_device_driver Clock_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *pargp +) +{ + Clock_Decrementer_value = (int) &CPU_PPC_CLICKS_PER_MS * + (BSP_Configuration.microseconds_per_tick / 1000); + + Install_clock( Clock_isr ); + + /* + * make major/minor avail to others such as shared memory driver + */ + + rtems_clock_major = major; + rtems_clock_minor = minor; + + return RTEMS_SUCCESSFUL; +} + +/* PAGE + * + * Clock_control + * + * This routine is the clock device driver control entry point. + * + * Input parameters: + * major - clock device major number + * minor - clock device minor number + * parg - pointer to optional device driver arguments + * + * Output parameters: NONE + * + * Return values: + * rtems_device_driver status code + */ + +rtems_device_driver Clock_control( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *pargp +) +{ + rtems_unsigned32 isrlevel; + rtems_libio_ioctl_args_t *args = pargp; + + if (args == 0) + goto done; + + /* + * This is hokey, but until we get a defined interface + * to do this, it will just be this simple... + */ + + if (args->command == rtems_build_name('I', 'S', 'R', ' ')) + { + Clock_isr( CLOCK_VECTOR, pargp ); + } + else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) + { + rtems_interrupt_disable( isrlevel ); + (void) set_vector( args->buffer, CLOCK_VECTOR, 1 ); + rtems_interrupt_enable( isrlevel ); + } + +done: + return RTEMS_SUCCESSFUL; +} + + + + + diff --git a/c/src/lib/libbsp/powerpc/dmv177/console/Makefile.in b/c/src/lib/libbsp/powerpc/dmv177/console/Makefile.in new file mode 100644 index 0000000000..eb8b914e91 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/console/Makefile.in @@ -0,0 +1,56 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +RTEMS_ROOT = @RTEMS_ROOT@ +PROJECT_ROOT = @PROJECT_ROOT@ +RTEMS_CUSTOM = $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg + +PGM=${ARCH}/console.rel + +# C source names, if any, go here -- minus the .c +C_PIECES=console duart +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +H_FILES= + +SRCS=$(C_FILES) $(H_FILES) +OBJS=$(C_O_FILES) + +include $(RTEMS_CUSTOM) +include $(PROJECT_ROOT)/make/leaf.cfg + +# +# (OPTIONAL) Add local stuff here using += +# + +DEFINES += +CPPFLAGS += +CFLAGS += + +LD_PATHS += +LD_LIBS += +LDFLAGS += + +# +# Add your list of files to delete here. The config files +# already know how to delete some stuff, so you may want +# to just run 'make clean' first to see what gets missed. +# 'make clobber' already includes 'make clean' +# + +CLEAN_ADDITIONS += +CLOBBER_ADDITIONS += + +${PGM}: ${SRCS} ${OBJS} + $(make-rel) + +all: ${ARCH} $(SRCS) $(PGM) + +# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile +install: all diff --git a/c/src/lib/libbsp/powerpc/dmv177/console/console.c b/c/src/lib/libbsp/powerpc/dmv177/console/console.c new file mode 100644 index 0000000000..b1fc6f19e9 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/console/console.c @@ -0,0 +1,479 @@ +/* + * console.c + * + * This driver uses the termios pseudo driver. + * + * Currently only polled mode is supported. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id: console.c + */ + +#include <stdlib.h> +#include <motorola/mc68681.h> +#include <bsp.h> +#include <rtems/libio.h> +#include <assert.h> + +#define COM1 0 +#define COM2 1 +#define NUM_PORTS 2 +#define USE_FOR_CONSOLE COM1 + +/* + * Define RDB_BREAK_IN if you need to be able to break in to the + * program with a ctrl-c during remote target debugging. If so, + * UART B will not be accessible from rtems during remote debugging + * if interrupt driven console is used. Does not affect UART A, polled + * mode or when the program runs without remote debugging. + */ +#define RDB_BREAK_IN + +/* Proto-types for Duart.C */ +void console_initialize_interrupts( void ); +char console_inbyte_polled( int port ); +void console_outbyte_polled(int port, char ch); +rtems_isr console_isr (rtems_vector_number vector); +volatile void init_mc88681(); + +/* PAGE + * + * console_initialize + * + * This routine initializes the console IO driver. + * + * Input parameters: + * major - console device major number + * minor - console device minor number + * arg - pointer to optional device driver arguments + * + * Output parameters: NONE + * + * Return values: + * rtems_device_driver status code + */ + +rtems_device_driver console_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_status_code status; + int console; + + /* + * initialize the termio interface. + */ + rtems_termios_initialize(); + + /* + * Register Device Names + */ + console = USE_FOR_CONSOLE; + status = rtems_io_register_name( "/dev/console", major, console ); + if (status != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred(status); + + /* + * Initialize Hardware + */ + + init_mc88681 (); + +#if CONSOLE_USE_INTERRUPTS + console_initialize_interrupts(); +#endif + + return RTEMS_SUCCESSFUL; +} + +/* PAGE + * + * console_write_support + * + * This routine is Console Termios output entry point. + * + * Input parameters: + * minor - console device minor number + * buf - buffer of data to be written + * len - length of data to be written + * + * Output parameters: NONE + * + * Return values: + * int number of bytes written + */ + +int console_write_support( + int minor, + const char *buf, + int len) +{ + int nwrite = 0; + int port = minor; + + /* + * verify port Number + */ + assert ( port < NUM_PORTS ); + + /* + * poll each byte in the string out of the port. + */ + while (nwrite < len) { +#if defined(CONSOLE_USE_INTERRUPTS) +#else + console_outbyte_polled(port, *buf++); +#endif + nwrite++; + } + + /* + * return the number of bytes written. + */ + return nwrite; +} + + +/* PAGE + * + * DEBUG_puts + * + * This should be safe in the event of an error. It attempts to insure + * that no TX empty interrupts occur while it is doing polled IO. Then + * it restores the state of that external interrupt. + * + * Input parameters: + * string - pointer to debug output string + * + * Output parameters: NONE + * + * Return values: NONE + */ + +void DEBUG_puts( + char *string +) +{ + char *s; + rtems_unsigned32 isrlevel; + + rtems_interrupt_disable( isrlevel ); + for ( s = string ; *s ; s++ ) + console_outbyte_polled( 0, *s ); + + console_outbyte_polled( 0, '\r' ); + console_outbyte_polled( 0, '\n' ); + rtems_interrupt_enable( isrlevel ); +} + + +/* PAGE + * + * console_open + * + * This routine is the console device driver open entry point. + * + * Input parameters: + * major - console device major number + * minor - console device minor number + * arg - pointer to optional device driver arguments + * + * Output parameters: NONE + * + * Return values: + * rtems_device_driver status code + */ + +rtems_device_driver console_open( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + rtems_status_code sc; + int port = minor; +#if defined(CONSOLE_USE_INTERRUPTS) + rtems_libio_open_close_args_t *args = arg; +#endif + + /* + * Verify the minor number is valid. + */ + if (minor < 0) + return RTEMS_INVALID_NUMBER; + + if ( port > NUM_PORTS ) + return RTEMS_INVALID_NUMBER; + + /* + * open the port as a termios console driver. + */ +#if defined(CONSOLE_USE_INTERRUPTS) + sc = rtems_termios_open (major, minor, arg, + NULL, NULL, NULL, + console_write_support, 0); +#else + sc = rtems_termios_open (major, minor, arg, NULL, NULL, + console_inbyte_nonblocking, + console_write_support, + 0); +#endif + + return sc; +} + + + +/* PAGE + * + * console_reserve_resources + * + * This routine reserves resources for each port which may be + * used as a console. + * + * Input parameters: + * configuration - rtems configuration table. + * + * Output parameters: NONE + * + * Return values: NONE + */ + +void console_reserve_resources( + rtems_configuration_table *configuration +) +{ + rtems_termios_reserve_resources( configuration, NUM_PORTS ); +} + +/* PAGE + * + * console_close + * + * This routine is the console device driver close entry point. + * + * Input parameters: + * major - console device major number + * minor - console device minor number + * arg - pointer to optional device driver arguments + * + * Output parameters: NONE + * + * Return values: + * rtems_device_driver status code + */ + +rtems_device_driver console_close( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + return rtems_termios_close (arg); +} + +/* PAGE + * + * console_read + * + * This routine is the console device driver read entry point. + * + * Input parameters: + * major - console device major number + * minor - console device minor number + * arg - pointer to optional device driver arguments + * + * Output parameters: NONE + * + * Return values: + * rtems_device_driver status code + * + */ + rtems_device_driver console_read( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + return rtems_termios_read (arg); +} + +/* PAGE + * + * console_write + * + * This routine is the console device driver write entry point. + * + * Input parameters: + * major - console device major number + * minor - console device minor number + * arg - pointer to optional device driver arguments + * + * Output parameters: NONE + * + * Return values: + * rtems_device_driver status code + * + */ +rtems_device_driver console_write( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + return rtems_termios_write (arg); +} + +/* PAGE + * + * console_control + * + * This routine is console device driver control entry point + * + * Input parameters: + * major - console device major number + * minor - console device minor number + * arg - pointer to optional device driver arguments + * + * Output parameters: NONE + * + * Return values: + * rtems_device_driver status code + * + */ +rtems_device_driver console_control( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + return rtems_termios_ioctl (arg); +} + + +/* + * Interrupt driven console IO + */ + +#if CONSOLE_USE_INTERRUPTS + +/* + * Buffers between task and ISRs + */ + +#include <ringbuf.h> +extern Ring_buffer_t TX_Buffer[2]; +extern Ring_buffer_t RX_Buffer[2]; + +/* + * console_inbyte_interrupts + * + * This routine reads a character from the UART. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: + * character read from UART + */ + +char console_inbyte_interrupts( int port ) +{ + char ch; + + while ( Ring_buffer_Is_empty( &RX_Buffer[ port ] ) ); + + Ring_buffer_Remove_character( &RX_Buffer[ port ], ch ); + return ch; +} + +/* + * console_outbyte_interrupts + * + * This routine transmits a character out. + * + * Input parameters: + * port - port to transmit character to + * ch - character to be transmitted + * + * Output parameters: NONE + * + * Return values: NONE + */ + +void console_outbyte_interrupts( + int port, + char ch +) +{ + /* + * If this is the first character then we need to prime the pump + */ + + if ( Is_TX_active[ port ] == FALSE ) { + Is_TX_active[ port ] = TRUE; + console_outbyte_polled( port, ch ); + return; + } + + while ( Ring_buffer_Is_full( &TX_Buffer[ port ] ) ); + + Ring_buffer_Add_character( &TX_Buffer[ port ], ch ); +} + +/* + * console_exit + * + * This routine allows the console to exit by masking its associated interrupt + * vectors. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + */ + +void console_exit() +{ + volatile unsigned char *_addr; + int port; + + /* + * Although the interrupts for the UART are unmasked, the PIL is set to + * disable all external interrupts. So we might as well do this first. + */ + + /* ??? Mask All UART Interrupts */ + + for (port = MC68681_PORT_A; port <= MC68681_PORT_B; port++) { + while (!Ring_buffer_Is_empty (&TX_Buffer[port])) { + Ring_buffer_Remove_character (&TX_Buffer[port],ch); + console_outbyte_polled (port,ch); + } + } + + /* + * Now wait for all the data to actually get out ... the send register + * should be empty. + */ + _addr = (unsigned char *) (DUART_ADDR + MC68681_STATUS_REG_A); + while (!(*_addr & MC68681_TX_EMPTY)); + + _addr = (unsigned char *) (DUART_ADDR + MC68681_STATUS_REG_B); + while (!(*_addr & MC68681_TX_EMPTY)); +} +#endif /* CONSOLE_USE_INTERRUPTS */ + + + diff --git a/c/src/lib/libbsp/powerpc/dmv177/console/duart.c b/c/src/lib/libbsp/powerpc/dmv177/console/duart.c new file mode 100644 index 0000000000..f72b37a832 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/console/duart.c @@ -0,0 +1,201 @@ +/* + * duart.c + * + * This code is a modified version of what you will find at the + * end of the IDP User's manual. The original code is copyrighted + * by Motorola and Motorola Semiconductor Products as well as + * Motorola Software products group. + * + * Modifications to the original IDP code by Doug McBride, Colorado + * Space Grant College. Modifications include a means of accessing + * port B of the duart as well as port A as well as modifications for + * buffering and RTEMS support. Modifications are provided + * as is and may not be correct. + * + * Rob Savoye provided the format for the mc68681 header file + * + * Joel Sherrill provided inspiration for recoding my original assembly + * for this file into C (a good idea) + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id: duart.c + */ + +#define MC68681_OFFSET_MULTIPLIER 8 +#include <motorola/mc68681.h> +#include <bsp.h> +#include <ringbuf.h> + +rtems_isr console_isr (rtems_vector_number vector); + +Ring_buffer_t TX_Buffer[2]; +Ring_buffer_t RX_Buffer[2]; + +/* PAGE + * + * init_mc88681 + * + * volatile routine to initialize duart + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return Values: NONE + */ + +volatile void init_mc88681() +{ + /* + * Initialize Ring buffers + */ + Ring_buffer_Initialize( &RX_Buffer[ 0 ] ); + Ring_buffer_Initialize( &RX_Buffer[ 1 ] ); + + Ring_buffer_Initialize( &TX_Buffer[ 0 ] ); + Ring_buffer_Initialize( &TX_Buffer[ 1 ] ); +} + +/* PAGE + * + * console_isr + * + * interrupt handler for receive of character from duart on ports A & B + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return Values: NONE + */ + +rtems_isr console_isr (rtems_vector_number vector) +{ + + /* + * Fill me in later ... + */ + +} + + +/* PAGE + * + * console_outbyte_polled + * + * This routine transmits a character out. + * + * Input parameters: + * port - port to transmit character to + * ch - character to be transmitted + * + * Output parameters: NONE + * + * Return values: NONE + */ + +void console_outbyte_polled( + int port, + char ch +) +{ + unsigned char status; + unsigned char data; + unsigned char t = 0; + + if (port == MC68681_PORT_A) { + status = MC68681_STATUS_REG_A; + data = MC68681_TRANSMIT_BUFFER_A; + } else { + status = MC68681_STATUS_REG_B; + data = MC68681_TRANSMIT_BUFFER_B; + } + + while ( !(MC68681_READ(DUART_ADDR, status) & MC68681_TX_READY) ){ + if (t == 0) { + Debug_Entry( 0x8000 ); + t++; + } + } + + Debug_Entry( 0x9000 ); + MC68681_WRITE(DUART_ADDR, data, ch); +} + + +/* PAGE + * + * console_inbyte_polled + * + * This routine reads a character from the UART. + * + * Input parameters: + * port - port to read character from + * + * Output parameters: NONE + * + * Return values: + * character read from UART + */ + +#define MC68681_RECEIVE_ERRORS \ + (MC68681_OVERRUN_ERROR | MC68681_PARITY_ERROR | MC68681_FRAMING_ERROR) + +char console_inbyte_polled( int port ) +{ + char status; + char data; + char cmd; + unsigned char status_info; + + /* + * Set Port A or B unique variables. + */ + if (port == MC68681_PORT_A) { + status = MC68681_STATUS_REG_A; + data = MC68681_RECEIVE_BUFFER_A; + cmd = MC68681_COMMAND_REG_A; + } else { + status = MC68681_STATUS_REG_B; + data = MC68681_RECEIVE_BUFFER_B; + cmd = MC68681_COMMAND_REG_B; + } + + /* Wait for the Ready bit and Clear any errors */ + for ( ; ; ) { + status_info = MC68681_READ(DUART_ADDR, status); + if ( status_info & MC68681_RX_READY ) + break; + + if ( status_info & MC68681_RECEIVE_ERRORS ) + MC68681_WRITE( DUART_ADDR, cmd, MC68681_MODE_REG_RESET_ERROR ); + } + + return MC68681_READ(DUART_ADDR, data); +} + + + + + + + + + + + + + + + + + + + diff --git a/c/src/lib/libbsp/powerpc/dmv177/include/Makefile.in b/c/src/lib/libbsp/powerpc/dmv177/include/Makefile.in new file mode 100644 index 0000000000..54f072893c --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/include/Makefile.in @@ -0,0 +1,38 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +RTEMS_ROOT = @RTEMS_ROOT@ +PROJECT_ROOT = @PROJECT_ROOT@ +RTEMS_CUSTOM = $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg + +H_FILES = $(srcdir)/bsp.h $(srcdir)/coverhd.h \ + $(srcdir)/dmv170.h $(srcdir)/chain.h $(srcdir)/tod.h + +# +# Equate files are for including from assembly preprocessed by +# gm4 or gasp. No examples are provided except for those for +# other CPUs. The best way to generate them would be to +# provide a program which generates the constants used based +# on the C equivalents. +# +# If you add equate files, don't forget to uncomment the install line +# below. +# + +EQ_FILES = + +SRCS=$(H_FILES) $(EQ_FILES) + +include $(RTEMS_CUSTOM) +include $(PROJECT_ROOT)/make/leaf.cfg + +CLEAN_ADDITIONS += +CLOBBER_ADDITIONS += + +all: $(SRCS) + $(INSTALL) -m 444 $(H_FILES) $(PROJECT_INCLUDE) diff --git a/c/src/lib/libbsp/powerpc/dmv177/include/bsp.h b/c/src/lib/libbsp/powerpc/dmv177/include/bsp.h new file mode 100644 index 0000000000..aa4f4df348 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/include/bsp.h @@ -0,0 +1,178 @@ +/* bsp.h + * + * This include file contains all DY-4 DMV170 board IO definitions. + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#ifndef __DMV170_BSP_h +#define __DMV170_BSP_h + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef ASM +/* Definition of where to store registers in alignment handler */ +#define ALIGN_REGS 0x0140 + +#else +#include <rtems.h> +#include <console.h> +#include <clockdrv.h> +#include <console.h> +#include <iosupp.h> + +#include <dmv170.h> + +#define Enable_Debug() \ + DMV170_WRITE( 0xffffbd0c, 0 ) + +#define Debug_Entry( num ) \ + DMV170_WRITE( 0xffffbd06, num ) + +/* + * The following macro calculates the Baud constant. For the Z8530 chip. + */ +#define Z8530_Baud( _frequency, _clock_by, _baud_rate ) \ + ( (_frequency /( _clock_by * 2 * _baud_rate)) - 2) + + +/* + * Define the time limits for RTEMS Test Suite test durations. + * Long test and short test duration limits are provided. These + * values are in seconds and need to be converted to ticks for the + * application. + * + */ + +#define MAX_LONG_TEST_DURATION 300 /* 5 minutes = 300 seconds */ +#define MAX_SHORT_TEST_DURATION 3 /* 3 seconds */ + + +/* + * Stuff for Time Test 27 + */ + +#define MUST_WAIT_FOR_INTERRUPT 1 + +#define Install_tm27_vector( _handler ) \ + set_vector( (_handler), PPC_IRQ_DECREMENTER, 1 ) + +#define Cause_tm27_intr() \ + do { \ + unsigned32 _clicks = 1; \ + asm volatile( "mtdec %0" : "=r" ((_clicks)) : "r" ((_clicks)) ); \ + } while (0) + + +#define Clear_tm27_intr() \ + do { \ + unsigned32 _clicks = 0xffffffff; \ + asm volatile( "mtdec %0" : "=r" ((_clicks)) : "r" ((_clicks)) ); \ + } while (0) + +#define Lower_tm27_intr() \ + do { \ + unsigned32 _msr = 0; \ + _ISR_Set_level( 0 ); \ + asm volatile( "mfmsr %0 ;" : "=r" (_msr) : "r" (_msr) ); \ + _msr |= 0x8002; \ + asm volatile( "mtmsr %0 ;" : "=r" (_msr) : "r" (_msr) ); \ + } while (0) + +/* Constants */ + +/* + * Device Driver Table Entries + */ + +/* + * NOTE: Use the standard Console driver entry + */ + +/* + * NOTE: Use the standard Clock driver entry + */ + + +/* + * Information placed in the linkcmds file. + */ + +extern int RAM_START; +extern int RAM_END; +extern int RAM_SIZE; + +extern int PROM_START; +extern int PROM_END; +extern int PROM_SIZE; + +extern int CLOCK_SPEED; + +extern int end; /* last address in the program */ + +/* + * How many libio files we want + */ + +#define BSP_LIBIO_MAX_FDS 20 + +/* functions */ + +/* + * genvec.c + */ +rtems_isr_entry set_EE_vector( + rtems_isr_entry handler, /* isr routine */ + rtems_vector_number vector /* vector number */ +); +void initialize_external_exception_vector (); + +/* + * console.c + */ +void DEBUG_puts( char *string ); + +void BSP_fatal_return( void ); + + + +void bsp_start( void ); + +void bsp_cleanup( void ); + +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 */ +); + +void BSP_fatal_return( void ); + +void bsp_spurious_initialize( void ); + +extern rtems_configuration_table BSP_Configuration; /* owned by BSP */ + +extern rtems_cpu_table Cpu_table; /* owned by BSP */ + +extern rtems_unsigned32 bsp_isr_level; + +extern int CPU_PPC_CLICKS_PER_MS; + +#endif /* ASM */ + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/c/src/lib/libbsp/powerpc/dmv177/include/chain.h b/c/src/lib/libbsp/powerpc/dmv177/include/chain.h new file mode 100644 index 0000000000..c54df2b4e7 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/include/chain.h @@ -0,0 +1,353 @@ +/* chain.h + * + * This include file contains all the constants and structures associated + * with doubly linked chains. This file actually just provides an + * interface to the chain object in rtems. + * + */ + +#ifndef __CHAIN_h +#define __CHAIN_h + +#include <rtems.h> + +/* + * Chain_Initialize + * + * This routine initializes the_chain structure to manage the + * contiguous array of number_nodes nodes which starts at + * starting_address. Each node is of node_size bytes. + * + * Chain_Control *the_chain, * IN * + * void *starting_address, * IN * + * rtems_unsigned32 number_nodes, * IN * + * rtems_unsigned32 node_size * IN * + */ + +#define Chain_Initialize( the_chain, starting_address, \ + number_nodes, node_size ) \ + _Chain_Initialize( the_chain, starting_address, \ + number_nodes, node_size ) \ + + +/* + * Chain_Initialize_empty + * + * This routine initializes the specified chain to contain zero nodes. + * + * Chain_Control *the_chain * IN * + */ + +#define Chain_Initialize_empty( the_chain ) \ + _Chain_Initialize_empty( the_chain ) + + +/* + * Chain_Are_nodes_equal + * + * This function returns TRUE if LEFT and RIGHT are equal, + * and FALSE otherwise. + * + * Chain_Node *left, * IN * + * Chain_Node *right * IN * + */ + +#define Chain_Are_nodes_equal( left, right ) \ + _Chain_Are_nodes_equal( left, right ) + + +/* + * Chain_Extract_unprotected + * + * This routine extracts the_node from the chain on which it resides. + * It does NOT disable interrupts to insure the atomicity of the + * extract operation. + * + * Chain_Node *the_node * IN * + */ + +#define Chain_Extract_unprotected( the_node ) \ + _Chain_Extract_unprotected( the_node ) + + +/* + * Chain_Extract + * + * This routine extracts the_node from the chain on which it resides. + * It disables interrupts to insure the atomicity of the + * extract operation. + * + * Chain_Node *the_node * IN * + */ + +#define Chain_Extract( the_node ) \ + _Chain_Extract( the_node ) + + +/* + * Chain_Get_unprotected + * + * This function removes the first node from the_chain and returns + * a pointer to that node. If the_chain is empty, then NULL is returned. + * It does NOT disable interrupts to insure the atomicity of the + * get operation. + * + * Chain_Control *the_chain * IN * + */ + +#define Chain_Get_unprotected( the_chain ) \ + _Chain_Get_unprotected( the_chain ) + + +/* + * Chain_Get + * + * This function removes the first node from the_chain and returns + * a pointer to that node. If the_chain is empty, then NULL is returned. + * It disables interrupts to insure the atomicity of the + * get operation. + * + * Chain_Control *the_chain * IN * + */ + +#define Chain_Get( the_chain ) \ + _Chain_Get( the_chain ) + + +/* + * Chain_Get_first_unprotected + * + * This function removes the first node from the_chain and returns + * a pointer to that node. It does NOT disable interrupts to insure + * the atomicity of the get operation. + * + * Chain_Control *the_chain * IN * + */ + +#define Chain_Get_first_unprotected( the_chain ) \ + _Chain_Get_first_unprotected( the_chain ) + + +/* + * Chain_Insert_unprotected + * + * This routine inserts the_node on a chain immediately following + * after_node. It does NOT disable interrupts to insure the atomicity + * of the extract operation. + * + * Chain_Node *after_node, * IN * + * Chain_Node *the_node * IN * + */ + +#define Chain_Insert_unprotected( after_node, the_node ) \ + _Chain_Insert_unprotected( after_node, the_node ) + + +/* + * Chain_Insert + * + * This routine inserts the_node on a chain immediately following + * after_node. It disables interrupts to insure the atomicity + * of the extract operation. + * + * Chain_Node *after_node, * IN * + * Chain_Node *the_node * IN * + */ + +#define Chain_Insert( after_node, the_node ) \ + _Chain_Insert( after_node, the_node ) + + +/* + * Chain_Append_unprotected + * + * This routine appends the_node onto the end of the_chain. + * It does NOT disable interrupts to insure the atomicity of the + * append operation. + * + * Chain_Control *the_chain, * IN * + * Chain_Node *the_node * IN * + */ + +#define Chain_Append_unprotected( the_chain, the_node ) \ + _Chain_Append_unprotected( the_chain, the_node ) + + +/* + * Chain_Append + * + * This routine appends the_node onto the end of the_chain. + * It disables interrupts to insure the atomicity of the + * append operation. + * + * Chain_Control *the_chain, * IN * + * Chain_Node *the_node * IN * + */ + +#define Chain_Append( the_chain, the_node ) \ + _Chain_Append( the_chain, the_node ) + + +/* + * Chain_Prepend_unprotected + * + * This routine prepends the_node onto the front of the_chain. + * It does NOT disable interrupts to insure the atomicity of the + * prepend operation. + * + * Chain_Control *the_chain, * IN * + * Chain_Node *the_node * IN * + */ + +#define Chain_Prepend_unprotected( the_chain, the_node ) \ + _Chain_Prepend_unprotected( the_chain, the_node ) + + +/* + * Chain_Prepend + * + * This routine prepends the_node onto the front of the_chain. + * It disables interrupts to insure the atomicity of the + * prepend operation. + * + * Chain_Control *the_chain, * IN * + * Chain_Node *the_node * IN * + */ + +#define Chain_Prepend( the_chain, the_node ) \ + _Chain_Prepend( the_chain, the_node ) + + +/* + * Chain_Head + * + * This function returns a pointer to the first node on the chain. + * + * Chain_Control *the_chain * IN * + */ + +#define Chain_Head( the_chain ) \ + _Chain_Head( the_chain ) + + +/* + * Chain_Tail + * + * This function returns a pointer to the last node on the chain. + * + * Chain_Control *the_chain * IN * + */ + +#define Chain_Tail( the_chain ) \ + _Chain_Tail( the_chain ) + + +/* + * Chain_Is_head + * + * This function returns TRUE if the_node is the head of the_chain and + * FALSE otherwise. + * + * Chain_Control *the_chain, * IN * + * Chain_Node *the_node * IN * + */ + +#define Chain_Is_head( the_chain, the_node ) \ + _Chain_Is_head( the_chain, the_node ) + + +/* + * Chain_Is_tail + * + * This function returns TRUE if the_node is the tail of the_chain and + * FALSE otherwise. + * + * Chain_Control *the_chain, * IN * + * Chain_Node *the_node * IN * + */ + +#define Chain_Is_tail( the_chain, the_node ) \ + _Chain_Is_tail( the_chain, the_node ) + + +/* + * Chain_Is_first + * + * This function returns TRUE if the_node is the first node on a chain and + * FALSE otherwise. + * + * Chain_Node *the_node * IN * + */ + +#define Chain_Is_first( the_node ) \ + _Chain_Is_first( the_node ) + + +/* + * Chain_Is_last + * + * This function returns TRUE if the_node is the last node on a chain and + * FALSE otherwise. + * + * Chain_Node *the_node * IN * + */ + +#define Chain_Is_last( the_node ) \ + _Chain_Is_last( the_node ) + + +/* + * Chain_Is_empty + * + * This function returns TRUE if there are no nodes on the_chain and + * FALSE otherwise. + * + * Chain_Control *the_chain * IN * + */ + +#define Chain_Is_empty( the_chain ) \ + _Chain_Is_empty( the_chain ) + + +/* + * Chain_Has_only_one_node + * + * This function returns TRUE if there is only one node on the_chain and + * FALSE otherwise. + * + * Chain_Control *the_chain * IN * + */ + +#define Chain_Has_only_one_node( the_chain ) \ + _Chain_Has_only_one_node( the_chain ) + + +/* + * Chain_Is_null + * + * This function returns TRUE if the_chain is NULL and FALSE otherwise. + * + * Chain_Control *the_chain * IN * + */ + +#define Chain_Is_null( the_chain ) \ + _Chain_Is_null( the_chain ) + + +/* + * Chain_Is_null_node + * + * This function returns TRUE if the_node is NULL and FALSE otherwise. + * + * Chain_Node *the_node * IN * + */ + +#define Chain_Is_null_node( the_node ) \ + _Chain_Is_null_node( the_node ) + + +#undef __RTEMS_APPLICATION__ +#include <rtems/score/chain.inl> +#define __RTEMS_APPLICATION__ +#endif +/* end of include file */ diff --git a/c/src/lib/libbsp/powerpc/dmv177/include/coverhd.h b/c/src/lib/libbsp/powerpc/dmv177/include/coverhd.h new file mode 100644 index 0000000000..451d13b706 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/include/coverhd.h @@ -0,0 +1,134 @@ +/* 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 + * calling overhead including passing of arguments. + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +/* + * + * 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 0 +#define CALLING_OVERHEAD_SHUTDOWN_EXECUTIVE 0 +#define CALLING_OVERHEAD_TASK_CREATE 0 +#define CALLING_OVERHEAD_TASK_IDENT 0 +#define CALLING_OVERHEAD_TASK_START 0 +#define CALLING_OVERHEAD_TASK_RESTART 0 +#define CALLING_OVERHEAD_TASK_DELETE 0 +#define CALLING_OVERHEAD_TASK_SUSPEND 0 +#define CALLING_OVERHEAD_TASK_RESUME 0 +#define CALLING_OVERHEAD_TASK_SET_PRIORITY 0 +#define CALLING_OVERHEAD_TASK_MODE 0 +#define CALLING_OVERHEAD_TASK_GET_NOTE 0 +#define CALLING_OVERHEAD_TASK_SET_NOTE 0 +#define CALLING_OVERHEAD_TASK_WAKE_WHEN 0 +#define CALLING_OVERHEAD_TASK_WAKE_AFTER 0 +#define CALLING_OVERHEAD_INTERRUPT_CATCH 0 +#define CALLING_OVERHEAD_CLOCK_GET 0 +#define CALLING_OVERHEAD_CLOCK_SET 0 +#define CALLING_OVERHEAD_CLOCK_TICK 0 + +#define CALLING_OVERHEAD_TIMER_CREATE 0 +#define CALLING_OVERHEAD_TIMER_IDENT 0 +#define CALLING_OVERHEAD_TIMER_DELETE 0 +#define CALLING_OVERHEAD_TIMER_FIRE_AFTER 0 +#define CALLING_OVERHEAD_TIMER_FIRE_WHEN 0 +#define CALLING_OVERHEAD_TIMER_RESET 0 +#define CALLING_OVERHEAD_TIMER_CANCEL 0 +#define CALLING_OVERHEAD_SEMAPHORE_CREATE 0 +#define CALLING_OVERHEAD_SEMAPHORE_IDENT 0 +#define CALLING_OVERHEAD_SEMAPHORE_DELETE 0 +#define CALLING_OVERHEAD_SEMAPHORE_OBTAIN 0 +#define CALLING_OVERHEAD_SEMAPHORE_RELEASE 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_CREATE 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_IDENT 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_DELETE 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_SEND 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_URGENT 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_BROADCAST 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_RECEIVE 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_FLUSH 0 + +#define CALLING_OVERHEAD_EVENT_SEND 0 +#define CALLING_OVERHEAD_EVENT_RECEIVE 0 +#define CALLING_OVERHEAD_SIGNAL_CATCH 0 +#define CALLING_OVERHEAD_SIGNAL_SEND 0 +#define CALLING_OVERHEAD_PARTITION_CREATE 0 +#define CALLING_OVERHEAD_PARTITION_IDENT 0 +#define CALLING_OVERHEAD_PARTITION_DELETE 0 +#define CALLING_OVERHEAD_PARTITION_GET_BUFFER 0 +#define CALLING_OVERHEAD_PARTITION_RETURN_BUFFER 0 +#define CALLING_OVERHEAD_REGION_CREATE 0 +#define CALLING_OVERHEAD_REGION_IDENT 0 +#define CALLING_OVERHEAD_REGION_DELETE 0 +#define CALLING_OVERHEAD_REGION_GET_SEGMENT 0 +#define CALLING_OVERHEAD_REGION_RETURN_SEGMENT 0 +#define CALLING_OVERHEAD_PORT_CREATE 0 +#define CALLING_OVERHEAD_PORT_IDENT 0 +#define CALLING_OVERHEAD_PORT_DELETE 0 +#define CALLING_OVERHEAD_PORT_EXTERNAL_TO_INTERNAL 0 +#define CALLING_OVERHEAD_PORT_INTERNAL_TO_EXTERNAL 0 + +#define CALLING_OVERHEAD_IO_INITIALIZE 0 +#define CALLING_OVERHEAD_IO_OPEN 0 +#define CALLING_OVERHEAD_IO_CLOSE 0 +#define CALLING_OVERHEAD_IO_READ 0 +#define CALLING_OVERHEAD_IO_WRITE 0 +#define CALLING_OVERHEAD_IO_CONTROL 0 +#define CALLING_OVERHEAD_FATAL_ERROR_OCCURRED 0 +#define CALLING_OVERHEAD_RATE_MONOTONIC_CREATE 0 +#define CALLING_OVERHEAD_RATE_MONOTONIC_IDENT 0 +#define CALLING_OVERHEAD_RATE_MONOTONIC_DELETE 0 +#define CALLING_OVERHEAD_RATE_MONOTONIC_CANCEL 0 +#define CALLING_OVERHEAD_RATE_MONOTONIC_PERIOD 0 +#define CALLING_OVERHEAD_MULTIPROCESSING_ANNOUNCE 0 + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/c/src/lib/libbsp/powerpc/dmv177/include/dmv170.h b/c/src/lib/libbsp/powerpc/dmv177/include/dmv170.h new file mode 100644 index 0000000000..2c0d8a0b00 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/include/dmv170.h @@ -0,0 +1,215 @@ +/* dmv170.h + * + * This include file contains information pertaining to the DMV170. + * + * NOTE: Other than where absolutely required, this version currently + * supports only the peripherals and bits used by the basic board + * support package. This includes at least significant pieces of + * the following items: + * + * + UART Channels A and B + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#ifndef _INCLUDE_DMV170_h +#define _INCLUDE_DMV170_h + + +/* + * DY-4 is out of their mind and uses a non-standard clock. + */ + +#undef MC68681_BAUD_RATE_MASK_9600 +#define MC68681_BAUD_RATE_MASK_9600 + +#define DMV17x_MC68681_BAUD_RATE_MASK_9600 + +#if 0 +#define MC68681_OFFSET_MULTIPLIER 8 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Note: Move address defs to the linker files. */ +#define DMV170_RTC_ADDRESS 0xf2c00000 /* Real Time clock Base Address*/ +#define DUART_ADDR 0xf2800000 /* base address of the DUART(68681) */ +#define SCC_ADDR 0xfb000000 /* base address for the SCC (85C30) */ + +#define DMV170_LOCAL_CONTROL_STATUS_REG 0xf2400000 +#define DMV170_TIMER0_COUNT_INTERVAL_REG 0xf2400008 +#define DMV170_TIMER1_COUNT_INTERVAL_REG 0xf2400010 +#define DMV170_TIMER2_COUNT_INTERVAL_REG 0xf2400018 +#define DMV170_TIMER_CONTROL_REG 0xf2400020 +#define DMV170_CARD_RESORCE_REG 0xf2400040 + + +#define DMV170_WRITE( reg,data) \ + *((volatile rtems_unsigned16 *)(reg)) = (data) + +#define DMV170_READ( reg, data ) \ + (data) = *((volatile rtems_unsigned16 *)(reg)) + +/* + * The following defines the bits in the Local Control and Status Register. + */ +#define DMV170_IPLx_MASK 0x0007 +#define DMV170_MAXPACK_SENSE_MASK 0x0008 +#define DMV170_MAXPACK_NOT_INSTALLED 0x0008 +#define DMV170_MAXPACK_INSTALLED 0x0000 + +#define DMV170_MAXPACK_RESET_MASK 0x0010 +#define DMV170_MAXPACK_RESET_NEGATE 0x0010 +#define DMV170_MAXPACK_RESET_ASSERT 0x0000 +#define DMV170_EEPROM_READ_WRITE_MASK 0x0020 +#define DMV170_EEPROM_READ 0x0020 +#define DMV170_EEPROM_WRITE 0x0000 +#define DMV170_EEPROM_CLOCK_CTRL_MASK 0x0040 +#define DMV170_EEPROM_CLOCK_ASSERT 0x0040 +#define DMV170_EEPROM_CLOCK_NEGATE 0x0000 +#define DMV170_EEPROM_DATA_MASK 0x0080 +#define DMV170_EEPROM_DATA_HIGH 0x0080 +#define DMV170_EEPROM_DATA_LOW 0x0000 + +/* Bits 8:10 68040 Transfer Modifer Codes represent the Transfer Modifier to be used on MAXPack Accesses. */ +/* Bit 11 68040 Transfer Type (TT) 0:TT are both low 1:TT are both high */ + +#define DMV170_USER_LINK0_STATUS_MASK 0x1000 +#define DMV170_USER_LINK0_OPEN 0x1000 +#define DMV170_USER_LINK0_INSTALLED 0x0000 +#define DMV170_LOWER_STATUS_LED_CONTROL_MASK 0x2000 +#define DMV170_LOWER_STATUS_LED_IS_OFF 0x2000 +#define DMV170_LOWER_STATUS_LED_IS_ON 0x0000 +#ifdef DMV176 + /* The following are not available for the DMV171 */ +#define DMV170_RAM_TYPE_MASK 0x4000 +#define DMV170_RAM_TYPE_IS_DRAM 0x4000 +#define DMV170_RAM_TYPE_IS_SRAM 0x0000 +#define DMV170_IACK_VECTOR_AUTOVECTOR_MASK 0x8000 +#define DMV170_IACK_VECTOR_AUTOVECTOR_IS_VECTOR 0x8000 +#define DMV170_IACK_VECTOR_AUTOVECTOR_IS_NOT_VECTOR 0x0000 +#endif + +/* + * The following defines the bits in the Timer Control Register. + */ +#define DMV170_TIMER0_ENABLE_MASK 0x0001 +#define DMV170_TIMER0_IS_ENABLED 0x0001 +#define DMV170_TIMER0_IS_DISABLED 0x0000 +#define DMV170_TIMER1_ENABLE_MASK 0x0002 +#define DMV170_TIMER1_IS_ENABLED 0x0002 +#define DMV170_TIMER1_IS_DISABLED 0x0000 +#define DMV170_TIMER2_ENABLE_MASK 0x0004 +#define DMV170_TIMER2_IS_ENABLED 0x0004 +#define DMV170_TIMER2_IS_DISABLED 0x0000 +#define DMV170_TIMER1_CLOCK_MASK 0x0008 +#define DMV170_TIMER1_CLOCK_AT_TIMER0 0x0008 +#define DMV170_TIMER1_CLOCK_AT_1MHZ 0x0000 + +#define DMV170_TIMER2_CLOCK_MASK 0x0010 +#define DMV170_TIMER2_CLOCK_AT_TIMER0 0x0010 +#define DMV170_TIMER2_CLOCK_AT_1MHZ 0x0000 +#define DMV170_TIMER0_INTERRUPT_MASK 0x0020 +#define DMV170_TIMER0_INTERRUPT_ENABLE 0x0020 +#define DMV170_TIMER0_INTERRUPT_CLEAR 0x0000 +#define DMV170_TIMER1_INTERRUPT_MASK 0x0040 +#define DMV170_TIMER1_INTERRUPT_ENABLE 0x0040 +#define DMV170_TIMER1_INTERRUPT_CLEAR 0x0000 +#define DMV170_TIMER2_INTERRUPT_MASK 0x0080 +#define DMV170_TIMER2_INTERRUPT_ENABLE 0x0080 +#define DMV170_TIMER2_INTERRUPT_CLEAR 0x0000 + + + +/* The Following definethe bits for the Card Resource Register */ +#define DMV170_DUART_INTERRUPT_MASK 0x0001 /* DUART Interrupt Sense Bit */ +#define DMV170_DUART_INTERRUPT_NEGATE 0x0001 +#define DMV170_DUART_INTERRUPT_ASSERT 0x0000 +#define DMV170_SONIC_INTERRUPT_MASK 0x0002 /* SONIC Interrupt Sense Bit */ +#define DMV170_SONIC_INTERRUPT_NEGATE 0x0002 +#define DMV170_SONIC_INTERRUPT_ASSERT 0x0000 +#define DMV170_SCSI_INTERRUPT_MASK 0x0004 /* SCSI Interrupt Sense Bit */ +#define DMV170_SCSI_INTERRUPT_NEGATE 0x0004 +#define DMV170_SCSI_INTERRUPT_ASSERT 0x0000 +#define DMV170_SCC_INTERRUPT_MASK 0x0008 /* SCC Interrupt Sense Bit */ +#define DMV170_SCC_INTERRUPT_NEGATE 0x0008 +#define DMV170_SCC_INTERRUPT_ASSERT 0x0000 +#define DMV170_SNOOP_ENABLE_MASK 0x0010 /* CPU Snoop Enable Bit */ +#define DMV170_SNOOP_DISABLE 0x0010 +#define DMV170_SNOOP_ENABLE 0x0000 +#define DMV170_SONIC_RESET_MASK 0x0020 /* SONIC RESET Control */ +#define DMV170_SONIC_RESET_CLEAR 0x0020 +#define DMV170_SONIC_RESET_HOLD 0x0000 +#define DMV170_NV64_WE_MASK 0x0040 /* 64-bit Non-Volital Memory */ +#define DMV170_NV64_WRITE_ENABLE 0x0040 /* Write Enable */ +#define DMV170_NV64_WRITE_DISABLE 0x0000 +#define DMV170_BOOT_NV16_MASK 0x0080 /* BOOT Device Type */ +#define DMV170_BOOT_64_BIT 0x0080 +#define DMV170_BOOT_16_BIT 0x0000 +#define DMV170_DUART_INST_MASK 0x0100 /* DUART Sense Bit */ +#define DMV170_DUART_INSTALLED 0x0100 +#define DMV170_DUART_NOT_INSTALLED 0x0000 +#define DMV170_SONIC_INST_MASK 0x0200 /* SONIC Sense Bit */ +#define DMV170_SONIC_INSTALLED 0x0200 +#define DMV170_SONIC_NOT_INSTALLED 0x0000 +#define DMV170_16M_NV64_MASK 0x0400 /* 16 Mb of 64bit Flash Sense */ +#define DMV170_16Mb_FLASH_INSTALLED 0x0400 +#define DMV170_8Mb_FLASH_INSTALLED 0x0000 +#define DMV170_SCC_INST_MASK 0x0800 /* SCC Sense Bit */ +#define DMV170_SCC_INSTALLED 0x0800 +#define DMV170_SCC_NOT_INSTALLED 0x0000 +#define DMV170_RTC_INST_MASK 0x1000 /* RTC Sense Bit */ +#define DMV170_RTC_INSTALLED 0x1000 +#define DMV170_RTC_NOT_INSTALLED 0x0000 +#define DMV170_NV64_INST_MASK 0x2000 /* 64bit Non-Volital Mem Sense*/ + +#define DMV170_64_BIT_NON_VOLITAL_MEM_INSTALLED 0x2000 +#define DMV170_64_BIT_NON_VOLITAL_MEM_NOT_INSTALLED 0x0000 + + +/* + * DUART Baud Rate Definations. + */ +#define DMV170_DUART_9621 MC68681_BAUD_RATE_MASK_600 /* close to 9600 */ + +#define DMV170_RTC_FREQUENCY 0x0000 + + +/* + * CPU General Purpose Interrupt definations (PPC_IRQ_EXTERNAL). + * Note: For the interrupt level read the lower 3 bits of the + * Local Control and Status Register. + */ +#define DMV170_IRQ_FIRST ( PPC_IRQ_LAST + 1 ) + +#define DMV170_LIRQ0 ( DMV170_IRQ_FIRST + 0 ) +#define DMV170_LIRQ1 ( DMV170_IRQ_FIRST + 1 ) +#define DMV170_LIRQ2 ( DMV170_IRQ_FIRST + 2 ) +#define DMV170_LIRQ3 ( DMV170_IRQ_FIRST + 3 ) +#define DMV170_LIRQ4 ( DMV170_IRQ_FIRST + 4 ) +#define DMV170_LIRQ5 ( DMV170_IRQ_FIRST + 5 ) + +#define MAX_BOARD_IRQS DMV170_LIRQ5 +#ifdef __cplusplus +} +#endif + +#endif /* !_INCLUDE_DMV170_h */ +/* end of include file */ + + + + + + + diff --git a/c/src/lib/libbsp/powerpc/dmv177/include/tod.h b/c/src/lib/libbsp/powerpc/dmv177/include/tod.h new file mode 100644 index 0000000000..d51ceb23b9 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/include/tod.h @@ -0,0 +1,38 @@ +/* + * Real Time Clock (MK48T08) for RTEMS on Score603e + * + * Based on MVME162 TOD by: + * COPYRIGHT (C) 1997 + * by Katsutoshi Shibuya - BU Denken Co.,Ltd. - Sapporo - JAPAN + * ALL RIGHTS RESERVED + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#ifndef TOD_H +#define TOD_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern void setRealTimeToRTEMS(); +/* Read real time from RTC and set it to RTEMS' clock manager */ + +extern void setRealTimeFromRTEMS(); +/* Read time from RTEMS' clock manager and set it to RTC */ + +extern int checkRealTime(); +/* Return the difference between RTC and RTEMS' clock manager time in minutes. + If the difference is greater than 1 day, this returns 9999. */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/lib/libbsp/powerpc/dmv177/sonic/Makefile.in b/c/src/lib/libbsp/powerpc/dmv177/sonic/Makefile.in new file mode 100644 index 0000000000..dcab232876 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/sonic/Makefile.in @@ -0,0 +1,62 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +RTEMS_ROOT = @RTEMS_ROOT@ +PROJECT_ROOT = @PROJECT_ROOT@ +RTEMS_CUSTOM = $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg + +PGM=${ARCH}/sonic.rel + +# C source names, if any, go here -- minus the .c +C_PIECES=sonic +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +H_FILES= + +# Assembly source names, if any, go here -- minus the .s +S_PIECES= +S_FILES=$(S_PIECES:%=%.s) +S_O_FILES=$(S_FILES:%.s=${ARCH}/%.o) + +SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES) +OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES) + +include $(RTEMS_CUSTOM) +include $(PROJECT_ROOT)/make/leaf.cfg + + +# +# (OPTIONAL) Add local stuff here using += +# + +DEFINES += +CPPFLAGS += +CFLAGS += + +LD_PATHS += +LD_LIBS += +LDFLAGS += + +# +# Add your list of files to delete here. The config files +# already know how to delete some stuff, so you may want +# to just run 'make clean' first to see what gets missed. +# 'make clobber' already includes 'make clean' +# + +CLEAN_ADDITIONS += +CLOBBER_ADDITIONS += + +${PGM}: ${SRCS} ${OBJS} + $(make-rel) + +all: ${ARCH} $(SRCS) $(PGM) + +# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile +install: all diff --git a/c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.c b/c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.c new file mode 100644 index 0000000000..cd748d59b7 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.c @@ -0,0 +1,1176 @@ +/* + ******************************************************************* + ******************************************************************* + ** ** + ** RTEMS/KA9Q DRIVER FOR NATIONAL DP83932 `SONIC' ** + ** SYSTEMS-ORIENTED NETWORK INTERFACE CONTROLLER ** + ** ** + ******************************************************************* + ******************************************************************* + */ + +/* + * $Revision$ $Date$ $Author$ + * $State$ + */ + +/* + * References: + * 1) DP83932C-20/25/33 MHz SONIC(TM) Systems-Oriented Network Interface + * Controller data sheet. TL/F/10492, RRD-B30M105, National Semiconductor, + * 1995. + * + * 2) Software Driver Programmer's Guide for the DP83932 SONIC(TM), + * Application Note 746, Wesley Lee and Mike Lui, TL/F/11140, + * RRD-B30M75, National Semiconductor, March, 1991. + * + * 3) SVME/DMV-171 Single Board Computer Documentation Package, #805905, + * DY 4 Systems Inc., Kanata, Ontario, September, 1996. + */ +#include "sonic.h" + +#include <rtems/error.h> +#include <ka9q/rtems_ka9q.h> +#include <ka9q/global.h> +#include <ka9q/domain.h> +#include <ka9q/enet.h> +#include <ka9q/iface.h> +#include <ka9q/netuser.h> +#include <ka9q/trace.h> +#include <ka9q/commands.h> + +/* + * Number of devices supported by this driver + */ +#ifndef NSONIC +# define NSONIC 1 +#endif + +/* + * Default location of device registers + */ +#ifndef SONIC_BASE_ADDRESS +# define SONIC_BASE_ADDRESS 0xF3000000 +# warning "Using default SONIC_BASE_ADDRESS." +#endif + +/* + * Default interrupt vector + */ +#ifndef SONIC_VECTOR +# define SONIC_VECTOR 1 +# warning "Using default SONIC_VECTOR." +#endif + +/* + * Default device configuration register values + * Conservative, generic values. + * DCR: + * No extended bus mode + * Unlatched bus retry + * Programmable outputs unused + * Asynchronous bus mode + * User definable pins unused + * No wait states (access time controlled by DTACK*) + * 32-bit DMA + * Empty/Fill DMA mode + * Maximum Transmit/Receive FIFO + * DC2: + * Extended programmable outputs unused + * Normal HOLD request + * Packet compress output unused + * No reject on CAM match + */ +#ifndef SONIC_DCR +# define SONIC_DCR (DCR_DW | DCR_TFT1 | DCR_TFT0) +#endif +#ifndef SONIC_DC2 +# define SONIC_DC2 (0) +#endif + +/* + * Default sizes of transmit and receive descriptor areas + */ +#define RDA_COUNT 20 +#define TDA_COUNT 10 + +/* + * + * As suggested by National Application Note 746, make the + * receive resource area bigger than the receive descriptor area. + */ +#define RRA_EXTRA_COUNT 3 + +/* + * RTEMS event used by interrupt handler to signal daemons. + */ +#define INTERRUPT_EVENT RTEMS_EVENT_1 + +/* + * Largest Ethernet frame. + */ +#define MAXIMUM_FRAME_SIZE 1518 + +/* + * Receive buffer size. + * Allow for a pointer, plus a full ethernet frame (including Frame + * Check Sequence) rounded up to a 4-byte boundary. + */ +#define RBUF_SIZE ((sizeof (void *) + (MAXIMUM_FRAME_SIZE) + 3) & ~3) +#define RBUF_WC ((((MAXIMUM_FRAME_SIZE) + 3) & ~3) / 2) + +/* + * Macros for manipulating 32-bit pointers as 16-bit fragments + */ +#define LSW(p) ((rtems_unsigned16)((rtems_unsigned32)(p))) +#define MSW(p) ((rtems_unsigned16)((rtems_unsigned32)(p) >> 16)) +#define PTR(m,l) ((void*)(((rtems_unsigned16)(m)<<16)|(rtems_unsigned16)(l))) + +/* + * Hardware-specific storage + */ +struct sonic { + /* + * Connection to KA9Q + */ + struct iface *iface; + + /* + * Default location of device registers + * ===CACHE=== + * This area must be non-cacheable, guarded. + */ + volatile struct SonicRegisters *sonic; + + /* + * Interrupt vector + */ + rtems_vector_number vector; + + /* + * Task waiting for transmit resources + */ + rtems_id txWaitTid; + + /* + * Receive resource area + */ + int rdaCount; + ReceiveResourcePointer_t rsa; + + /* + * Transmit descriptors + */ + int tdaCount; + TransmitDescriptorPointer_t tdaHead; /* Last filled */ + TransmitDescriptorPointer_t tdaTail; /* Next to retire */ + int tdaActiveCount; + + /* + * Statistics + */ + unsigned long rxInterrupts; + unsigned long rxMissed; + unsigned long rxGiant; + unsigned long rxNonOctet; + unsigned long rxBadCRC; + unsigned long rxCollision; + + unsigned long txInterrupts; + unsigned long txSingleCollision; + unsigned long txMultipleCollision; + unsigned long txCollision; + unsigned long txDeferred; + unsigned long txUnderrun; + unsigned long txLateCollision; + unsigned long txExcessiveCollision; + unsigned long txExcessiveDeferral; + unsigned long txLostCarrier; + unsigned long txRawWait; +}; +static struct sonic sonic[NSONIC]; + +/* + ****************************************************************** + * * + * Support Routines * + * * + ****************************************************************** + */ + +/* + * Allocate non-cacheable memory on a single 64k page. + * Very simple minded -- just keeps trying till the memory is on a single page. + */ +static void * +sonic_allocate (unsigned int nbytes) +{ + void *p; + unsigned long a1, a2; + + for (;;) { + /* + * ===CACHE=== + * Change malloc to malloc_noncacheable_guarded. + */ + p = malloc (nbytes); + if (p == NULL) + rtems_panic ("No memory!"); + a1 = (unsigned long)p; + a2 = a1 + nbytes - 1; + if ((a1 >> 16) == (a2 >> 16)) + break; + } + return p; +} + +/* + * Shut down the interface. + * This is a pretty simple-minded routine. It doesn't worry + * about cleaning up mbufs, shutting down daemons, etc. + */ +static int +sonic_stop (struct iface *iface) +{ + int i; + struct sonic *dp = &sonic[iface->dev]; + volatile struct SonicRegisters *rp = dp->sonic; + + /* + * Stop the transmitter and receiver. + */ + rp->cr = CR_HTX | CR_RXDIS; + + /* + * Wait for things to stop. + * For safety's sake, there is an alternate exit. + */ + i = 0; + while (rp->cr & (CR_RXEN | CR_TXP)) { + if (++i == 10000) + break; + } + + /* + * Reset the device + */ + rp->cr = CR_RST; + rp->imr = 0; + return 0; +} + +/* + * Show interface statistics + */ +static void +sonic_show (struct iface *iface) +{ + struct sonic *dp = &sonic[iface->dev]; + + printf (" Rx Interrupts:%-8lu", dp->rxInterrupts); + printf (" Giant:%-8lu", dp->rxGiant); + printf (" Non-octet:%-8lu\n", dp->rxNonOctet); + printf (" Bad CRC:%-8lu", dp->rxBadCRC); + printf (" Collision:%-8lu", dp->rxCollision); + printf (" Missed:%-8lu\n", dp->rxMissed); + + printf ( " Tx Interrupts:%-8lu", dp->txInterrupts); + printf ( " Deferred:%-8lu", dp->txDeferred); + printf (" Lost Carrier:%-8lu\n", dp->txLostCarrier); + printf ( "Single Collisions:%-8lu", dp->txSingleCollision); + printf ( "Multiple Collisions:%-8lu", dp->txMultipleCollision); + printf ("Excessive Collisions:%-8lu\n", dp->txExcessiveCollision); + printf ( " Total Collisions:%-8lu", dp->txCollision); + printf ( " Late Collision:%-8lu", dp->txLateCollision); + printf (" Underrun:%-8lu\n", dp->txUnderrun); + printf ( " Raw output wait:%-8lu\n", dp->txRawWait); +} + +/* + ****************************************************************** + * * + * Interrupt Handler * + * * + ****************************************************************** + */ +static rtems_isr +sonic_interrupt_handler (rtems_vector_number v) +{ + struct sonic *dp = sonic; + volatile struct SonicRegisters *rp; + +#if (NSONIC > 1) + /* + * Find the device which requires service + */ + for (;;) { + if (dp->vector == v) + break; + if (++dp == &sonic[NSONIC]) + return; /* Spurious interrupt? */ + } +#endif /* NSONIC > 1 */ + + /* + * Get pointer to SONIC registers + */ + rp = dp->sonic; + + /* + * Packet received or receive buffer area exceeded? + */ + if ((rp->imr & (IMR_PRXEN | IMR_RBAEEN)) + && (rp->isr & (ISR_PKTRX | ISR_RBAE))) { + rp->imr &= ~(IMR_PRXEN | IMR_RBAEEN); + dp->rxInterrupts++; + rtems_event_send (dp->iface->rxproc, INTERRUPT_EVENT); + } + + /* + * Packet started, transmitter done or transmitter error? + */ + if ((rp->imr & (IMR_PINTEN | IMR_PTXEN | IMR_TXEREN)) + && (rp->isr & (ISR_PINT | ISR_TXDN | ISR_TXER))) { + rp->imr &= ~(IMR_PINTEN | IMR_PTXEN | IMR_TXEREN); + dp->txInterrupts++; + rtems_event_send (dp->txWaitTid, INTERRUPT_EVENT); + } +} + +/* + ****************************************************************** + * * + * Transmitter Routines * + * * + ****************************************************************** + */ + +/* + * Soak up transmit descriptors that have been sent. + */ +static void +sonic_retire_tda (struct sonic *dp) +{ + rtems_unsigned16 status; + unsigned int collisions; + + /* + * Repeat for all completed transmit descriptors. + */ + while ((dp->tdaActiveCount != 0) + && ((status = dp->tdaTail->status) != 0)) { + /* + * Check for errors which stop the transmitter. + */ + if (status & (TDA_STATUS_EXD | + TDA_STATUS_EXC | + TDA_STATUS_FU | + TDA_STATUS_BCM)) { + /* + * Restart the transmitter if there are + * packets waiting to go. + */ + rtems_unsigned16 link; + link = *(dp->tdaTail->linkp); + + if ((link & TDA_LINK_EOL) == 0) { + volatile struct SonicRegisters *rp = dp->sonic; + + rp->ctda = link; + rp->cr = CR_TXP; + } + } + + /* + * Update network statistics + */ + collisions = (status & TDA_STATUS_COLLISION_MASK) >> TDA_STATUS_COLLISION_SHIFT; + if (collisions) { + if (collisions == 1) + dp->txSingleCollision++; + else + dp->txMultipleCollision++; + dp->txCollision += collisions; + } + if (status & TDA_STATUS_EXC) + dp->txExcessiveCollision++; + if (status & TDA_STATUS_OWC) + dp->txLateCollision++; + if (status & TDA_STATUS_EXD) + dp->txExcessiveDeferral++; + if (status & TDA_STATUS_DEF) + dp->txDeferred++; + if (status & TDA_STATUS_FU) + dp->txUnderrun++; + if (status & TDA_STATUS_CRSL) + dp->txLostCarrier++; + + /* + * Free the packet + */ + dp->tdaActiveCount--; + free_p ((struct mbuf **)&dp->tdaTail->mbufp); + + /* + * Move to the next transmit descriptor + */ + dp->tdaTail = dp->tdaTail->next; + } +} + +/* + * Send raw packet (caller provides header). + * This code runs in the context of the interface transmit + * task (most packets) or in the context of the network + * task (for ARP requests). + */ +static int +sonic_raw (struct iface *iface, struct mbuf **bpp) +{ + struct sonic *dp = &sonic[iface->dev]; + volatile struct SonicRegisters *rp = dp->sonic; + struct mbuf *bp; + TransmitDescriptorPointer_t tdp; + volatile struct TransmitDescriptorFragLink *fp; + unsigned int packetSize; + int i; + static char padBuf[64]; + + /* + * Update the log. + */ + iface->rawsndcnt++; + iface->lastsent = secclock (); + dump (iface, IF_TRACE_OUT, *bpp); + + /* + * It would not do to have two tasks active in the transmit + * loop at the same time. + * The blocking is simple-minded since the odds of two tasks + * simultaneously attempting to use this code are low. The only + * way that two tasks can try to run here is: + * 1) Task A enters this code and ends up having to + * wait for a transmit buffer descriptor. + * 2) Task B gains control and tries to transmit a packet. + * The RTEMS/KA9Q scheduling semaphore ensures that there + * are no race conditions associated with manipulating the + * txWaitTid variable. + */ + if (dp->txWaitTid) { + dp->txRawWait++; + while (dp->txWaitTid) + rtems_ka9q_ppause (10); + } + + /* + * Free up transmit descriptors. + */ + sonic_retire_tda (dp); + + /* + * Wait for transmit descriptor to become available. + */ + if (dp->tdaActiveCount == dp->tdaCount) { + /* + * Find out who we are + */ + if (dp->txWaitTid == 0) + rtems_task_ident (RTEMS_SELF, 0, &dp->txWaitTid); + + /* + * Clear old events. + */ + rp->isr = ISR_PINT | ISR_TXDN | ISR_TXER; + + /* + * Wait for transmit descriptor to become available. + * Note that the transmit descriptors are checked + * *before* * entering the wait loop -- this catches + * the possibility that a transmit descriptor became + * available between the `if' the started this block, + * and the clearing of the interrupt status register. + */ + sonic_retire_tda (dp); + while (dp->tdaActiveCount == dp->tdaCount) { + /* + * Enable transmitter interrupts. + */ + rp->imr |= (IMR_PINTEN | IMR_PTXEN | IMR_TXEREN); + + /* + * Wait for interrupt + */ + rtems_ka9q_event_receive (INTERRUPT_EVENT, + RTEMS_WAIT|RTEMS_EVENT_ANY, + RTEMS_NO_TIMEOUT); + rp->isr = ISR_PINT | ISR_TXDN | ISR_TXER; + sonic_retire_tda (dp); + } + } + + /* + * Get the head of the packet mbuf chain. + */ + bp = *bpp; + + /* + * Fill in the transmit descriptor fragment descriptors. + * ===CACHE=== + * If data cache is operating in write-back mode, flush cached + * data to memory. + */ + tdp = dp->tdaHead->next; + tdp->mbufp = bp; + packetSize = 0; + fp = tdp->frag; + for (i = 0 ; i < MAXIMUM_FRAGS_PER_DESCRIPTOR ; i++, fp++) { + fp->frag_lsw = LSW(bp->data); + fp->frag_msw = MSW(bp->data); + fp->frag_size = bp->cnt; + packetSize += bp->cnt; + + /* + * Break out of the loop if this mbuf is the last in the frame. + */ + if ((bp = bp->next) == NULL) + break; + } + + /* + * Pad short packets. + */ + if ((packetSize < 64) && (i < MAXIMUM_FRAGS_PER_DESCRIPTOR)) { + int padSize = 64 - packetSize; + fp->frag_lsw = LSW(padBuf); + fp->frag_msw = MSW(padBuf); + fp->frag_size = padSize; + packetSize += padSize; + i++; + fp++; + } + + /* + * Fill Transmit Descriptor + */ + tdp->pkt_size = packetSize; + tdp->frag_count = i; + tdp->status = 0; + + /* + * Chain onto list and start transmission. + */ + tdp->linkp = &fp->frag_link; + *tdp->linkp = LSW(tdp->next) | TDA_LINK_EOL; + *dp->tdaHead->linkp &= ~TDA_LINK_EOL; + rp->cr = CR_TXP; + dp->tdaActiveCount++; + dp->tdaHead = tdp; + + /* + * Let KA9Q know the packet is on the way. + */ + dp->txWaitTid = 0; + *bpp = NULL; + return 0; +} + +/* + ****************************************************************** + * * + * Receiver Routines * + * * + ****************************************************************** + */ + +/* + * Wait for SONIC to hand over a Receive Descriptor. + */ +static void +sonic_rda_wait (struct sonic *dp, ReceiveDescriptorPointer_t rdp) +{ + int i; + volatile struct SonicRegisters *rp = dp->sonic; + + /* + * Wait for Receive Descriptor. + * The order of the tests is very important. + * The RDA is checked after RBAE is detected. This ensures that + * the driver processes all RDA entries before reusing the RRA + * entry holding the giant packet. + * The event wait is done after the RDA and RBAE checks. This + * catches the possibility that a Receive Descriptor became ready + * between the call to this function and the clearing of the + * interrupt status register bit. + */ + for (;;) { + /* + * Has a giant packet arrived? + * The National DP83932C data sheet is very vague on what + * happens under this condition. The description of the + * Interrupt Status Register (Section 4.3.6) states, + * ``Reception is aborted and the SONIC fetches the next + * available resource descriptors in the RRA. The buffer + * space is not re-used and an RDA is not setup for the + * truncated packet.'' + * I take ``Reception is aborted'' to mean that the RXEN + * bit in the Command Register is cleared and must be set + * by the driver to begin reception again. + * Unfortunately, an alternative interpretation could be + * that only reception of the current packet is aborted. + * This would be more difficult to recover from.... + */ + if (rp->isr & ISR_RBAE) { + /* + * One more check to soak up any Receive Descriptors + * that may already have been handed back to the driver. + */ + if (rdp->in_use == 0) + break; + + /* + * Check my interpretation of the SONIC manual. + */ + if (rp->cr & CR_RXEN) + rtems_panic ("SONIC RBAE/RXEN"); + + /* + * Update statistics + */ + dp->rxGiant++; + + /* + * Reuse receive buffer. + * Again, the manual is subject to interpretation. The + * RRP register is described as, `the lower address of + * the next descriptor the SONIC will read.'' + * Since, acording to the ISR/RBAE notes, the SONIC has + * ``fetched the next available resource descriptor in + * the RRA'', I interpret this to mean that that the + * driver has to move the RRP back *two* entries to + * reuse the receive buffer holding the giant packet. + */ + for (i = 0 ; i < 2 ; i++) { + if (rp->rrp == rp->rsa) + rp->rrp = rp->rea; + rp->rrp -= sizeof (ReceiveResource_t); + } + + /* + * Restart reception + */ + rp->isr = ISR_RBAE; + rp->cr = CR_RXEN; + } + + /* + * Clear old packet-received events. + */ + rp->isr = ISR_PKTRX; + + /* + * Has Receive Descriptor become available? + */ + if (rdp->in_use == 0) + break; + + /* + * Enable interrupts. + */ + rp->imr |= IMR_PRXEN | IMR_RBAEEN; + + /* + * Wait for interrupt. + */ + rtems_ka9q_event_receive (INTERRUPT_EVENT, + RTEMS_WAIT|RTEMS_EVENT_ANY, + RTEMS_NO_TIMEOUT); + } +} + +/* + * SCC reader task + */ +static void +sonic_rx (int dev, void *p1, void *p2) +{ + struct iface *iface = (struct iface *)p1; + struct sonic *dp = (struct sonic *)p2; + volatile struct SonicRegisters *rp = dp->sonic; + struct mbuf *bp; + rtems_unsigned16 status; + ReceiveDescriptor_t *rda; + ReceiveDescriptorPointer_t ordp, rdp; + ReceiveResourcePointer_t rwp, rea; + rtems_unsigned16 newMissedTally, oldMissedTally; + int i; + int continuousCount; + + /* + * Set up list in Receive Resource Area. + * Allocate space for incoming packets. + */ + rwp = dp->rsa; + for (i = 0 ; i < (dp->rdaCount + RRA_EXTRA_COUNT) ; i++, rwp++) { + struct mbuf **mbp; + + /* + * Allocate memory for buffer. + * Place a pointer to the mbuf at the beginning of the buffer + * so we can find the mbuf when the SONIC returns the buffer + * to the driver. + */ + bp = ambufw (RBUF_SIZE); + mbp = (struct mbuf **)bp->data; + bp->data += sizeof *mbp; + *mbp = bp; + + /* + * Set up RRA entry + */ + rwp->buff_ptr_lsw = LSW(bp->data); + rwp->buff_ptr_msw = MSW(bp->data); + rwp->buff_wc_lsw = RBUF_WC; + rwp->buff_wc_msw = 0; + } + rea = rwp; + + /* + * Set up remaining Receive Resource Area pointers + */ + rp->rsa = LSW(dp->rsa); + rp->rrp = LSW(dp->rsa); + rp->rea = LSW(rea); + rp->rwp = LSW(rea); + + /* + * Set End Of Buffer Count register to the value recommended + * in Note 1 of Section 3.4.4.4 of the SONIC data sheet. + */ + rp->eobc = RBUF_WC - 2; + + /* + * Set up circular linked list in Receive Descriptor Area. + * Leaves ordp pointing at the `end' of the list and + * rdp pointing at the `beginning' of the list. + */ + rda = sonic_allocate (dp->rdaCount * sizeof *rda); + ordp = rdp = rda; + for (i = 0 ; i < dp->rdaCount ; i++) { + /* + * Set up RDA entry + */ + if (i == (dp->rdaCount - 1)) + rdp->next = rda; + else + rdp->next = (ReceiveDescriptor_t *)(rdp + 1); + rdp->in_use = 1; + ordp = rdp; + rdp = rdp->next; + ordp->link = LSW(rdp); + } + ordp->link |= RDA_LINK_EOL; + rp->urda = MSW(rdp); + rp->crda = LSW(rdp); + + /* + * Start the receiver + */ + oldMissedTally = rp->mpt; + rp->cr = CR_RRRA; + rp->cr = CR_RXEN; + + /* + * Input packet handling loop + */ + continuousCount = 0; + for (;;) { + /* + * Wait till SONIC supplies a Receive Descriptor. + */ + if (rdp->in_use) { + continuousCount = 0; + sonic_rda_wait (dp, rdp); + } + + /* + * Check that packet is valid + */ + status = rdp->status; + if (status & RDA_STATUS_PRX) { + struct mbuf **mbp; + void *p; + + /* + * Get the mbuf pointer + */ + p = PTR(rdp->pkt_msw, rdp->pkt_lsw); + mbp = (struct mbuf **)p - 1; + bp = *mbp; + + /* + * Pass the packet up the chain. + * The mbuf count is reduced to remove + * the frame check sequence at the end + * of the packet. + * ===CACHE=== + * Invalidate cache entries for this memory. + */ + bp->cnt = rdp->byte_count - sizeof (uint32); + net_route (iface, &bp); + + /* + * Give the network code a chance to digest the + * packet. This guards against a flurry of + * incoming packets (usually an ARP storm) from + * using up all the available memory. + */ + if (++continuousCount >= dp->rdaCount) + kwait_null (); + + /* + * Sanity check that Receive Resource Area is + * still in sync with Receive Descriptor Area + * The buffer reported in the Receive Descriptor + * should be the same as the buffer in the Receive + * Resource we are about to reuse. + */ + if ((LSW(p) != rwp->buff_ptr_lsw) + || (MSW(p) != rwp->buff_ptr_msw)) + rtems_panic ("SONIC RDA/RRA"); + + /* + * Allocate a new mbuf. + */ + bp = ambufw (RBUF_SIZE); + mbp = (struct mbuf **)bp->data; + bp->data += sizeof *mbp; + *mbp = bp; + + /* + * Reuse Receive Resource. + */ + rwp->buff_ptr_lsw = LSW(bp->data); + rwp->buff_ptr_msw = MSW(bp->data); + rwp++; + if (rwp == rea) + rwp = dp->rsa; + rp->rwp = LSW(rwp); + + /* + * Tell the SONIC to reread the RRA. + */ + if (rp->isr & ISR_RBE) + rp->isr = ISR_RBE; + } + else { + if (status & RDA_STATUS_COL) + dp->rxCollision++; + if (status & RDA_STATUS_FAER) + dp->rxNonOctet++; + else if (status & RDA_STATUS_CRCR) + dp->rxBadCRC++; + } + + /* + * Count missed packets + */ + newMissedTally = rp->mpt; + if (newMissedTally != oldMissedTally) { + dp->rxMissed += (newMissedTally - oldMissedTally) & 0xFFFF; + newMissedTally = oldMissedTally; + } + + /* + * Move to next receive descriptor + */ + rdp->link |= RDA_LINK_EOL; + rdp->in_use = 1; + ordp->link &= ~RDA_LINK_EOL; + ordp = rdp; + rdp = rdp->next; + } +} + +/* + ****************************************************************** + * * + * Initialization Routines * + * * + ****************************************************************** + */ + +/* + * Initialize the SONIC hardware + */ +static void +sonic_initialize_hardware (struct sonic *dp, int broadcastFlag) +{ + volatile struct SonicRegisters *rp = dp->sonic; + int i; + unsigned char *hwaddr; + rtems_status_code sc; + rtems_isr_entry old_handler; + TransmitDescriptorPointer_t otdp, tdp; + struct CamDescriptor{ + rtems_unsigned32 cep; + rtems_unsigned32 cap0; + rtems_unsigned32 cap1; + rtems_unsigned32 cap2; + rtems_unsigned32 ce; + }; + volatile struct CamDescriptor *cdp; + + /* + * Issue a software reset if necessary. + */ + if ((rp->cr & CR_RST) == 0) + rp->cr = CR_RST; + + /* + * Set up data configuration registers. + */ + rp->dcr = SONIC_DCR; + rp->dcr2 = SONIC_DC2; + + /* + * Remove device reset + */ + rp->cr = 0; + + /* + * Clear outstanding interrupts. + */ + rp->isr = 0x7FFF; + + /* + * Allocate the receive resource area. + * In accordance with National Application Note 746, make the + * receive resource area bigger than the receive descriptor area. + * This has the useful side effect of making the receive resource + * area big enough to hold the CAM descriptor area. + */ + dp->rsa = sonic_allocate ((dp->rdaCount + RRA_EXTRA_COUNT) * sizeof *dp->rsa); + rp->urra = MSW(dp->rsa); + + /* + * Set up the SONIC CAM with our hardware address. + * Use the Receive Resource Area to hold the CAM Descriptor Area. + */ + hwaddr = dp->iface->hwaddr; + cdp = (struct CamDescriptor *)dp->rsa; + cdp->cep = 0; /* Fill first entry in CAM */ + cdp->cap2 = hwaddr[0] << 8 | hwaddr[1]; + cdp->cap1 = hwaddr[2] << 8 | hwaddr[3]; + cdp->cap0 = hwaddr[4] << 8 | hwaddr[5]; + cdp->ce = 0x0001; /* Enable first entry in CAM */ + rp->cdc = 1; /* One entry in CDA */ + rp->cdp = LSW(cdp); + rp->cr = CR_LCAM; /* Load the CAM */ + while (rp->cr & CR_LCAM) + continue; + + /* + * Verify that CAM was properly loaded. + */ + rp->cep = 0; /* Select first entry in CAM */ + if ((rp->cap2 != cdp->cap2) + || (rp->cap1 != cdp->cap1) + || (rp->cap0 != cdp->cap0) + || (rp->ce != cdp->ce)) { + printf ("Failed to load Ethernet address into SONIC CAM.\n" + " Wrote %04x%04x%04x - %#x\n" + " Read %04x%04x%04x - %#x\n", + cdp->cap2, cdp->cap1, cdp->cap0, cdp->ce, + rp->cap2, rp->cap1, rp->cap0, rp->ce); + rtems_panic ("SONIC LCAM"); + } + + /* + * Set up circular linked list in Transmit Descriptor Area. + * Use the PINT bit in the transmit configuration field to + * request an interrupt on every other transmitted packet. + */ + dp->tdaActiveCount = 0; + dp->tdaTail = sonic_allocate (dp->tdaCount * sizeof *tdp); + otdp = tdp = dp->tdaTail; + for (i = 0 ; i < dp->tdaCount ; i++) { + if (i & 1) + tdp->pkt_config = TDA_CONFIG_PINT; + else + tdp->pkt_config = 0; + if (i == (dp->tdaCount - 1)) + tdp->next = (TransmitDescriptor_t *)dp->tdaTail; + else + tdp->next = (TransmitDescriptor_t *)(tdp + 1); + otdp = tdp; + tdp = tdp->next; + } + dp->tdaHead = otdp; + dp->tdaHead->linkp = &dp->tdaHead->frag[0].frag_link; + rp->utda = MSW(dp->tdaTail); + rp->ctda = LSW(dp->tdaTail); + + /* + * Enable/disable reception of broadcast packets + */ + if (broadcastFlag) + rp->rcr = RCR_BRD; + else + rp->rcr = 0; + + /* + * Attach SONIC interrupt handler + */ + rp->imr = 0; + sc = rtems_interrupt_catch (sonic_interrupt_handler, dp->vector, &old_handler); + if (sc != RTEMS_SUCCESSFUL) + rtems_panic ("Can't attach SONIC interrupt handler: %s\n", + rtems_status_text (sc)); + + /* + * Remainder of hardware initialization is + * done by the receive and transmit daemons. + */ +} + +/* + * Attach an SONIC driver to the system + * This is the only `extern' function in the driver. + * + * argv[0]: interface label, e.g. "rtems" + * The remainder of the arguments are optional key/value pairs: + * mtu ## -- maximum transmission unit, default 1500 + * broadcast y/n -- accept or ignore broadcast packets, default yes + * rbuf ## -- Set number of receive descriptor entries + * tbuf ## -- Set number of transmit descriptor entries + * ip ###.###.###.### -- IP address + * ether ##:##:##:##:##:## -- Ethernet address + * reg ###### -- Address of SONIC device registers + * vector ### -- SONIC interrupt vector + */ +int +rtems_ka9q_driver_attach (int argc, char *argv[], void *p) +{ + struct sonic *dp; + struct iface *iface; + char *cp; + int argIndex; + int broadcastFlag; + char cbuf[30]; + + /* + * Find an unused entry + */ + dp = sonic; + for (;;) { + if (dp == &sonic[NSONIC]) { + printf ("No more SONIC devices.\n"); + return -1; + } + if (dp->iface == NULL) + break; + dp++; + } + if (if_lookup (argv[0]) != NULL) { + printf ("Interface %s already exists\n", argv[0]); + return -1; + } + + /* + * Create an inteface descriptor + */ + iface = callocw (1, sizeof *iface); + iface->name = strdup (argv[0]); + iface->dev = dp - sonic;; + + /* + * Set default values + */ + broadcastFlag = 1; + dp->txWaitTid = 0; + dp->rdaCount = RDA_COUNT; + dp->tdaCount = TDA_COUNT; + iface->mtu = 1500; + iface->addr = Ip_addr; + iface->hwaddr = mallocw (EADDR_LEN); + memset (iface->hwaddr, 0x08, EADDR_LEN); + dp->sonic = (struct SonicRegisters *)SONIC_BASE_ADDRESS; + dp->vector = SONIC_VECTOR; + + /* + * Parse remaining arguments + */ + for (argIndex = 1 ; argIndex < (argc - 1) ; argIndex++) { + if (strcmp ("mtu", argv[argIndex]) == 0) { + iface->mtu = strtoul (argv[++argIndex], NULL, 0); + } + else if (strcmp ("broadcast", argv[argIndex]) == 0) { + if (*argv[++argIndex] == 'n') + broadcastFlag = 0; + } + else if (strcmp ("rbuf", argv[argIndex]) == 0) { + /* + * The minimum RDA count is 2. A single-entry RDA + * would be difficult to use since the SONIC does + * not release (in_use = 0) the RDA that has the + * EOL bit set. + */ + dp->rdaCount = strtoul (argv[++argIndex], NULL, 0); + if ((dp->rdaCount <= 1) || (dp->rdaCount > 200)) { + printf ("RDA option (%d) is invalid.\n", dp->rdaCount); + return -1; + } + } + else if (strcmp ("tbuf", argv[argIndex]) == 0) { + dp->tdaCount = strtoul (argv[++argIndex], NULL, 0); + if ((dp->tdaCount <= 1) || (dp->tdaCount > 200)) { + printf ("TDA option (%d) is invalid.\n", dp->tdaCount); + return -1; + } + } + else if (strcmp ("ip", argv[argIndex]) == 0) { + iface->addr = resolve (argv[++argIndex]); + } + else if (strcmp ("ether", argv[argIndex]) == 0) { + gether (iface->hwaddr, argv[++argIndex]); + } + else if (strcmp ("reg", argv[argIndex]) == 0) { + dp->sonic = (struct SonicRegisters *)strtoul (argv[++argIndex], NULL, 0); + } + else if (strcmp ("vector", argv[argIndex]) == 0) { + dp->vector = strtoul (argv[++argIndex], NULL, 0); + } + else { + printf ("Argument %d (%s) is invalid.\n", argIndex, argv[argIndex]); + return -1; + } + } + printf ("Ethernet address: %s\n", pether (cbuf, iface->hwaddr)); + iface->raw = sonic_raw; + iface->stop = sonic_stop; + iface->show = sonic_show; + dp->iface = iface; + setencap (iface, "Ethernet"); + + /* + * Set up SONIC hardware + */ + sonic_initialize_hardware (dp, broadcastFlag); + + /* + * Chain onto list of interfaces + */ + iface->next = Ifaces; + Ifaces = iface; + + /* + * Start I/O daemons + */ + cp = if_name (iface, " tx"); + iface->txproc = newproc (cp, 2048, if_tx, iface->dev, iface, NULL, 0); + free (cp); + cp = if_name (iface, " rx"); + iface->rxproc = newproc (cp, 2048, sonic_rx, iface->dev, iface, dp, 0); + free (cp); + return 0; +} diff --git a/c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.h b/c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.h new file mode 100644 index 0000000000..2607e2a170 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.h @@ -0,0 +1,364 @@ +/* + ******************************************************************* + ******************************************************************* + ** ** + ** DECLARATIONS FOR NATIONAL DP83932 `SONIC' ** + ** SYSTEMS-ORIENTED NETWORK INTERFACE CONTROLLER ** + ** ** + ******************************************************************* + ******************************************************************* + */ + +/* + * $Revision$ $Date$ $Author$ + * $State$ + */ + +#ifndef _SONIC_DP83932_ +#define _SONIC_DP83932_ + +#include <bsp.h> + +/* + ****************************************************************** + * * + * Device Registers * + * * + ****************************************************************** + */ +struct SonicRegisters { + /* + * Command and status registers + */ + rtems_unsigned32 cr; /* Command */ + rtems_unsigned32 dcr; /* Data configuration */ + rtems_unsigned32 rcr; /* Receive control */ + rtems_unsigned32 tcr; /* Transmit control */ + rtems_unsigned32 imr; /* Interrupt mask */ + rtems_unsigned32 isr; /* Interrupt status */ + + /* + * Transmit registers + */ + rtems_unsigned32 utda; /* Upper transmit descriptor address */ + rtems_unsigned32 ctda; /* Current transmit descriptor address */ + + /* + * Receive registers + */ + rtems_unsigned32 pad0[5]; + rtems_unsigned32 urda; /* Upper receive descriptor address */ + rtems_unsigned32 crda; /* Current receive descriptor address */ + rtems_unsigned32 pad1[4]; + rtems_unsigned32 eobc; /* End of buffer word count */ + rtems_unsigned32 urra; /* Upper receive resource */ + rtems_unsigned32 rsa; /* Resource start address */ + rtems_unsigned32 rea; /* Resource end address */ + rtems_unsigned32 rrp; /* Resouce read pointer */ + rtems_unsigned32 rwp; /* Resouce read pointer */ + + /* + * Content-addressable memory registers + */ + rtems_unsigned32 pad2[8]; + rtems_unsigned32 cep; /* CAM entry pointer */ + rtems_unsigned32 cap2; /* CAM address port 2 */ + rtems_unsigned32 cap1; /* CAM address port 1 */ + rtems_unsigned32 cap0; /* CAM address port 0 */ + rtems_unsigned32 ce; /* CAM enable */ + rtems_unsigned32 cdp; /* CAM descriptor pointer */ + rtems_unsigned32 cdc; /* CAM descriptor count */ + + /* + * Silicon revision + */ + rtems_unsigned32 sr; /* Silicon revision */ + + /* + * Watchdog counters + */ + rtems_unsigned32 wt0; /* Watchdog timer 0 */ + rtems_unsigned32 wt1; /* Watchdog timer 1 */ + + /* + * Another receive register + */ + rtems_unsigned32 rsc; /* Receive sequence counter */ + + /* + * Tally counters + */ + rtems_unsigned32 crct; /* CRC error tally */ + rtems_unsigned32 faet; /* FAE tally */ + rtems_unsigned32 mpt; /* Missed packet tally */ + + /* + * Another command and status register + */ + rtems_unsigned32 pad3[16]; + rtems_unsigned32 dcr2; /* Data configuration 2 */ +}; + +/* + * Command register + */ +#define CR_LCAM 0x0200 +#define CR_RRRA 0x0100 +#define CR_RST 0x0080 +#define CR_ST 0x0020 +#define CR_STP 0x0010 +#define CR_RXEN 0x0008 +#define CR_RXDIS 0x0004 +#define CR_TXP 0x0002 +#define CR_HTX 0x0001 + +/* + * Data configuration register + */ +#define DCR_EXBUS 0x8000 +#define DCR_LBR 0x2000 +#define DCR_PO1 0x1000 +#define DCR_PO0 0x0800 +#define DCR_SBUS 0x0400 +#define DCR_USR1 0x0200 +#define DCR_USR0 0x0100 +#define DCR_WC1 0x0080 +#define DCR_WC0 0x0040 +#define DCR_DW 0x0020 +#define DCR_BMS 0x0010 +#define DCR_RFT1 0x0008 +#define DCR_RFT0 0x0004 +#define DCR_TFT1 0x0002 +#define DCR_TFT0 0x0001 + +/* + * Receive control register + */ +#define RCR_ERR 0x8000 +#define RCR_RNT 0x4000 +#define RCR_BRD 0x2000 +#define RCR_PRO 0x1000 +#define RCR_AMC 0x0800 +#define RCR_LB1 0x0400 +#define RCR_LB0 0x0200 +#define RCR_MC 0x0100 +#define RCR_BC 0x0080 +#define RCR_LPKT 0x0040 +#define RCR_CRS 0x0020 +#define RCR_COL 0x0010 +#define RCR_CRCR 0x0008 +#define RCR_FAER 0x0004 +#define RCR_LBK 0x0002 +#define RCR_PRX 0x0001 + +/* + * Transmit control register + */ +#define TCR_PINT 0x8000 +#define TCR_POWC 0x4000 +#define TCR_CRCI 0x2000 +#define TCR_EXDIS 0x1000 +#define TCR_EXD 0x0400 +#define TCR_DEF 0x0200 +#define TCR_NCRS 0x0100 +#define TCR_CRSL 0x0080 +#define TCR_EXC 0x0040 +#define TCR_OWC 0x0020 +#define TCR_PMB 0x0008 +#define TCR_FU 0x0004 +#define TCR_BCM 0x0002 +#define TCR_PTX 0x0001 + +/* + * Interrupt mask register + */ +#define IMR_BREN 0x4000 +#define IMR_HBLEN 0x2000 +#define IMR_LCDEN 0x1000 +#define IMR_PINTEN 0x0800 +#define IMR_PRXEN 0x0400 +#define IMR_PTXEN 0x0200 +#define IMR_TXEREN 0x0100 +#define IMR_TCEN 0x0080 +#define IMR_RDEEN 0x0040 +#define IMR_RBEEN 0x0020 +#define IMR_RBAEEN 0x0010 +#define IMR_CRCEN 0x0008 +#define IMR_FAEEN 0x0004 +#define IMR_MPEN 0x0002 +#define IMR_RFOEN 0x0001 + +/* + * Interrupt status register + */ +#define ISR_BR 0x4000 +#define ISR_HBL 0x2000 +#define ISR_LCD 0x1000 +#define ISR_PINT 0x0800 +#define ISR_PKTRX 0x0400 +#define ISR_TXDN 0x0200 +#define ISR_TXER 0x0100 +#define ISR_TC 0x0080 +#define ISR_RDE 0x0040 +#define ISR_RBE 0x0020 +#define ISR_RBAE 0x0010 +#define ISR_CRC 0x0008 +#define ISR_FAE 0x0004 +#define ISR_MP 0x0002 +#define ISR_RFO 0x0001 + +/* + * Data configuration register 2 + */ +#define DCR2_EXPO3 0x8000 +#define DCR2_EXPO2 0x4000 +#define DCR2_EXPO1 0x2000 +#define DCR2_EXPO0 0x1000 +#define DCR2_PH 0x0010 +#define DCR2_PCM 0x0004 +#define DCR2_PCNM 0x0002 +#define DCR2_RJCM 0x0001 + +/* + ****************************************************************** + * * + * Transmit Buffer Management * + * * + ****************************************************************** + */ + +/* + * Transmit descriptor area entry. + * There is one transmit descriptor for each packet to be transmitted. + * Statically reserve space for up to MAXIMUM_FRAGS_PER_PACKET fragments + * per descriptor. + */ +#define MAXIMUM_FRAGS_PER_DESCRIPTOR 6 +struct TransmitDescriptor { + rtems_unsigned32 status; + rtems_unsigned32 pkt_config; + rtems_unsigned32 pkt_size; + rtems_unsigned32 frag_count; + + /* + * Packet fragment pointers + */ + struct TransmitDescriptorFragLink { + rtems_unsigned32 frag_lsw; /* LSW of fragment address */ +#define frag_link frag_lsw + rtems_unsigned32 frag_msw; /* MSW of fragment address */ + rtems_unsigned32 frag_size; + } frag[MAXIMUM_FRAGS_PER_DESCRIPTOR]; + + /* + * Space for link if all fragment pointers are used. + */ + rtems_unsigned32 link_pad; + + /* + * Extra RTEMS/KA9Q stuff + */ + struct TransmitDescriptor *next; /* Circularly-linked list */ + struct mbuf *mbufp; /* First mbuf in packet */ + volatile rtems_unsigned32 *linkp; /* Pointer to un[xxx].link */ +}; +typedef struct TransmitDescriptor TransmitDescriptor_t; +typedef volatile TransmitDescriptor_t *TransmitDescriptorPointer_t; + +/* + * Transmit Configuration. + * For standard Ethernet transmission, all bits in the transmit + * configuration field are set to 0. + */ +#define TDA_CONFIG_PINT 0x8000 +#define TDA_CONFIG_POWC 0x4000 +#define TDA_CONFIG_CRCI 0x2000 +#define TDA_CONFIG_EXDIS 0x1000 + +/* + * Transmit status + */ +#define TDA_STATUS_COLLISION_MASK 0xF800 +#define TDA_STATUS_COLLISION_SHIFT 11 +#define TDA_STATUS_EXD 0x0400 +#define TDA_STATUS_DEF 0x0200 +#define TDA_STATUS_NCRS 0x0100 +#define TDA_STATUS_CRSL 0x0080 +#define TDA_STATUS_EXC 0x0040 +#define TDA_STATUS_OWC 0x0020 +#define TDA_STATUS_PMB 0x0008 +#define TDA_STATUS_FU 0x0004 +#define TDA_STATUS_BCM 0x0002 +#define TDA_STATUS_PTX 0x0001 + +#define TDA_LINK_EOL 0x1 + + + +/* + ****************************************************************** + * * + * Receive Buffer Management * + * * + ****************************************************************** + */ + +/* + * Receive resource area entry. + * There is one receive resource entry for each receive buffer area (RBA). + * This driver allows only one packet per receive buffer area, so one + * receive resource entry corresponds to one correctly-received packet. + */ +struct ReceiveResource { + rtems_unsigned32 buff_ptr_lsw; /* LSW of RBA address */ + rtems_unsigned32 buff_ptr_msw; /* MSW of RBA address */ + rtems_unsigned32 buff_wc_lsw; /* LSW of RBA size (16-bit words) */ + rtems_unsigned32 buff_wc_msw; /* MSW of RBA size (16-bit words) */ +}; +typedef struct ReceiveResource ReceiveResource_t; +typedef volatile ReceiveResource_t *ReceiveResourcePointer_t; + +/* + * Receive descriptor area entry. + * There is one receive descriptor for each packet received. + */ +struct ReceiveDescriptor { + rtems_unsigned32 status; + rtems_unsigned32 byte_count; + rtems_unsigned32 pkt_lsw; /* LSW of packet address */ + rtems_unsigned32 pkt_msw; /* MSW of packet address */ + rtems_unsigned32 seq_no; + rtems_unsigned32 link; + rtems_unsigned32 in_use; + + /* + * Extra RTEMS/KA9Q stuff + */ + struct ReceiveDescriptor *next; /* Circularly-linked list */ +}; +typedef struct ReceiveDescriptor ReceiveDescriptor_t; +typedef volatile ReceiveDescriptor_t *ReceiveDescriptorPointer_t; + +/* + * Receive status + */ +#define RDA_STATUS_ERR 0x8800 +#define RDA_STATUS_RNT 0x4000 +#define RDA_STATUS_BRD 0x2000 +#define RDA_STATUS_PRO 0x1000 +#define RDA_STATUS_AMC 0x0800 +#define RDA_STATUS_LB1 0x0400 +#define RDA_STATUS_LB0 0x0200 +#define RDA_STATUS_MC 0x0100 +#define RDA_STATUS_BC 0x0080 +#define RDA_STATUS_LPKT 0x0040 +#define RDA_STATUS_CRS 0x0020 +#define RDA_STATUS_COL 0x0010 +#define RDA_STATUS_CRCR 0x0008 +#define RDA_STATUS_FAER 0x0004 +#define RDA_STATUS_LBK 0x0002 +#define RDA_STATUS_PRX 0x0001 + +#define RDA_LINK_EOL 0x1 + +#endif /* _SONIC_DP83932_ */ diff --git a/c/src/lib/libbsp/powerpc/dmv177/start/Makefile.in b/c/src/lib/libbsp/powerpc/dmv177/start/Makefile.in new file mode 100644 index 0000000000..10d2b8a9ea --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/start/Makefile.in @@ -0,0 +1,56 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +RTEMS_ROOT = @RTEMS_ROOT@ +PROJECT_ROOT = @PROJECT_ROOT@ +RTEMS_CUSTOM = $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg + +PGMS=${ARCH}/start.o + +# C source names, if any, go here -- minus the .c +C_PIECES= +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +H_FILES= + +# Assembly source names, if any, go here -- minus the .s +S_PIECES=start +S_FILES=$(S_PIECES:%=%.s) +S_O_FILES=$(S_FILES:%.s=${ARCH}/%.o) + +SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES) +OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES) + +include $(RTEMS_CUSTOM) +include $(PROJECT_ROOT)/make/leaf.cfg + +# +# (OPTIONAL) Add local stuff here using += +# + +DEFINES += +CPPFLAGS += +CFLAGS += + +LD_PATHS += +LD_LIBS += +LDFLAGS += + +# +# Add your list of files to delete here. The config files +# already know how to delete some stuff, so you may want +# to just run 'make clean' first to see what gets missed. +# 'make clobber' already includes 'make clean' +# + +CLEAN_ADDITIONS += +CLOBBER_ADDITIONS += + +all: ${ARCH} $(SRCS) $(OBJS) $(PGM) + $(INSTALL_VARIANT) -m 555 ${PGMS} ${PROJECT_RELEASE}/lib diff --git a/c/src/lib/libbsp/powerpc/dmv177/start/start.s b/c/src/lib/libbsp/powerpc/dmv177/start/start.s new file mode 100644 index 0000000000..1b471c0d8c --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/start/start.s @@ -0,0 +1,117 @@ +/* + * This is based on the mvme-crt0.S file from libgloss/rs6000. + * crt0.S -- startup file for PowerPC systems. + * + * Copyright (c) 1995 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + * + * $Id$ + */ + +#include <rtems/score/targopts.h> +#include "ppc-asm.h" + + .file "start.s" + .section ".got2","aw" + .align 2 + +.LCTOC1 = .+32768 + + .extern FUNC_NAME(atexit) + .globl FUNC_NAME(__atexit) + .section ".sdata","aw" + .align 2 +FUNC_NAME(__atexit): /* tell C's eabi-ctor's we have an atexit function */ + .long FUNC_NAME(atexit)@fixup /* and that it is to register __do_global_dtors */ + + .section ".fixup","aw" + .align 2 + .long FUNC_NAME(__atexit) + + .section ".got2","aw" +.Ltable = .-.LCTOC1 + .long .LCTOC1 /* address we think .LCTOC1 is loaded at */ + +.Lbss_start = .-.LCTOC1 + .long __bss_start + +.Lend = .-.LCTOC1 + .long _end + +.Lstack = .-.LCTOC1 /* stack address if set by user */ + .long __stack + + .text +.Lptr: + .long .LCTOC1-.Laddr + + .globl _start + .type _start,@function +_start: + lis r5,0 + mr r4,r5 + ori r4,r4,0x0000 /* 0x2030 */ + mtmsr r4 + +/* Add special purpose register initialization based upon the console driver + * initialization of these registers XXXXX + */ + + bl .Laddr /* get current address */ + +.Laddr: + mflr r4 /* real address of .Laddr */ + lwz r5,(.Lptr-.Laddr)(r4) /* linker generated address of .LCTOC1 */ + add r5,r5,r4 /* correct to real pointer */ + lwz r4,.Ltable(r5) /* get linker's idea of where .Laddr is */ + subf r4,r4,r5 /* calculate difference between where linked and current */ + + /* clear bss */ + lwz r6,.Lbss_start(r5) /* calculate beginning of the BSS */ + lwz r7,.Lend(r5) /* calculate end of the BSS */ + add r6,r6,r4 /* adjust pointers */ + add r7,r7,r4 + + cmplw 1,r6,r7 + bc 4,4,.Ldone + + subf r8,r6,r7 /* number of bytes to zero */ + srwi r9,r8,2 /* number of words to zero */ + mtctr r9 + li r0,0 /* zero to clear memory */ + addi r6,r6,-4 /* adjust so we can use stwu */ +.Lloop: + stwu r0,4(r6) /* zero bss */ + bdnz .Lloop + +.Ldone: + + lwz r0,.Lstack(r5) /* stack address or 0 */ + cmplwi 1,r0,0 /* equal to 0? */ + bc 12,6,.Lnostack /* use default stack if == 0 */ + mr sp,r0 /* use user defined stack */ + +.Lnostack: + /* set up initial stack frame */ + addi sp,sp,-4 /* make sure we don't overwrite debug mem */ + lis r0,0 + stw r0,0(sp) /* clear back chain */ + stwu sp,-56(sp) /* push another stack frame */ + + /* Let her rip */ + bl FUNC_NAME(main) + + /* return value from main is argument to exit */ + bl FUNC_NAME(exit) + trap +.Lstart: + .size _start,.Lstart-_start diff --git a/c/src/lib/libbsp/powerpc/dmv177/startup/Makefile.in b/c/src/lib/libbsp/powerpc/dmv177/startup/Makefile.in new file mode 100644 index 0000000000..229bfa3eef --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/startup/Makefile.in @@ -0,0 +1,68 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +RTEMS_ROOT = @RTEMS_ROOT@ +PROJECT_ROOT = @PROJECT_ROOT@ +RTEMS_CUSTOM = $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg + +PGM=${ARCH}/startup.rel + +# C source names, if any, go here -- minus the .c +C_PIECES=bspstart sbrk setvec genpvec vmeintr +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +CC_PIECES=rtems-ctor +CC_FILES=$(CC_PIECES:%=%.cc) +CC_O_FILES=$(CC_PIECES:%=${ARCH}/%.o) + +H_FILES= + +# Assembly source names, if any, go here -- minus the .s +S_PIECES=bspclean +S_FILES=$(S_PIECES:%=%.s) +S_O_FILES=$(S_FILES:%.s=${ARCH}/%.o) + +SRCS=linkcmds $(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES) +OBJS=$(C_O_FILES) $(S_O_FILES) + +# We install the RTEMS constructor as a separate .o +# so it can be easily place correctly by the compiler config file. +INSTALLED_O_FILES=$(ARCH)/rtems-ctor.o + +include $(RTEMS_CUSTOM) +include $(PROJECT_ROOT)/make/leaf.cfg + +# +# (OPTIONAL) Add local stuff here using += +# + +DEFINES += +CPPFLAGS += +CFLAGS += + +LD_PATHS += +LD_LIBS += +LDFLAGS += + +# +# Add your list of files to delete here. The config files +# already know how to delete some stuff, so you may want +# to just run 'make clean' first to see what gets missed. +# 'make clobber' already includes 'make clean' +# + +CLEAN_ADDITIONS += +CLOBBER_ADDITIONS += + +${PGM}: ${SRCS} ${OBJS} + $(make-rel) + +all: ${ARCH} $(SRCS) $(INSTALLED_O_FILES) $(PGM) + $(INSTALL) $(srcdir)/linkcmds ${PROJECT_RELEASE}/lib + $(INSTALL_VARIANT) $(INSTALLED_O_FILES) ${PROJECT_RELEASE}/lib diff --git a/c/src/lib/libbsp/powerpc/dmv177/startup/bspclean.s b/c/src/lib/libbsp/powerpc/dmv177/startup/bspclean.s new file mode 100644 index 0000000000..339f9d6eb6 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/startup/bspclean.s @@ -0,0 +1,25 @@ +/* + * bspclean.s -- based on mvme-exit.S from libgloss which was designed to + * work for targets using the ppcbug monitor + * + * Copyright (c) 1995 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ + +#include "ppc-asm.h" + + .file "bspclean.s" + .text +FUNC_START(bsp_cleanup) + li r10,0x63 + sc +FUNC_END(bsp_cleanup) diff --git a/c/src/lib/libbsp/powerpc/dmv177/startup/bspstart.c b/c/src/lib/libbsp/powerpc/dmv177/startup/bspstart.c new file mode 100644 index 0000000000..fba086515c --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/startup/bspstart.c @@ -0,0 +1,312 @@ +/* bspstart.c + * + * This set of routines starts the application. It includes application, + * board, and monitor specific initialization and configuration. + * The generic CPU dependent initialization has been performed + * before any of these are invoked. + * + * Called by RTEMS::RTEMS constructor in rtems-ctor.cc + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994, 1997. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * $Id$ + */ + +#include <bsp.h> +#include <rtems/libio.h> + +#include <libcsupport.h> + +#include <string.h> +#include <fcntl.h> + +#ifdef STACK_CHECKER_ON +#include <stackchk.h> +#endif + +/* + * 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; +rtems_unsigned32 bsp_isr_level; + +/* PAGE + * + * bsp_libc_init + * + * Initialize whatever libc we are using called from bsp_postdriver_hook. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + * + */ + +void bsp_libc_init(void) +{ + extern int end; + rtems_unsigned32 heap_start; + rtems_unsigned32 heap_size; + + heap_start = (rtems_unsigned32) &end; + if (heap_start & (CPU_ALIGNMENT-1)) + heap_start = (heap_start + CPU_ALIGNMENT) & ~(CPU_ALIGNMENT-1); + + heap_size = BSP_Configuration.work_space_start - (void *)&end; + heap_size &= 0xfffffff0; /* keep it as a multiple of 16 bytes */ + + RTEMS_Malloc_Initialize((void *) heap_start, heap_size, 0); + + /* + * Init the RTEMS libio facility to provide UNIX-like system + * calls for use by newlib (ie: provide __rtems_open, __rtems_close, etc) + * Uses malloc() to get area for the iops, so must be after malloc init + */ + + rtems_libio_init(); + + /* + * Set up for the libc handling. + */ + + if (BSP_Configuration.ticks_per_timeslice > 0) + libc_init(1); /* reentrant if possible */ + else + libc_init(0); /* non-reentrant */ + +} + + +/* PAGE + * + * bsp_pretasking_hook + * + * BSP pretasking hook. Called just before drivers are initialized. + * Used to setup libc and install any BSP extensions. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + * + */ + +void bsp_pretasking_hook(void) +{ + bsp_libc_init(); + +#ifdef STACK_CHECKER_ON + /* + * Initialize the stack bounds checker + * We can either turn it on here or from the app. + */ + + Stack_check_Initialize(); +#endif + +#ifdef RTEMS_DEBUG + rtems_debug_enable( RTEMS_DEBUG_ALL_MASK ); +#endif + +} + +/* PAGE + * + * bsp_predriver_hook + * + * Initialization before drivers are setup. + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + */ + +void bsp_predriver_hook(void) +{ + initialize_external_exception_vector(); +} + +/* PAGE + * + * bsp_postdriver_hook + * + * After drivers are setup, register some "filenames" + * and open stdin, stdout, stderr files + * + * Newlib will automatically associate the files with these + * (it hardcodes the numbers) + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + * + */ + +void bsp_postdriver_hook(void) +{ + int stdin_fd, stdout_fd, stderr_fd; + int error_code; + + error_code = 'S' << 24 | 'T' << 16; + + if ((stdin_fd = __rtems_open("/dev/console", O_RDONLY, 0)) == -1) + rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' ); + + if ((stdout_fd = __rtems_open("/dev/console", O_WRONLY, 0)) == -1) + rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' ); + + if ((stderr_fd = __rtems_open("/dev/console", O_WRONLY, 0)) == -1) + rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' ); + + if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2)) + rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' ); +} + +/* PAGE + * + * bsp_start + * + * This routine does the bulk of the system initialization. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + * + */ + +void bsp_start( void ) +{ + unsigned char *work_space_start; + unsigned int msr_value = 0x2030; + + /* + * Set BSP to initial value. Note: This value is a guess + * check how the real board comes up. This is critical to + * getting the source to work with the debugger. + */ + _CPU_MSR_SET( msr_value ); + + /* + * Set up our hooks + * Make sure libc_init is done before drivers initialized so that + * they can use atexit() + */ + + Cpu_table.exceptions_in_RAM = TRUE; + + 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.idle_task = NULL; /* do not override system IDLE task */ + + Cpu_table.clicks_per_usec = 66 / 4; /* XXX get from linkcmds */ + + + /* + * SIS does zero out memory BUT only when IT begins execution. Thus + * if we want to have a clean slate in the workspace each time we + * begin execution of OUR application, then we must zero the workspace. + */ + + Cpu_table.do_zero_of_workspace = TRUE; + + /* + * This should be enough interrupt stack. + */ + + Cpu_table.interrupt_stack_size = (12 * 1024); + + /* + * DMV170 does not support MP configurations so there is really no way + * to check this out. + */ + + Cpu_table.extra_mpci_receive_server_stack = 0; + + /* + * Copy the table and allocate memory for the RTEMS Workspace + */ + + BSP_Configuration = Configuration; + +#if defined(RTEMS_POSIX_API) + BSP_Configuration.work_space_size *= 3; +#endif + + work_space_start = + (unsigned char *)&RAM_END - BSP_Configuration.work_space_size; + + if ( work_space_start <= (unsigned char *)&end ) { + DEBUG_puts( "bspstart: Not enough RAM!!!\n" ); + bsp_cleanup(); + } + + BSP_Configuration.work_space_start = work_space_start; + + /* + * Add 1 region for RTEMS Malloc + */ + + BSP_Configuration.RTEMS_api_configuration->maximum_regions++; + + /* + * Account for the console's resources + */ + + console_reserve_resources( &BSP_Configuration ); + +#ifdef RTEMS_NEWLIB + /* + * Add 1 extension for newlib libc + */ + + BSP_Configuration.maximum_extensions++; +#endif + +#ifdef STACK_CHECKER_ON + /* + * Add 1 extension for stack checker + */ + + BSP_Configuration.maximum_extensions++; +#endif + + /* + * Add 1 extension for MPCI_fatal + */ + + if (BSP_Configuration.User_multiprocessing_table) + BSP_Configuration.maximum_extensions++; + + /* + * Initialize RTEMS. main() will finish it up and start multitasking. + */ + + rtems_libio_config( &BSP_Configuration, BSP_LIBIO_MAX_FDS ); + + bsp_isr_level = rtems_initialize_executive_early( + &BSP_Configuration, + &Cpu_table + ); +} + + + + diff --git a/c/src/lib/libbsp/powerpc/dmv177/startup/genpvec.c b/c/src/lib/libbsp/powerpc/dmv177/startup/genpvec.c new file mode 100644 index 0000000000..98989c2401 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/startup/genpvec.c @@ -0,0 +1,184 @@ +/* genpvec.c + * + * These routines handle the external exception. Multiple ISRs occur off + * of this one interrupt. This method will allow multiple ISRs to be + * called using the same IRQ index. However, removing the ISR routines is + * presently not supported. + * + * The external exception vector numbers begin with DMV170_IRQ_FIRST. + * DMV170_IRQ_FIRST is defined to be one greater than the last processor + * interrupt. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id: + */ + +#include <bsp.h> +#include "chain.h" +#include <assert.h> + +#define NUM_LIRQ_HANDLERS 20 +#define NUM_LIRQ ( MAX_BOARD_IRQS - PPC_IRQ_LAST ) + +/* + * Structure to for one of possible multiple interrupt handlers for + * a given interrupt. + */ +typedef struct +{ + Chain_Node Node; + rtems_isr_entry handler; /* isr routine */ + rtems_vector_number vector; /* vector number */ +} EE_ISR_Type; + +/* + * Note: The following will not work if we add a method to remove + * handlers at a later time. + */ +EE_ISR_Type ISR_Nodes [NUM_LIRQ_HANDLERS]; +rtems_unsigned16 Nodes_Used; +Chain_Control ISR_Array [NUM_LIRQ]; + + +/* PAGE + * + * initialize_external_exception_vector + * + * This routine initializes the external exception vector + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + */ + +void initialize_external_exception_vector () +{ + int i; + rtems_isr_entry previous_isr; + rtems_status_code status; + + Nodes_Used = 0; + + for (i=0; i <NUM_LIRQ; i++) + Chain_Initialize_empty( &ISR_Array[i] ); + + /* + * Install external_exception_ISR () as the handler for + * the General Purpose Interrupt. + */ + + status = rtems_interrupt_catch( external_exception_ISR, + PPC_IRQ_EXTERNAL , (rtems_isr_entry *) &previous_isr ); +} + +/* PAGE + * + * set_EE_vector + * + * This routine installs one of multiple ISRs for the general purpose + * inerrupt. + * + * Input parameters: + * handler - handler to call at exception + * vector - vector number associated with this handler. + * + * Output parameters: NONE + * + * Return values: + */ +rtems_isr_entry set_EE_vector( + rtems_isr_entry handler, /* isr routine */ + rtems_vector_number vector /* vector number */ +) +{ + rtems_unsigned16 vec_idx = vector - DMV170_IRQ_FIRST; + rtems_unsigned32 index; + + /* + * Verify that all of the nodes have not been used. + */ + assert (Nodes_Used < NUM_LIRQ_HANDLERS); + + /* + * If we have already installed this handler for this vector, then + * just reset it. + */ + + for ( index=0 ; index <= Nodes_Used ; index++ ) { + if ( ISR_Nodes[index].vector == vector && + ISR_Nodes[index].handler == handler ) + return 0; + } + + /* + * Increment the number of nedes used and set the index for the node + * array. + */ + + Nodes_Used++; + index = Nodes_Used - 1; + + /* + * Write the values of the handler and the vector to this node. + */ + ISR_Nodes[index].handler = handler; + ISR_Nodes[index].vector = vector; + + /* + * Connect this node to the chain at the location of the + * vector index. + */ + Chain_Append( &ISR_Array[vec_idx], &ISR_Nodes[index].Node ); + + /* + * No interrupt service routine was removed so return 0 + */ + return 0; +} + +/* PAGE + * + * external_exception_ISR + * + * This interrupt service routine is called for an External Exception. + * + * Input parameters: + * vector - vector number representing the external exception vector. + * + * Output parameters: NONE + * + * Return values: + */ + +rtems_isr external_exception_ISR ( + rtems_vector_number vector /* IN */ +) +{ + rtems_unsigned16 index; + EE_ISR_Type *node; + + /* + * Read vector. + */ + index = 0; + + node = ISR_Array[ index ].first; + while ( !_Chain_Is_tail( &ISR_Array[ index ], node ) ) { + (*node->handler)( node->vector ); + node = node->Node.next; + } + + /* + * Clear the interrupt. + */ +} + diff --git a/c/src/lib/libbsp/powerpc/dmv177/startup/linkcmds b/c/src/lib/libbsp/powerpc/dmv177/startup/linkcmds new file mode 100644 index 0000000000..80b586dbad --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/startup/linkcmds @@ -0,0 +1,173 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc) +ENTRY(_start) + +/* + * Number of Decrementer countdowns per millisecond + * + * Calculated by: (66.67 Mhz * 1000) / 4 cycles per click + */ + +PROVIDE(CPU_PPC_CLICKS_PER_MS = 16667); + +MEMORY + { + RAM : ORIGIN = 0, LENGTH = 32M + EPROM : ORIGIN = 0xFFF00000, LENGTH = 0x20000 + } + +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + /* . = 0x40000 + SIZEOF_HEADERS; */ + /* . = 0x1000000;*/ + . = 0x41000; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rela.text : { *(.rela.text) } + .rela.data : { *(.rela.data) } + .rela.rodata : { *(.rela.rodata) } + .rela.got : { *(.rela.got) } + .rela.got1 : { *(.rela.got1) } + .rela.got2 : { *(.rela.got2) } + .rela.ctors : { *(.rela.ctors) } + .rela.dtors : { *(.rela.dtors) } + .rela.init : { *(.rela.init) } + .rela.fini : { *(.rela.fini) } + .rela.bss : { *(.rela.bss) } + .rela.plt : { *(.rela.plt) } + .rela.sdata : { *(.rela.sdata2) } + .rela.sbss : { *(.rela.sbss2) } + .rela.sdata2 : { *(.rela.sdata2) } + .rela.sbss2 : { *(.rela.sbss2) } + .plt : { *(.plt) } + .text : + { + *(.text) + *(.descriptors) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } =0 + .init : { *(.init) } =0 + .fini : { *(.fini) } =0 + .rodata : { *(.rodata) } + .rodata1 : { *(.rodata1) } + _etext = .; + PROVIDE (etext = .); + PROVIDE (__SDATA2_START__ = .); + .sdata2 : { *(.sdata2) } + .sbss2 : { *(.sbss2) } + PROVIDE (__SBSS2_END__ = .); + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. It would + be more correct to do this: + . = ALIGN(0x40000) + (ALIGN(8) & (0x40000 - 1)); + The current expression does not correctly handle the case of a + text segment ending precisely at the end of a page; it causes the + data segment to skip a page. The above expression does not have + this problem, but it will currently (2/95) cause BFD to allocate + a single segment, combining both text and data, for this case. + This will prevent the text segment from being shared among + multiple executions of the program; I think that is more + important than losing a page of the virtual address space (note + that no actual memory is lost; the page which is skipped can not + be referenced). */ + . = ALIGN(8) + 0x40000; + PROVIDE (sdata = .); + .data : + { + *(.data) + CONSTRUCTORS + } + PROVIDE (__EXCEPT_START__ = .); + .gcc_except_table : { *(.gcc_except_table) } + PROVIDE (__EXCEPT_END__ = .); + + .data1 : { *(.data1) } + .got1 : { *(.got1) } + .dynamic : { *(.dynamic) } + /* Put .ctors and .dtors next to the .got2 section, so that the pointers + get relocated with -mrelocatable. Also put in the .fixup pointers. + The current compiler no longer needs this, but keep it around for 2.7.2 */ + PROVIDE (_GOT2_START_ = .); + .got2 : { *(.got2) } + PROVIDE (__GOT2_END__ = .); + PROVIDE (__CTOR_LIST__ = .); + .ctors : { *(.ctors) } + PROVIDE (__CTOR_END__ = .); + PROVIDE (__DTOR_LIST__ = .); + .dtors : { *(.dtors) } + PROVIDE (__DTOR_END__ = .); + PROVIDE (_FIXUP_START_ = .); + .fixup : { *(.fixup) } + PROVIDE (_FIXUP_END_ = .); + PROVIDE (__FIXUP_END__ = .); + PROVIDE (_GOT2_END_ = .); + PROVIDE (_GOT_START_ = .); + s.got = .; + .got : { *(.got) } + .got.plt : { *(.got.plt) } + PROVIDE (_GOT_END_ = .); + PROVIDE (__GOT_END__ = .); + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + PROVIDE (__SDATA_START__ = .); + .sdata : { *(.sdata) } + _edata = .; + PROVIDE (edata = .); + PROVIDE (RAM_END = 4M); + .sbss : + { + PROVIDE (__sbss_start = .); + *(.sbss) + *(.scommon) + PROVIDE (__sbss_end = .); + } + PROVIDE (__SBSS_END__ = .); + .bss : + { + PROVIDE (__bss_start = .); + *(.dynbss) + *(.bss) + *(COMMON) + } + . = ALIGN(8) + 0x8000; + PROVIDE (__stack = .); + _end = . ; + PROVIDE (end = .); + + /* These are needed for ELF backends which have not yet been + converted to the new style linker. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* These must appear regardless of . */ +} diff --git a/c/src/lib/libbsp/powerpc/dmv177/startup/rtems-ctor.cc b/c/src/lib/libbsp/powerpc/dmv177/startup/rtems-ctor.cc new file mode 100644 index 0000000000..0c7efef592 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/startup/rtems-ctor.cc @@ -0,0 +1,151 @@ +/* + * rtems-ctor.cc + * + * Description: + * This file exists solely to (try to) ensure RTEMS is initialized + * before any global constructors are run. + * + * The problem: + * Global constructors might reasonably expect that new() will + * work, but since new() uses malloc() which uses RTEMS regions, + * it can not be called until after initialize_executive(). + * + * Global constructors are called in GNU systems one of 2 ways: + * + * an "invisible" call to __main() inserted by compiler + * This __main() calls __do_global_ctors() which + * walks thru the table and calls all global + * constructors. + * + * or - + * A special section is put into the linked binary. The + * system startup code knows to run the constructors in + * this special section before calling main(). + * + * By making RTEMS initialization a constructor, we avoid having + * too much about all this. All we have to guarantee is that + * this constructor is the first one run. + * + * + * So for the first case above, this is what happens + * + * host crt0 + * main() + * __main() + * __do_global_ctors() + * bsp_start() + * init_executive_early() + * <<any other constructors>> + * + * rtems_init_executive_late() + * bsp_cleanup() + * + * TODO: + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <bsp.h> + +/* + * RTEMS program name + * Probably not used by anyone, but it is nice to have it. + * Actually the UNIX version of CPU_INVOKE_DEBUGGER will probably + * need to use it + */ + +char *rtems_progname; +char **rtems_environp; + +#ifdef USE_CONSTRUCTORS_FOR_INIT_EXEC + +class RTEMS { + public: + RTEMS(); + ~RTEMS(); +}; + +RTEMS rtems_constructor; + + +/* PAGE + * + * RTEMS::RTEMS + * + * RTEMS constructor routine + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + */ + +RTEMS::RTEMS() +{ + bsp_start(); +} + +/* PAGE + * + * RTEMS::~RTEMS + * + * RTEMS distructor routine + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + */ + +RTEMS::~RTEMS() +{ + bsp_cleanup(); +} +#endif + +extern "C" { + int + main(int argc, + char **argv, + char **environp) + { + +#ifndef USE_CONSTRUCTORS_FOR_INIT_EXEC + bsp_start(); +#endif + + if ((argc > 0) && argv && argv[0]) + rtems_progname = argv[0]; + else + rtems_progname = "RTEMS"; + + rtems_environp = environp; + + /* + * Start multitasking + */ + + rtems_initialize_executive_late( bsp_isr_level ); + +#ifndef USE_CONSTRUCTORS_FOR_INIT_EXEC + bsp_cleanup(); +#endif + + /* + * Returns when multitasking is stopped + * This allows our destructors to get run normally + */ + + return 0; + } +} diff --git a/c/src/lib/libbsp/powerpc/dmv177/startup/sbrk.c b/c/src/lib/libbsp/powerpc/dmv177/startup/sbrk.c new file mode 100644 index 0000000000..c52224cc35 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/startup/sbrk.c @@ -0,0 +1,61 @@ +/* + * sbrk.c + * + * If the BSP wants to dynamically allocate the memory for the + * C Library heap (malloc) and/or be able to extend the heap, + * then this routine must be functional. + * + * 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/sbrk.c: + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> + +#include <signal.h> +#include <errno.h> +#include <sys/types.h> +#include <unistd.h> + +/* PAGE + * + * sbrk + * + * Routine to allow dynamically allocated memory for the heap. + * Note the int may need to be a size_t on some hosts + * + * Input parameters: + * incr + * Output parameters: NONE + * + * Return values: + */ +void * sbrk(size_t incr) +{ + errno = EINVAL; + return (void *)-1; +} + diff --git a/c/src/lib/libbsp/powerpc/dmv177/startup/setvec.c b/c/src/lib/libbsp/powerpc/dmv177/startup/setvec.c new file mode 100644 index 0000000000..4fb6333da8 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/startup/setvec.c @@ -0,0 +1,71 @@ +/* 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 + * + * Derived from c/src/lib/libbsp/no_cpu/no_bsp/startup/setvec.c: + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id: + */ + +#include <rtems.h> +#include <bsp.h> + + +/* PAGE + * + * set_vector + * + * This routine installs vector number vector. + * + * Input parameters: + * handler - routine to call when the interupt occurs + * vector - vector id + * type - RAW or RTEMS vector + * + * Output parameters: NONE + * + * Return values: Removed interupt routine or 0 if none. + */ + +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_status_code status; + + + /* + * vectors greater than PPC603e_IRQ_LAST are handled by the General purpose + * interupt handler. + */ + if ( vector > PPC_IRQ_LAST ) { + set_EE_vector ( handler, vector ); + } + else { + status = rtems_interrupt_catch + ( handler, vector, (rtems_isr_entry *) &previous_isr ); + } + return previous_isr; +} + diff --git a/c/src/lib/libbsp/powerpc/dmv177/startup/vmeintr.c b/c/src/lib/libbsp/powerpc/dmv177/startup/vmeintr.c new file mode 100644 index 0000000000..212d7eb938 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/startup/vmeintr.c @@ -0,0 +1,84 @@ +/* vmeintr.c + * + * VMEbus support routines for the DMV170. + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#include <bsp.h> +#include <vmeintr.h> + +/* PAGE + * + * VME_interrupt_Disable + * + * This routine disables vme interupts + * + * Input parameters: + * mask - interupt mask + * + * Output parameters: NONE + * + * Return values: NONE + */ + +void VME_interrupt_Disable ( + VME_interrupt_Mask mask /* IN */ +) +{ + volatile rtems_unsigned8 *VME_interrupt_enable; + rtems_unsigned8 value; + +#if 0 + VME_interrupt_enable = ACC_VIE; +#else + VME_interrupt_enable = 0; +#endif + value = *VME_interrupt_enable; + + value &= ~mask; /* turn off interrupts for all levels in mask */ + + *VME_interrupt_enable = value; +} + +/* PAGE + * + * VME_interrupt_Enable + * + * This routine enables vme interupts + * + * Input parameters: + * mask - interupt mask + * + * Output parameters: NONE + * + * Return values: + */ + +void VME_interrupt_Enable ( + VME_interrupt_Mask mask /* IN */ +) +{ + volatile rtems_unsigned8 *VME_interrupt_enable; + rtems_unsigned8 value; + +#if 0 + VME_interrupt_enable = ACC_VIE; +#else + VME_interrupt_enable = 0; +#endif + value = *VME_interrupt_enable; + + value |= mask; /* turn on interrupts for all levels in mask */ + + *VME_interrupt_enable = value; +} diff --git a/c/src/lib/libbsp/powerpc/dmv177/timer/Makefile.in b/c/src/lib/libbsp/powerpc/dmv177/timer/Makefile.in new file mode 100644 index 0000000000..35a903e737 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/timer/Makefile.in @@ -0,0 +1,61 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +RTEMS_ROOT = @RTEMS_ROOT@ +PROJECT_ROOT = @PROJECT_ROOT@ +RTEMS_CUSTOM = $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg + +PGM=${ARCH}/timer.rel + +# C source names, if any, go here -- minus the .c +C_PIECES=timer +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +H_FILES= + +# Assembly source names, if any, go here -- minus the .s +S_PIECES= +S_FILES=$(S_PIECES:%=%.s) +S_O_FILES=$(S_FILES:%.s=${ARCH}/%.o) + +SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES) +OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES) + +include $(RTEMS_CUSTOM) +include $(PROJECT_ROOT)/make/leaf.cfg + +# +# (OPTIONAL) Add local stuff here using += +# + +DEFINES += +CPPFLAGS += +CFLAGS += + +LD_PATHS += +LD_LIBS += +LDFLAGS += + +# +# Add your list of files to delete here. The config files +# already know how to delete some stuff, so you may want +# to just run 'make clean' first to see what gets missed. +# 'make clobber' already includes 'make clean' +# + +CLEAN_ADDITIONS += +CLOBBER_ADDITIONS += + +${PGM}: ${SRCS} ${OBJS} + $(make-rel) + +all: ${ARCH} $(SRCS) $(PGM) + +# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile +install: all diff --git a/c/src/lib/libbsp/powerpc/dmv177/timer/timer.c b/c/src/lib/libbsp/powerpc/dmv177/timer/timer.c new file mode 100644 index 0000000000..72d1bb79a3 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/timer/timer.c @@ -0,0 +1,152 @@ +/* timer.c + * + * This file implements a benchmark timer using the General Purpose Timer on + * the MEC. + * + * The license and distribution terms for this file are in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <assert.h> + +#include <bsp.h> + +rtems_unsigned64 Timer_driver_Start_time; + +rtems_boolean Timer_driver_Find_average_overhead; + +static inline rtems_unsigned64 PPC_Get_timebase_register( void ) +{ + rtems_unsigned32 tbr_low; + rtems_unsigned32 tbr_high; + rtems_unsigned32 tbr_high_old; + rtems_unsigned64 tbr; + + do { + asm volatile( "mftbu %0" : "=r" (tbr_high_old)); + asm volatile( "mftb %0" : "=r" (tbr_low)); + asm volatile( "mftbu %0" : "=r" (tbr_high)); + } while ( tbr_high_old != tbr_high ); + + tbr = tbr_high; + tbr <<= 32; + tbr |= tbr_low; + return tbr; +} + +/* PAGE + * + * Timer_initialize + * + * This routine initializes the timer. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + * + */ + +void Timer_initialize() +{ + /* + * Timer runs long and accurate enough not to require an interrupt. + */ + + + Timer_driver_Start_time = PPC_Get_timebase_register(); + + +} + +#define AVG_OVERHEAD 24 /* It typically takes 24 instructions */ + /* to start/stop the timer. */ +#define LEAST_VALID 1 /* Don't trust a value lower than this */ + /* psim can count instructions. :) */ + +/* PAGE + * + * Read_timer + * + * This routine reads the timer. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: timer in ms units + * + */ + +int Read_timer() +{ + rtems_unsigned64 clicks; + rtems_unsigned64 total64; + rtems_unsigned32 total; + + /* approximately CLOCK_SPEED clicks per microsecond */ + + clicks = PPC_Get_timebase_register(); + + assert( clicks > Timer_driver_Start_time ); + + total64 = clicks - Timer_driver_Start_time; + + assert( total64 <= 0xffffffff ); /* fits into a unsigned32 */ + + total = (rtems_unsigned32) total64; + + if ( Timer_driver_Find_average_overhead == 1 ) + return total; /* in one microsecond units */ + + if ( total < LEAST_VALID ) + return 0; /* below timer resolution */ + + return total - AVG_OVERHEAD; +} + +/* PAGE + * + * Empty_function + * + * This routine is called during the idle loop. + * + * Input parameters: NONE + * + * Output parameters: + * status code of successful + * + * Return values: NONE + * + */ + +rtems_status_code Empty_function( void ) +{ + return RTEMS_SUCCESSFUL; +} + +/* PAGE + * + * Set_find_average_overhead + * + * This routine sets a global boolean to the value passed in. + * + * Input parameters: + * find_flag - flag to indicate to find the average overhead. + * + * Output parameters: NONE + * + * Return values: NONE + * + */ + +void Set_find_average_overhead( + rtems_boolean find_flag +) +{ + Timer_driver_Find_average_overhead = find_flag; +} diff --git a/c/src/lib/libbsp/powerpc/dmv177/tod/Makefile.in b/c/src/lib/libbsp/powerpc/dmv177/tod/Makefile.in new file mode 100644 index 0000000000..dfad6613f4 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/tod/Makefile.in @@ -0,0 +1,59 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +RTEMS_ROOT = @RTEMS_ROOT@ +PROJECT_ROOT = @PROJECT_ROOT@ +RTEMS_CUSTOM = $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg + +PGM=${ARCH}/tod.rel + +# C source names, if any, go here -- minus the .c +C_PIECES=$(TOD_PIECES) +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +H_FILES= + +SRCS=$(C_FILES) $(H_FILES) +OBJS=$(C_O_FILES) + +include $(RTEMS_CUSTOM) +include $(PROJECT_ROOT)/make/leaf.cfg + +# First and second generation use different RTC chips :( +TOD_PIECES=tod + +# +# (OPTIONAL) Add local stuff here using += +# + +DEFINES += +CPPFLAGS += +CFLAGS += + +LD_PATHS += +LD_LIBS += +LDFLAGS += + +# +# Add your list of files to delete here. The config files +# already know how to delete some stuff, so you may want +# to just run 'make clean' first to see what gets missed. +# 'make clobber' already includes 'make clean' +# + +CLEAN_ADDITIONS += +CLOBBER_ADDITIONS += + +${PGM}: ${SRCS} ${OBJS} + $(make-rel) + +all: ${ARCH} $(SRCS) $(PGM) + +# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile +install: all diff --git a/c/src/lib/libbsp/powerpc/dmv177/tod/tod.c b/c/src/lib/libbsp/powerpc/dmv177/tod/tod.c new file mode 100644 index 0000000000..800f342cf1 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/tod/tod.c @@ -0,0 +1,282 @@ +/* + * Real Time Clock (Harris ICM7170) for RTEMS + * + * This part is found on the second generation of this board. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#include <tod.h> +#include <bsp.h> + +/* + * These values are programed into a register and must not be changed. + */ + +#define ICM1770_CRYSTAL_FREQ_32K 0x00 +#define ICM1770_CRYSTAL_FREQ_1M 0x01 +#define ICM1770_CRYSTAL_FREQ_2M 0x02 +#define ICM1770_CRYSTAL_FREQ_4M 0x03 + +void ICM7170_GetTOD( + volatile unsigned char *imc1770_regs, + rtems_unsigned8 icm1770_freq, + rtems_time_of_day *rtc_tod +); +void ICM7170_SetTOD( + volatile unsigned char *imc1770_regs, + rtems_unsigned8 icm1770_freq, + rtems_time_of_day *rtc_tod +); + +/* + * This code is dependent on the boards use of the ICM7170 RTC/NVRAM + * and should remain in this file. + */ + +/* PAGE + * + * This routine copies the time from the real time clock to RTEMS + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + */ + +void setRealTimeToRTEMS() +{ + rtems_time_of_day rtc_tod; + + ICM7170_GetTOD( DMV170_RTC_ADDRESS, DMV170_RTC_FREQUENCY, &rtc_tod ); + rtems_clock_set( &rtc_tod ); +} + +/* PAGE + * + * setRealTimeFromRTEMS + * + * This routine copies the time from RTEMS to the real time clock + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + */ + +void setRealTimeFromRTEMS() +{ + rtems_time_of_day rtems_tod; + + rtems_clock_get( RTEMS_CLOCK_GET_TOD, &rtems_tod ); + ICM7170_SetTOD( DMV170_RTC_ADDRESS, DMV170_RTC_FREQUENCY, &rtems_tod ); +} + +/* PAGE + * + * checkRealTime + * + * This routine reads the returns the variance betweent the real time and + * rtems time. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: + * int The differance between the real time clock and rtems time or + * 9999 in the event of an error. + */ + +int checkRealTime() +{ + rtems_time_of_day rtems_tod; + rtems_time_of_day rtc_tod; + + ICM7170_GetTOD( DMV170_RTC_ADDRESS, DMV170_RTC_FREQUENCY, &rtc_tod ); + rtems_clock_get( RTEMS_CLOCK_GET_TOD, &rtems_tod ); + + if( rtems_tod.year == rtc_tod.year && + rtems_tod.month == rtc_tod.month && + rtems_tod.day == rtc_tod.day ) { + return ((rtems_tod.hour - rtc_tod.hour) * 3600) + + ((rtems_tod.minute - rtc_tod.minute) * 60) + + (rtems_tod.second - rtc_tod.second); + } + return 9999; +} + +/* + * These routines are ICM7170 should be in + * a separate support library. When the chiplib + * is created for RTEMS these routines will be moved. + */ + +/* PAGE + * + * ICM7170_GetField + * + * This routine gets a field + * + * Input parameters: + * imc1770_regs - pointer to the register base address. + * reg - register id + * + * Output parameters: NONE + * + * Return values: value of register + */ + +static int ICM7170_GetField( + volatile unsigned char *imc1770_regs, + int reg +) +{ + unsigned char x; + + x = imc1770_regs[reg*4]; + + return x; +} + +/* PAGE + * + * ICM7170_SetField + * + * This routine sets a field + * + * Input parameters: + * imc1770_regs - pointer to the register base address. + * reg - register id + * d - data to write + * + * Output parameters: NONE + * + * Return values: NONE + */ + +static void ICM7170_SetField( + volatile unsigned char *imc1770_regs, + int reg, + unsigned char d +) +{ + imc1770_regs[reg*4] = d; +} + +/* PAGE + * + * ICM7170_GetTOD + * + * This routine gets the real time clock time of day in rtems + * time of day format. + * + * Input parameters: + * imc1770_regs - pointer to the register base address. + * icm1770_freq - oscillator frequency + * + * Output parameters: + * rtc_tod - time of day by the real time clock + * + * Return values: NONE + */ + +void ICM7170_GetTOD( + volatile unsigned char *imc1770_regs, + rtems_unsigned8 icm1770_freq, + rtems_time_of_day *rtc_tod +) +{ + int year; + int usec; + static rtems_boolean init = TRUE; + + /* Initialize the clock at once prior to reading */ + if (init ) { + ICM7170_SetField( imc1770_regs, 0x11, (0x0c | icm1770_freq) ); + init = FALSE; + } + + usec = ICM7170_GetField( imc1770_regs, 0x00 ); + + year = ICM7170_GetField( imc1770_regs, 0x06 ); + if ( year >= 88 ) + year += 1900; + else + year += 2000; + + rtc_tod->year = year; + rtc_tod->month = ICM7170_GetField( imc1770_regs, 0x04 ); + rtc_tod->day = ICM7170_GetField( imc1770_regs, 0x05 ); + rtc_tod->hour = ICM7170_GetField( imc1770_regs, 0x01 ); + rtc_tod->minute = ICM7170_GetField( imc1770_regs, 0x02 ); + rtc_tod->second = ICM7170_GetField( imc1770_regs, 0x03 ); + rtc_tod->ticks = ICM7170_GetField( imc1770_regs, 0x00 ); +} + +/* PAGE + * + * ICM7170_SetTOD + * + * This routine sets the real time clock + * + * Input parameters: + * imc1770_regs - pointer to the register base address. + * icm1770_freq - oscillator frequency + * rtc_tod - time of day to set + * + * Output parameters: + * + * Return values: + */ + +void ICM7170_SetTOD( + volatile unsigned char *imc1770_regs, + rtems_unsigned8 icm1770_freq, + rtems_time_of_day *rtc_tod +) +{ + int ticks; + int year; + + year = rtc_tod->year; + if ( year >= 2088 ) /* plan ahead :) */ + rtems_fatal_error_occurred( 0xBAD0BAD0 ); + + if ( year >= 2000 ) + year -= 2000; + else + year -= 1900; + + ICM7170_SetField( imc1770_regs, 0x11, (0x04 |icm1770_freq ) ); + + ICM7170_SetField( imc1770_regs, 0x06, year ); + ICM7170_SetField( imc1770_regs, 0x04, rtc_tod->month ); + ICM7170_SetField( imc1770_regs, 0x05, rtc_tod->day ); + ICM7170_SetField( imc1770_regs, 0x01, rtc_tod->hour ); + ICM7170_SetField( imc1770_regs, 0x02, rtc_tod->minute ); + ICM7170_SetField( imc1770_regs, 0x03, rtc_tod->second ); + + /* + * I don't know which day of week is + * + */ + ICM7170_SetField( imc1770_regs, 0x07, 1 ); + + ICM7170_SetField( imc1770_regs, 0x11, (0x0c | icm1770_freq) ); +} + + + + + + + + diff --git a/c/src/lib/libbsp/powerpc/dmv177/wrapup/Makefile.in b/c/src/lib/libbsp/powerpc/dmv177/wrapup/Makefile.in new file mode 100644 index 0000000000..285b8e0356 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/dmv177/wrapup/Makefile.in @@ -0,0 +1,57 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +RTEMS_ROOT = @RTEMS_ROOT@ +PROJECT_ROOT = @PROJECT_ROOT@ +RTEMS_CUSTOM = $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg + +#BSP_PIECES=startup clock console timer tod vectors +BSP_PIECES=startup clock console sonic timer tod #vectors +# pieces to pick up out of libcpu/$(RTEMS_CPU) +CPU_PIECES= +GENERIC_PIECES= + +# bummer; have to use $foreach since % pattern subst rules only replace 1x +OBJS=$(foreach piece, $(BSP_PIECES), ../$(piece)/$(ARCH)/$(piece).rel) \ + $(foreach piece, $(CPU_PIECES), \ + ../../../../libcpu/$(RTEMS_CPU)/$(piece)/$(ARCH)/$(piece).rel) \ + $(foreach piece, $(GENERIC_PIECES), \ + ../../../$(piece)/$(ARCH)/$(piece).rel) +LIB=$(ARCH)/libbsp.a + +include $(RTEMS_CUSTOM) +include $(PROJECT_ROOT)/make/lib.cfg + +# +# (OPTIONAL) Add local stuff here using += +# + +DEFINES += +CPPFLAGS += +CFLAGS += + +LD_PATHS += +LD_LIBS += +LDFLAGS += + +# +# Add your list of files to delete here. The config files +# already know how to delete some stuff, so you may want +# to just run 'make clean' first to see what gets missed. +# 'make clobber' already includes 'make clean' +# + +CLEAN_ADDITIONS += +CLOBBER_ADDITIONS += + +$(LIB): ${OBJS} + $(make-library) + +all: ${ARCH} $(SRCS) $(LIB) + $(INSTALL_VARIANT) -m 644 $(LIB) ${PROJECT_RELEASE}/lib + |