summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2008-12-04 22:55:13 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2008-12-04 22:55:13 +0000
commitb17830622a32cbbeaac014e8e6bb56d99184876a (patch)
tree4a622766310aceed0bdbabc8b79d5f5cebaf1241
parent2008-12-04 Jukka Pietarinen <jukka.pietarinen@mrf.fi> (diff)
downloadrtems-b17830622a32cbbeaac014e8e6bb56d99184876a.tar.bz2
2008-12-04 Jukka Pietarinen <jukka.pietarinen@mrf.fi>
* ChangeLog, Makefile.am, README, acinclude.m4, configure.ac, shared/clock/ckinit.c, shared/clock/clock.h, shared/console/console.c, shared/console/uart.c, shared/console/uart.h, shared/start/start.S, shared/startup/bspstart.c, shared/startup/setvec.c, shared/timer/timer.c, shared/tsmac/dp83848phy.h, shared/tsmac/tsmac.c, shared/tsmac/tsmac.h: New files.
-rw-r--r--c/src/lib/libbsp/lm32/ChangeLog10
-rw-r--r--c/src/lib/libbsp/lm32/Makefile.am11
-rw-r--r--c/src/lib/libbsp/lm32/README39
-rw-r--r--c/src/lib/libbsp/lm32/acinclude.m410
-rw-r--r--c/src/lib/libbsp/lm32/configure.ac21
-rw-r--r--c/src/lib/libbsp/lm32/shared/clock/ckinit.c179
-rw-r--r--c/src/lib/libbsp/lm32/shared/clock/clock.h42
-rw-r--r--c/src/lib/libbsp/lm32/shared/console/console.c226
-rw-r--r--c/src/lib/libbsp/lm32/shared/console/uart.c72
-rw-r--r--c/src/lib/libbsp/lm32/shared/console/uart.h89
-rw-r--r--c/src/lib/libbsp/lm32/shared/start/start.S156
-rw-r--r--c/src/lib/libbsp/lm32/shared/startup/bspstart.c49
-rw-r--r--c/src/lib/libbsp/lm32/shared/startup/setvec.c43
-rw-r--r--c/src/lib/libbsp/lm32/shared/timer/timer.c107
-rw-r--r--c/src/lib/libbsp/lm32/shared/tsmac/dp83848phy.h182
-rw-r--r--c/src/lib/libbsp/lm32/shared/tsmac/tsmac.c824
-rw-r--r--c/src/lib/libbsp/lm32/shared/tsmac/tsmac.h160
17 files changed, 2220 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/lm32/ChangeLog b/c/src/lib/libbsp/lm32/ChangeLog
new file mode 100644
index 0000000000..fb88947f99
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/ChangeLog
@@ -0,0 +1,10 @@
+2008-12-04 Jukka Pietarinen <jukka.pietarinen@mrf.fi>
+
+ * ChangeLog, Makefile.am, README, acinclude.m4, configure.ac,
+ shared/clock/ckinit.c, shared/clock/clock.h,
+ shared/console/console.c, shared/console/uart.c,
+ shared/console/uart.h, shared/start/start.S,
+ shared/startup/bspstart.c, shared/startup/setvec.c,
+ shared/timer/timer.c, shared/tsmac/dp83848phy.h,
+ shared/tsmac/tsmac.c, shared/tsmac/tsmac.h: New files.
+
diff --git a/c/src/lib/libbsp/lm32/Makefile.am b/c/src/lib/libbsp/lm32/Makefile.am
new file mode 100644
index 0000000000..e60a8966ac
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/Makefile.am
@@ -0,0 +1,11 @@
+##
+## $Id$
+##
+
+ACLOCAL_AMFLAGS = -I ../../../aclocal
+
+# Descend into the @RTEMS_BSP_FAMILY@ directory
+SUBDIRS = @RTEMS_BSP_FAMILY@
+
+include $(top_srcdir)/../../../automake/subdirs.am
+include $(top_srcdir)/../../../automake/local.am
diff --git a/c/src/lib/libbsp/lm32/README b/c/src/lib/libbsp/lm32/README
new file mode 100644
index 0000000000..ca434207c8
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/README
@@ -0,0 +1,39 @@
+#
+# $Id$
+#
+# The Lattice Mico32 port uses the system_config.h generated by the Mico
+# System Builder to retrieve the properties of the peripherals.
+#
+# Implemented (in shared/ subdirectory)
+# Polled console driver (uart)
+# Clock interrupt with 10 ms tick
+# Networking using Lattice tri-speed ethernet MAC
+#
+# Todo
+# Support more peripherals:
+# - uart driver using interrupts
+#
+# jukka.pietarinen@mrf.fi, 3.12.2008
+#
+
+BSP NAME: lm32_evr
+BOARD: cRIO-EVR, Micro-Research Finland Oy
+BUS: wishbone
+CPU FAMILY: lm32 (Lattice Mico32)
+CPU: small
+COPROCESSORS: none
+MODE: 32 bit mode
+
+DEBUG MONITOR: none
+
+PERIPHERALS
+===========
+TIMERS: clock
+ RESOLUTION: 10 ms
+SERIAL PORTS: uart
+REAL-TIME CLOCK: none
+DMA: none
+VIDEO: none
+SCSI: none
+NETWORKING: tsmac
+
diff --git a/c/src/lib/libbsp/lm32/acinclude.m4 b/c/src/lib/libbsp/lm32/acinclude.m4
new file mode 100644
index 0000000000..49a88aaa31
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/acinclude.m4
@@ -0,0 +1,10 @@
+# RTEMS_CHECK_BSPDIR(RTEMS_BSP_FAMILY)
+AC_DEFUN([RTEMS_CHECK_BSPDIR],
+[
+ case "$1" in
+ lm32_evr )
+ AC_CONFIG_SUBDIRS([lm32_evr]);;
+ *)
+ AC_MSG_ERROR([Invalid BSP]);;
+ esac
+])
diff --git a/c/src/lib/libbsp/lm32/configure.ac b/c/src/lib/libbsp/lm32/configure.ac
new file mode 100644
index 0000000000..d297503385
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/configure.ac
@@ -0,0 +1,21 @@
+## Process this file with autoconf to produce a configure script.
+##
+## $Id$
+
+AC_PREREQ(2.60)
+AC_INIT([rtems-c-src-lib-libbsp-lm32],[_RTEMS_VERSION],[http://www.rtems.org/bugzilla])
+AC_CONFIG_SRCDIR([lm32_evr])
+RTEMS_TOP(../../../../..)
+
+RTEMS_CANONICAL_TARGET_CPU
+AM_INIT_AUTOMAKE([no-define foreign 1.10])
+AM_MAINTAINER_MODE
+
+RTEMS_ENV_RTEMSBSP
+RTEMS_PROJECT_ROOT
+
+RTEMS_CHECK_BSPDIR([$RTEMS_BSP_FAMILY])
+
+# Explicitly list all Makefiles here
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/c/src/lib/libbsp/lm32/shared/clock/ckinit.c b/c/src/lib/libbsp/lm32/shared/clock/ckinit.c
new file mode 100644
index 0000000000..433d3d5d72
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/clock/ckinit.c
@@ -0,0 +1,179 @@
+/* ckinit.c
+ *
+ * Clock device driver for Lattice Mico32 (lm32).
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ * Jukka Pietarinen <jukka.pietarinen@mrf.fi>, 2008,
+ * Micro-Research Finland Oy
+ */
+
+#include <stdlib.h>
+
+#include <rtems.h>
+#include <bsp.h>
+#include "../include/system_conf.h"
+#include "clock.h"
+
+static inline int clockread(unsigned int reg)
+{
+ return *((int*)(TIMER0_BASE_ADDRESS + reg));
+}
+
+static inline void clockwrite(unsigned int reg, int value)
+{
+ *((int*)(TIMER0_BASE_ADDRESS + reg)) = value;
+}
+
+void Clock_exit( void );
+rtems_isr Clock_isr( rtems_vector_number vector );
+extern lm32_isr_entry set_vector(rtems_isr_entry handler,
+ rtems_vector_number vector, int type);
+
+/*
+ * The interrupt vector number associated with the clock tick device
+ * driver.
+ */
+
+#define CLOCK_VECTOR ( TIMER0_IRQ )
+#define CLOCK_IRQMASK ( 1 << CLOCK_VECTOR )
+
+/*
+ * Clock_driver_ticks is a monotonically increasing counter of the
+ * number of clock ticks since the driver was initialized.
+ */
+
+volatile uint32_t Clock_driver_ticks;
+
+/*
+ * These are set by clock driver during its init
+ */
+
+rtems_device_major_number rtems_clock_major = ~0;
+rtems_device_minor_number rtems_clock_minor;
+
+/*
+ * The previous ISR on this clock tick interrupt vector.
+ */
+
+rtems_isr_entry Old_ticker;
+
+void Clock_exit( void );
+
+/*
+ * Isr Handler
+ */
+
+rtems_isr Clock_isr(
+ rtems_vector_number vector
+)
+{
+/*
+ * bump the number of clock driver ticks since initialization
+ *
+ * determine if it is time to announce the passing of tick as configured
+ * to RTEMS through the rtems_clock_tick directive
+ *
+ * perform any timer dependent tasks
+ */
+
+ /* Clear overflow flag */
+ clockwrite(LM32_CLOCK_SR, 0);
+ lm32_interrupt_ack(CLOCK_IRQMASK);
+
+ /* Increment clock ticks */
+ Clock_driver_ticks += 1;
+
+ rtems_clock_tick();
+}
+
+/*
+ * Install_clock
+ *
+ * Install a clock tick handler and reprograms the chip. This
+ * is used to initially establish the clock tick.
+ */
+
+void Install_clock(
+ rtems_isr_entry clock_isr
+)
+{
+ /*
+ * Initialize the clock tick device driver variables
+ */
+
+ Clock_driver_ticks = 0;
+
+ Old_ticker = (rtems_isr_entry) set_vector( clock_isr, CLOCK_VECTOR, 1 );
+ /*
+ * Hardware specific initialize goes here
+ */
+
+ printk("rtems_configuration_get_microseconds_per_tick() %d\n",
+ rtems_configuration_get_microseconds_per_tick());
+ printk("PERIOD %d\n",
+ (CPU_FREQUENCY / (1000000 / rtems_configuration_get_microseconds_per_tick())));
+
+ /* Set clock period */
+ clockwrite(LM32_CLOCK_PERIOD,
+ (CPU_FREQUENCY /
+ (1000000 / rtems_configuration_get_microseconds_per_tick())));
+
+ /* Enable clock interrupts and start in continuous mode */
+ clockwrite(LM32_CLOCK_CR, LM32_CLOCK_CR_ITO |
+ LM32_CLOCK_CR_CONT |
+ LM32_CLOCK_CR_START);
+
+ lm32_interrupt_unmask(CLOCK_IRQMASK);
+
+ /*
+ * Schedule the clock cleanup routine to execute if the application exits.
+ */
+
+ atexit( Clock_exit );
+}
+
+/*
+ * Clean up before the application exits
+ */
+
+void Clock_exit( void )
+{
+ /* Disable clock interrupts and stop */
+
+ lm32_interrupt_unmask(CLOCK_IRQMASK);
+ clockwrite(LM32_CLOCK_CR, LM32_CLOCK_CR_STOP);
+}
+
+/*
+ * Clock_initialize
+ *
+ * Device driver entry point for clock tick driver initialization.
+ */
+
+rtems_device_driver Clock_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ printk("Clock initialize %d %d\n", major, minor);
+
+ Install_clock( Clock_isr );
+
+ /*
+ * make major/minor avail to others such as shared memory driver
+ */
+
+ rtems_clock_major = major;
+ rtems_clock_minor = minor;
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/c/src/lib/libbsp/lm32/shared/clock/clock.h b/c/src/lib/libbsp/lm32/shared/clock/clock.h
new file mode 100644
index 0000000000..d8f86175f9
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/clock/clock.h
@@ -0,0 +1,42 @@
+/*
+ * This file contains definitions for LatticeMico32 Timer (Clock)
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ * Jukka Pietarinen <jukka.pietarinen@mrf.fi>, 2008,
+ * Micro-Research Finland Oy
+ */
+
+#ifndef _BSPCLOCK_H
+#define _BSPCLOCK_H
+
+/* Status Register */
+
+#define LM32_CLOCK_SR (0x0000)
+#define LM32_CLOCK_SR_TO (0x0001)
+#define LM32_CLOCK_SR_RUN (0x0002)
+
+/* Control Register */
+
+#define LM32_CLOCK_CR (0x0004)
+#define LM32_CLOCK_CR_ITO (0x0001)
+#define LM32_CLOCK_CR_CONT (0x0002)
+#define LM32_CLOCK_CR_START (0x0004)
+#define LM32_CLOCK_CR_STOP (0x0008)
+
+/* Period Register */
+
+#define LM32_CLOCK_PERIOD (0x0008)
+
+/* Snapshot Register */
+
+#define LM32_CLOCK_SNAPSHOT (0x000C)
+
+#endif /* _BSPCLOCK_H */
diff --git a/c/src/lib/libbsp/lm32/shared/console/console.c b/c/src/lib/libbsp/lm32/shared/console/console.c
new file mode 100644
index 0000000000..63fa79de0d
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/console/console.c
@@ -0,0 +1,226 @@
+/*
+ * Console driver for Lattice Mico32 (lm32).
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ * Jukka Pietarinen <jukka.pietarinen@mrf.fi>, 2008,
+ * Micro-Research Finland Oy
+ */
+
+#define NO_BSP_INIT
+
+#include <rtems.h>
+#include <bsp.h>
+#include <rtems/libio.h>
+
+void BSP_uart_polled_write(char ch);
+char BSP_uart_polled_read( void );
+char BSP_uart_is_character_ready(char *ch);
+
+/* console_initialize
+ *
+ * This routine initializes the console IO driver.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values:
+ */
+
+rtems_device_driver console_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ rtems_status_code status;
+
+ printk("console_initialize\n");
+
+ status = rtems_io_register_name(
+ "/dev/console",
+ major,
+ (rtems_device_minor_number) 0
+ );
+
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred(status);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/* is_character_ready
+ *
+ * This routine returns TRUE if a character is available.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values:
+ */
+
+bool is_character_ready(
+ char *ch
+)
+{
+ return BSP_uart_is_character_ready(ch);
+}
+
+/* inbyte
+ *
+ * This routine reads a character from the SOURCE.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values:
+ * character read from SOURCE
+ */
+
+char inbyte( void )
+{
+ /*
+ * If polling, wait until a character is available.
+ */
+
+ return (char) BSP_uart_polled_read();
+}
+
+/* outbyte
+ *
+ * This routine transmits a character out the SOURCE. It may support
+ * XON/XOFF flow control.
+ *
+ * Input parameters:
+ * ch - character to be transmitted
+ *
+ * Output parameters: NONE
+ */
+
+void outbyte(
+ char ch
+)
+{
+ /*
+ * If polling, wait for the transmitter to be ready.
+ * Check for flow control requests and process.
+ * Then output the character.
+ */
+
+ BSP_uart_polled_write(ch);
+}
+
+/*
+ * Open entry point
+ */
+
+rtems_device_driver console_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Close entry point
+ */
+
+rtems_device_driver console_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * read bytes from the serial port. We only have stdin.
+ */
+
+rtems_device_driver console_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ rtems_libio_rw_args_t *rw_args;
+ char *buffer;
+ int maximum;
+ int count = 0;
+
+ rw_args = (rtems_libio_rw_args_t *) arg;
+
+ buffer = rw_args->buffer;
+ maximum = rw_args->count;
+
+ for (count = 0; count < maximum; count++) {
+ buffer[ count ] = inbyte();
+ if (buffer[ count ] == '\n' || buffer[ count ] == '\r') {
+ buffer[ count++ ] = '\n';
+ break;
+ }
+ }
+
+ rw_args->bytes_moved = count;
+ return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
+}
+
+/*
+ * write bytes to the serial port. Stdout and stderr are the same.
+ */
+
+rtems_device_driver console_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ int count;
+ int maximum;
+ rtems_libio_rw_args_t *rw_args;
+ char *buffer;
+
+ rw_args = (rtems_libio_rw_args_t *) arg;
+
+ buffer = rw_args->buffer;
+ maximum = rw_args->count;
+
+ for (count = 0; count < maximum; count++) {
+ if ( buffer[ count ] == '\n') {
+ outbyte('\r');
+ }
+ outbyte( buffer[ count ] );
+ }
+
+ rw_args->bytes_moved = maximum;
+ return 0;
+}
+
+/*
+ * IO Control entry point
+ */
+
+rtems_device_driver console_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return RTEMS_SUCCESSFUL;
+}
+
+BSP_output_char_function_type BSP_output_char = BSP_uart_polled_write;
+BSP_polling_getchar_function_type BSP_poll_char = BSP_uart_polled_read;
diff --git a/c/src/lib/libbsp/lm32/shared/console/uart.c b/c/src/lib/libbsp/lm32/shared/console/uart.c
new file mode 100644
index 0000000000..a67f8092aa
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/console/uart.c
@@ -0,0 +1,72 @@
+/*
+ * Uart driver for Lattice Mico32 (lm32) UART
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ * Jukka Pietarinen <jukka.pietarinen@mrf.fi>, 2008,
+ * Micro-Research Finland Oy
+ */
+
+#include "../include/system_conf.h"
+#include "uart.h"
+#include <rtems/libio.h>
+
+static inline int uartread(unsigned int reg)
+{
+ return *((int*)(UART_BASE_ADDRESS + reg));
+}
+
+static inline void uartwrite(unsigned int reg, int value)
+{
+ *((int*)(UART_BASE_ADDRESS + reg)) = value;
+}
+
+void BSP_uart_init(int baud)
+{
+ /* Disable UART interrupts */
+ uartwrite(LM32_UART_IER, 0);
+
+ /* Line control 8 bit, 1 stop, no parity */
+ uartwrite(LM32_UART_LCR, LM32_UART_LCR_8BIT);
+
+ /* Modem control, DTR = 1, RTS = 1 */
+ uartwrite(LM32_UART_MCR, LM32_UART_MCR_DTR | LM32_UART_MCR_RTS);
+
+ /* Set baud rate */
+ uartwrite(LM32_UART_DIV, CPU_FREQUENCY/baud);
+}
+
+void BSP_uart_polled_write(char ch)
+{
+ /* Insert CR before LF */
+ if (ch == '\n')
+ BSP_uart_polled_write('\r');
+ /* Wait until THR is empty. */
+ while (!(uartread(LM32_UART_LSR) & LM32_UART_LSR_THRE));
+ uartwrite(LM32_UART_RBR, ch);
+}
+
+char BSP_uart_polled_read( void )
+{
+ /* Wait until there is a byte in RBR */
+ while (!(uartread(LM32_UART_LSR) & LM32_UART_LSR_DR));
+ return (char) uartread(LM32_UART_RBR);
+}
+
+char BSP_uart_is_character_ready(char *ch)
+{
+ if (uartread(LM32_UART_LSR) & LM32_UART_LSR_DR)
+ {
+ *ch = (char) uartread(LM32_UART_RBR);
+ return true;
+ }
+ *ch = '0';
+ return false;
+}
diff --git a/c/src/lib/libbsp/lm32/shared/console/uart.h b/c/src/lib/libbsp/lm32/shared/console/uart.h
new file mode 100644
index 0000000000..7c64646fdc
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/console/uart.h
@@ -0,0 +1,89 @@
+/*
+ * This file contains definitions for LatticeMico32 UART
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ * Jukka Pietarinen <jukka.pietarinen@mrf.fi>, 2008,
+ * Micro-Research Finland Oy
+ */
+
+#ifndef _BSPUART_H
+#define _BSPUART_H
+
+void BSP_uart_init(int baud);
+
+/* Receive buffer register / transmit holding register */
+
+#define LM32_UART_RBR (0x0000)
+
+/* Interrupt enable register */
+
+#define LM32_UART_IER (0x0004)
+#define LM32_UART_IER_RBRI (0x0001)
+#define LM32_UART_IER_THRI (0x0002)
+#define LM32_UART_IER_RLSI (0x0004)
+#define LM32_UART_IER_MSI (0x0008)
+
+/* Interrupt identification register */
+
+#define LM32_UART_IIR (0x0008)
+#define LM32_UART_IIR_STAT (0x0001)
+#define LM32_UART_IIR_ID0 (0x0002)
+#define LM32_UART_IIR_ID1 (0x0004)
+
+/* Line control register */
+
+#define LM32_UART_LCR (0x000C)
+#define LM32_UART_LCR_WLS0 (0x0001)
+#define LM32_UART_LCR_WLS1 (0x0002)
+#define LM32_UART_LCR_STB (0x0004)
+#define LM32_UART_LCR_PEN (0x0008)
+#define LM32_UART_LCR_EPS (0x0010)
+#define LM32_UART_LCR_SP (0x0020)
+#define LM32_UART_LCR_SB (0x0040)
+#define LM32_UART_LCR_5BIT (0)
+#define LM32_UART_LCR_6BIT (LM32_UART_LCR_WLS0)
+#define LM32_UART_LCR_7BIT (LM32_UART_LCR_WLS1)
+#define LM32_UART_LCR_8BIT (LM32_UART_LCR_WLS1 | LM32_UART_LCR_WLS0)
+
+/* Modem control register */
+
+#define LM32_UART_MCR (0x0010)
+#define LM32_UART_MCR_DTR (0x0001)
+#define LM32_UART_MCR_RTS (0x0002)
+
+/* Line status register */
+
+#define LM32_UART_LSR (0x0014)
+#define LM32_UART_LSR_DR (0x0001)
+#define LM32_UART_LSR_OE (0x0002)
+#define LM32_UART_LSR_PE (0x0004)
+#define LM32_UART_LSR_FE (0x0008)
+#define LM32_UART_LSR_BI (0x0010)
+#define LM32_UART_LSR_THRE (0x0020)
+#define LM32_UART_LSR_TEMT (0x0040)
+
+/* Modem status register */
+
+#define LM32_UART_MSR (0x0018)
+#define LM32_UART_MSR_DCTS (0x0001)
+#define LM32_UART_MSR_DDSR (0x0002)
+#define LM32_UART_MSR_TERI (0x0004)
+#define LM32_UART_MSR_DDCD (0x0008)
+#define LM32_UART_MSR_CTS (0x0010)
+#define LM32_UART_MSR_DSR (0x0020)
+#define LM32_UART_MSR_RI (0x0040)
+#define LM32_UART_MSR_DCD (0x0000)
+
+/* Baud-rate divisor register */
+
+#define LM32_UART_DIV (0x001C)
+
+#endif /* _BSPUART_H */
diff --git a/c/src/lib/libbsp/lm32/shared/start/start.S b/c/src/lib/libbsp/lm32/shared/start/start.S
new file mode 100644
index 0000000000..6cfa9268f1
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/start/start.S
@@ -0,0 +1,156 @@
+/* LM32 startup code
+ *
+ * This is the entry point on reset and when loading the
+ * executive from a bootloader.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ * Jukka Pietarinen <jukka.pietarinen@mrf.fi>, 2008,
+ * Micro-Research Finland Oy
+ */
+
+ .section .boot,"a",@progbits
+ .align 4
+
+ .globl start
+ .type start,@function
+ .globl _start
+ .type _start,@function
+ .globl __start
+ .type __start,@function
+ .globl LatticeDDInit
+ .type LatticeDDInit,@function
+
+LatticeDDInit:
+__start:
+_start:
+start:
+ /* Clear r0 */
+ xor r0,r0,r0
+ /* Disable interrupts */
+ wcsr IE, r0
+ /* Mask all interrupts */
+ wcsr IM,r0
+ /* Set exception base address */
+ mvhi r1, hi(start)
+ ori r1, r1, lo(start)
+ wcsr EBA, r1
+ bi crt0
+ nop
+/*
+ * Unused handlers call debug handlers
+ */
+breakpoint_handler:
+ rcsr r7, DEBA
+ addi r7, r7, 32
+ b r7
+ nop
+ nop
+ nop
+ nop
+ nop
+instruction_bus_error_handler:
+ rcsr r7, DEBA
+ addi r7, r7, 64
+ b r7
+ nop
+ nop
+ nop
+ nop
+ nop
+watchpoint_handler:
+ rcsr r7, DEBA
+ addi r7, r7, 96
+ b r7
+ nop
+ nop
+ nop
+ nop
+ nop
+data_bus_error_handler:
+ rcsr r7, DEBA
+ addi r7, r7, 128
+ b r7
+ nop
+ nop
+ nop
+ nop
+ nop
+divide_by_zero_handler:
+ rcsr r7, DEBA
+ addi r7, r7, 160
+ b r7
+ nop
+ nop
+ nop
+ nop
+ nop
+interrupt_handler:
+ .extern _ISR_Handler
+ bi _ISR_Handler
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+system_call_handler:
+ rcsr r7, DEBA
+ addi r7, r7, 224
+ b r7
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ .text
+crt0:
+ /* Flush data cache */
+ addi r1, r0, 1
+ wcsr DCC, r1
+ nop
+ nop
+ nop
+ nop
+ /* Flush Instruction Cache */
+ wcsr ICC, r1
+ nop
+ nop
+ nop
+ nop
+ /* Initialize stack pointer */
+ mvhi sp, hi(_fstack-4)
+ ori sp, sp, lo(_fstack-4)
+ /* Initialize global pointer */
+ mvhi gp, hi(_edata)
+ ori gp, gp, lo(_edata)
+ /* Clear bss */
+ mvhi r1, hi(_clear_start)
+ ori r1, r1, lo(_clear_start)
+ mvhi r3, hi(_clear_end)
+ ori r3, r3, lo(_clear_end)
+.clear_bss:
+ be r1, r3, .end_clear_bss
+ sw (r1+0), r0
+ addi r1, r1, 4
+ bi .clear_bss
+.end_clear_bss:
+ mvi r1, 0
+ mvi r2, 0
+ mvi r3, 0
+ calli boot_card
+.dead_end:
+ bi .dead_end
+
+ calli boot_card
+# boot_card should never return
+_stuck_in_start:
+ bi _stuck_in_start
+
+
diff --git a/c/src/lib/libbsp/lm32/shared/startup/bspstart.c b/c/src/lib/libbsp/lm32/shared/startup/bspstart.c
new file mode 100644
index 0000000000..770d8d81b4
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/startup/bspstart.c
@@ -0,0 +1,49 @@
+/*
+ * This routine starts the application. It includes application,
+ * board, and monitor specific initialization and configuration.
+ * The generic CPU dependent initialization has been performed
+ * before this routine is invoked.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ * Jukka Pietarinen <jukka.pietarinen@mrf.fi>, 2008,
+ * Micro-Research Finland Oy
+ */
+
+#include <string.h>
+
+#include <bsp.h>
+#include "../include/system_conf.h"
+#include "../console/uart.h"
+#include <rtems/score/heap.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/timespec.h>
+#include <rtems/score/tod.h>
+
+/*
+ * bsp_start
+ *
+ * This routine does the bulk of the system initialization.
+ */
+
+void bsp_start( void )
+{
+ /* Setup console baud rate which we derive from
+ Mico System Builder (MSB) generated system_conf.h */
+ BSP_uart_init(UART_BAUD_RATE);
+}
+
+void bsp_predriver_hook(void)
+{
+}
+
+
diff --git a/c/src/lib/libbsp/lm32/shared/startup/setvec.c b/c/src/lib/libbsp/lm32/shared/startup/setvec.c
new file mode 100644
index 0000000000..b7818d3699
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/startup/setvec.c
@@ -0,0 +1,43 @@
+/* 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
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ */
+
+#include <rtems.h>
+#include <bsp.h>
+
+lm32_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 */
+)
+{
+ lm32_isr_entry previous_isr;
+
+ if ( type )
+ rtems_interrupt_catch( handler, vector, (rtems_isr_entry *) &previous_isr );
+ else {
+ /* XXX: install non-RTEMS ISR as "raw" interupt */
+ }
+ return previous_isr;
+}
diff --git a/c/src/lib/libbsp/lm32/shared/timer/timer.c b/c/src/lib/libbsp/lm32/shared/timer/timer.c
new file mode 100644
index 0000000000..4fef00ce37
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/timer/timer.c
@@ -0,0 +1,107 @@
+/* timer.c
+ *
+ * This file manages the benchmark timer used by the RTEMS Timing
+ * Test Suite. Each measured time period is demarcated by calls to
+ * benchmark_timer_initialize() and benchmark_timer_read().
+ * benchmark_timer_read() usually returns the number of microseconds
+ * since benchmark_timer_initialize() exitted.
+ *
+ * NOTE: It is important that the timer start/stop overhead be
+ * determined when porting or modifying this code.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ * Jukka Pietarinen <jukka.pietarinen@mrf.fi>, 2008,
+ * Micro-Research Finland Oy
+ */
+
+#include <rtems.h>
+#include <bsp.h>
+#include "../include/system_conf.h"
+#include "../../shared/clock/clock.h"
+
+static inline int timerread(unsigned int reg)
+{
+#ifdef TIMER1_BASE_ADDRESS
+ return *((int*)(TIMER1_BASE_ADDRESS + reg));
+#else
+#warning "Benchmarking timer TIMER1 not available!"
+ return 0;
+#endif
+}
+
+static inline void timerwrite(unsigned int reg, int value)
+{
+#ifdef TIMER1_BASE_ADDRESS
+ *((int*)(TIMER1_BASE_ADDRESS + reg)) = value;
+#endif
+}
+
+bool benchmark_timer_find_average_overhead;
+
+void benchmark_timer_initialize( void )
+{
+ /* Set timer period */
+ timerwrite(LM32_CLOCK_PERIOD, 0xffffffff);
+ /* Stop timer */
+ timerwrite(LM32_CLOCK_CR, LM32_CLOCK_CR_STOP);
+ /* Clear status register */
+ timerwrite(LM32_CLOCK_SR, 0);
+ /* Start timer */
+ timerwrite(LM32_CLOCK_CR, LM32_CLOCK_CR_START);
+}
+
+/*
+ * The following controls the behavior of benchmark_timer_read().
+ *
+ * AVG_OVEREHAD is the overhead for starting and stopping the timer. It
+ * is usually deducted from the number returned.
+ *
+ * LEAST_VALID is the lowest number this routine should trust. Numbers
+ * below this are "noise" and zero is returned.
+ */
+
+#define AVG_OVERHEAD 4 /* It typically takes X.X microseconds */
+ /* (Y countdowns) to start/stop the timer. */
+ /* This value is in microseconds. */
+#define LEAST_VALID 4 /* Don't trust a clicks value lower than this */
+
+int benchmark_timer_read( void )
+{
+ uint32_t ticks;
+ uint32_t total;
+ uint32_t status;
+
+ ticks = 0xffffffff - timerread(LM32_CLOCK_SNAPSHOT);
+ status = timerread(LM32_CLOCK_SR);
+ if (status & LM32_CLOCK_SR_TO)
+ printk("Timer overflow!\n");
+
+ total = ticks / (CPU_FREQUENCY / 1000000);
+
+ if ( benchmark_timer_find_average_overhead == true )
+ return total; /* in XXX microsecond units */
+ else
+ {
+ if ( total < LEAST_VALID )
+ return 0; /* below timer resolution */
+ /*
+ * Somehow convert total into microseconds
+ */
+ return (total - AVG_OVERHEAD);
+ }
+}
+
+void benchmark_timer_disable_subtracting_average_overhead(
+ bool find_flag
+)
+{
+ benchmark_timer_find_average_overhead = find_flag;
+}
diff --git a/c/src/lib/libbsp/lm32/shared/tsmac/dp83848phy.h b/c/src/lib/libbsp/lm32/shared/tsmac/dp83848phy.h
new file mode 100644
index 0000000000..792130943f
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/tsmac/dp83848phy.h
@@ -0,0 +1,182 @@
+/*
+ * This file contains definitions for LatticeMico32 TSMAC (Tri-Speed MAC)
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ * Jukka Pietarinen <jukka.pietarinen@mrf.fi>, 2008,
+ * Micro-Research Finland Oy
+ */
+
+#ifndef _DP83848PHY_H
+#define _DP83848PHY_H
+
+#define DEFAULT_PHY_ADDRESS (0x01)
+
+#define PHY_BMCR (0x00)
+#define PHY_BMCR_RESET (1<<15)
+#define PHY_BMCR_LOOPBACK (1<<14)
+#define PHY_BMCR_SPEEDSEL (1<<13)
+#define PHY_BMCR_AN_ENA (1<<12)
+#define PHY_BMCR_PWRDWN (1<<11)
+#define PHY_BMCR_ISOLATE (1<<10)
+#define PHY_BMCR_RESTART_AN (1<<9)
+#define PHY_BMCR_DUPLEX_MODE (1<<8)
+#define PHY_BMCR_COLL_TEST (1<<7)
+#define PHY_BMSR (0x01)
+#define PHY_BMSR_100_T4 (1<<15)
+#define PHY_BMSR_100_TX_FD (1<<14)
+#define PHY_BMSR_100_TX_HD (1<<13)
+#define PHY_BMSR_10_T_FD (1<<12)
+#define PHY_BMSR_10_T_HD (1<<11)
+#define PHY_BMSR_PRESUP (1<<6)
+#define PHY_BMSR_AN_CMPL (1<<5)
+#define PHY_BMSR_REM_FLT (1<<4)
+#define PHY_BMSR_AN_AB (1<<3)
+#define PHY_BMSR_LINK_STAT (1<<2)
+#define PHY_BMSR_JABBDET (1<<1)
+#define PHY_BMSR_EXT_CAP (1<<0)
+#define PHY_PHYIDR1 (0x02)
+#define DEFAULT_PHYIDR1 (0x2000)
+#define PHY_PHYIDR2 (0x03)
+#define DEFAULT_PHYIDR2 (0x5C90)
+#define PHY_ANAR (0x04)
+#define PHY_ANAR_NP (1<<15)
+#define PHY_ANAR_RF (1<<13)
+#define PHY_ANAR_ASM_DIR (1<<11)
+#define PHY_ANAR_PAUSE (1<<10)
+#define PHY_ANAR_T4 (1<<9)
+#define PHY_ANAR_TX_FD (1<<8)
+#define PHY_ANAR_TX (1<<7)
+#define PHY_ANAR_10_FD (1<<6)
+#define PHY_ANAR_10 (1<<5)
+#define PHY_ANAR_SEL_MASK (0x0f)
+#define PHY_ANAR_SEL_SHIFT (0)
+#define PHY_ANAR_SEL_DEF (1)
+#define PHY_ANLPAR (0x05)
+#define PHY_ANLPAR_NP (1<<15)
+#define PHY_ANLPAR_ACK (1<<14)
+#define PHY_ANLPAR_RF (1<<13)
+#define PHY_ANLPAR_ASM_DIR (1<<11)
+#define PHY_ANLPAR_PAUSE (1<<10)
+#define PHY_ANLPAR_T4 (1<<9)
+#define PHY_ANLPAR_TX_FD (1<<8)
+#define PHY_ANLPAR_TX (1<<7)
+#define PHY_ANLPAR_10_FD (1<<6)
+#define PHY_ANLPAR_10 (1<<5)
+#define PHY_ANLPAR_SEL_MASK (0x0f)
+#define PHY_ANLPAR_SEL_SHIFT (0)
+#define PHY_ANLPARNP (0x05)
+#define PHY_ANLPARNP_NP (1<<15)
+#define PHY_ANLPARNP_ACK (1<<14)
+#define PHY_ANLPARNP_MP (1<<13)
+#define PHY_ANLPARNP_ACK2 (1<<12)
+#define PHY_ANLPARNP_TOGGLE (1<<11)
+#define PHY_ANLPARNP_CDE_MASK (0x03ff)
+#define PHY_ANER (0x06)
+#define PHY_ANER_PDF (1<<4)
+#define PHY_ANER_LP_NP_ABLE (1<<3)
+#define PHY_ANER_NP_ABLE (1<<2)
+#define PHY_ANER_PAGE_RX (1<<1)
+#define PHY_ANER_LP_AN_ABLE (1<<0)
+#define PHY_ANNPTR (0x07)
+#define PHY_ANNPTR_NP (1<<15)
+#define PHY_ANNPTR_MP (1<<13)
+#define PHY_ANNPTR_ACK2 (1<<12)
+#define PHY_ANNPTR_TOG_TX (1<<11)
+#define PHY_ANNPTR_CDE_MASK (0x03ff)
+#define PHY_PHYSTS (0x10)
+#define PHY_PHYSTS_MDIX_MDE (1<<14)
+#define PHY_PHYSTS_RCV_ERRL (1<<13)
+#define PHY_PHYSTS_POLSTAT (1<<12)
+#define PHY_PHYSTS_FCSL (1<<11)
+#define PHY_PHYSTS_SD (1<<10)
+#define PHY_PHYSTS_DESCL (1<<9)
+#define PHY_PHYSTS_PGREC (1<<8)
+#define PHY_PHYSTS_MIIIRQ (1<<7)
+#define PHY_PHYSTS_REM_FLT (1<<6)
+#define PHY_PHYSTS_JABBDET (1<<5)
+#define PHY_PHYSTS_AN_CMP (1<<4)
+#define PHY_PHYSTS_LOOPBACK (1<<3)
+#define PHY_PHYSTS_DUPLEX (1<<2)
+#define PHY_PHYSTS_SPEED (1<<1)
+#define PHY_PHYSTS_LINK (1<<0)
+#define PHY_MICR (0x11)
+#define PHY_MICR_TINT (1<<2)
+#define PHY_MICR_INTEN (1<<1)
+#define PHY_MICR_INT_OE (1<<0)
+#define PHY_MISR (0x12)
+#define PHY_MISR_ED_INT (1<<14)
+#define PHY_MISR_LINK_INT (1<<13)
+#define PHY_MISR_SPD_INT (1<<12)
+#define PHY_MISR_DUP_INT (1<<11)
+#define PHY_MISR_ANC_INT (1<<10)
+#define PHY_MISR_FHF_INT (1<<9)
+#define PHY_MISR_RHF_INT (1<<8)
+#define PHY_MISR_ED_INT_EN (1<<6)
+#define PHY_MISR_LINK_INT_EN (1<<5)
+#define PHY_MISR_SPD_INT_EN (1<<4)
+#define PHY_MISR_DUP_INT_EN (1<<3)
+#define PHY_MISR_ANC_INT_EN (1<<2)
+#define PHY_MISR_FHF_INT_EN (1<<1)
+#define PHY_MISR_RHF_INT_EN (1<<0)
+#define PHY_FCSCR (0x14)
+#define PHY_RECR (0x15)
+#define PHY_PCSR (0x16)
+#define PHY_PCSR_TQ_EN (1<<10)
+#define PHY_PCSR_SDFPMA (1<<9)
+#define PHY_PCSR_SD_OPT (1<<8)
+#define PHY_PCSR_DESC_TIME (1<<7)
+#define PHY_PCSR_F_100_OK (1<<5)
+#define PHY_PCSR_NRZI_BYPASS (1<<2)
+#define PHY_RBR (0x17)
+#define PHY_RBR_RMII_MODE (1<<5)
+#define PHY_RBR_RMII_REV1_0 (1<<4)
+#define PHY_RBR_RX_OVF_STS (1<<3)
+#define PHY_RBR_RX_UNF_STS (1<<2)
+#define PHY_RBR_ELAST_BUF1 (1<<1)
+#define PHY_RBR_ELAST_BUF0 (1<<0)
+#define PHY_LEDCR (0x18)
+#define PHY_LEDCR_DRV_SPDLED (1<<5)
+#define PHY_LEDCR_DRV_LNKLED (1<<4)
+#define PHY_LEDCR_DRV_ACTLED (1<<3)
+#define PHY_LEDCR_SPDLED (1<<2)
+#define PHY_LEDCR_LNKLED (1<<1)
+#define PHY_LEDCR_ACTLED (1<<0)
+#define PHY_PHYCR (0x19)
+#define PHY_PHYCR_MDIX_EN (1<<15)
+#define PHY_PHYCR_FORCE_MDIX (1<<14)
+#define PHY_PHYCR_PAUSE_RX (1<<13)
+#define PHY_PHYCR_PAUSE_TX (1<<12)
+#define PHY_PHYCR_BIST_FE (1<<11)
+#define PHY_PHYCR_PSR_15 (1<<10)
+#define PHY_PHYCR_BIST_STATUS (1<<9)
+#define PHY_PHYCR_BIST_START (1<<8)
+#define PHY_PHYCR_BP_STRETCH (1<<7)
+#define PHY_PHYCR_LED_CNFG1 (1<<6)
+#define PHY_PHYCR_LED_CNFG0 (1<<5)
+#define PHY_PHYCR_ADDR4 (1<<4)
+#define PHY_PHYCR_ADDR3 (1<<3)
+#define PHY_PHYCR_ADDR2 (1<<2)
+#define PHY_PHYCR_ADDR1 (1<<1)
+#define PHY_PHYCR_ADDR0 (1<<0)
+#define PHY_10BTSCR (0x1A)
+#define PHY_10BTSCR_SERIAL (1<<15)
+#define PHY_10BTSCR_SQ_MASK (0x07)
+#define PHY_10BTSCR_SQ_SHIFT (9)
+#define PHY_10BTSCR_LP_10_DIS (1<<8)
+#define PHY_10BTSCR_LP_DIS (1<<7)
+#define PHY_10BTSCR_FLINK_10 (1<<1)
+#define PHY_10BTSCR_POL (1<<4)
+#define PHY_10BTSCR_HB_DIS (1<<1)
+#define PHY_10BTSCR_JAB_DIS (1<<0)
+#define PHY_CDCTRL1 (0x1B)
+#define PHY_EDCR (0x1D)
+
+#endif /* _DP83848PHY_H */
diff --git a/c/src/lib/libbsp/lm32/shared/tsmac/tsmac.c b/c/src/lib/libbsp/lm32/shared/tsmac/tsmac.c
new file mode 100644
index 0000000000..a0eb06116e
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/tsmac/tsmac.c
@@ -0,0 +1,824 @@
+/*
+ * This file contains definitions for LatticeMico32 TSMAC (Tri-Speed MAC)
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ * Jukka Pietarinen <jukka.pietarinen@mrf.fi>, 2008,
+ * Micro-Research Finland Oy
+ */
+
+#define _KERNEL
+
+#include <rtems.h>
+#include <bsp.h>
+#include <stdio.h>
+#include <errno.h>
+#include <rtems/error.h>
+#include <rtems/rtems_bsdnet.h>
+
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include "../include/system_conf.h"
+#include "tsmac.h"
+#include "dp83848phy.h"
+
+struct tsmac_softc {
+ struct arpcom arpcom;
+ void *ioaddr;
+ rtems_id rxDaemonTid;
+ rtems_id txDaemonTid;
+
+ /*
+ * Statistics
+ */
+ int rxInterrupts;
+ int rxPktIgnore;
+ int rxLenCheckError;
+ int rxLongFrame;
+ int rxShortFrame;
+ int rxIPGViolation;
+ int rxCRCError;
+ int rxOKPackets;
+ int rxControlFrame;
+ int rxPauseFrame;
+ int rxMulticast;
+ int rxBroadcast;
+ int rxVLANTag;
+ int rxPreShrink;
+ int rxDribNib;
+ int rxUnsupOPCD;
+ int rxByteCnt;
+ int rxFifoFull;
+
+ int txInterrupts;
+ int txUnicast;
+ int txPauseFrame;
+ int txMulticast;
+ int txBroadcast;
+ int txVLANTag;
+ int txBadFCS;
+ int txJumboCnt;
+ int txByteCnt;
+ int txLostCarrier;
+ int txFifoFull;
+};
+
+/*
+ * Macros to access tsmac wrapper registers.
+ */
+
+static inline uint32_t tsmacread(unsigned int reg)
+{
+ return *((uint32_t *)(TS_MAC_CORE_BASE_ADDRESS + reg));
+}
+
+static inline void tsmacwrite(unsigned int reg, uint32_t value)
+{
+ *((uint32_t *)(TS_MAC_CORE_BASE_ADDRESS + reg)) = value;
+}
+
+/*
+ * tsmac is a wishbone to MAC wrapper.
+ * The macros below access to MAC registers.
+ */
+
+static inline uint16_t tsmacregread(unsigned int reg)
+{
+ tsmacwrite(LM32_TSMAC_MAC_REGS_ADDR_RW, reg);
+ return *((uint16_t *)(TS_MAC_CORE_BASE_ADDRESS + LM32_TSMAC_MAC_REGS_DATA + 2));
+}
+
+static inline void tsmacregwrite(unsigned int reg, uint16_t value)
+{
+ *((uint16_t *)(TS_MAC_CORE_BASE_ADDRESS + LM32_TSMAC_MAC_REGS_DATA + 2)) = value;
+ tsmacwrite(LM32_TSMAC_MAC_REGS_ADDR_RW, REGS_ADDR_WRITE | reg);
+}
+
+/*
+#define DEBUG 1
+*/
+
+/* We support one interface */
+
+#define TSMAC_NUM 1
+#define TSMAC_NAME "TSMAC"
+#define TSMAC_MAC0 0x00
+#define TSMAC_MAC1 0x0E
+#define TSMAC_MAC2 0xB2
+#define TSMAC_MAC3 0x00
+#define TSMAC_MAC4 0x00
+#define TSMAC_MAC5 0x01
+
+/*
+ * The interrupt vector number associated with the tsmac device
+ * driver.
+ */
+
+#define TSMAC_VECTOR ( TS_MAC_CORE_IRQ )
+#define TSMAC_IRQMASK ( 1 << TSMAC_VECTOR )
+
+rtems_isr tsmac_interrupt_handler(rtems_vector_number vector);
+
+extern lm32_isr_entry set_vector(rtems_isr_entry handler,
+ rtems_vector_number vector, int type);
+
+/*
+ * Macros to access PHY registers through the (G)MII
+ */
+
+uint16_t tsmacphyread(unsigned int reg)
+{
+ tsmacregwrite(LM32_TSMAC_GMII_MNG_CTL_BYTE0,
+ ((DEFAULT_PHY_ADDRESS & GMII_MNG_CTL_PHY_ADD_MASK) <<
+ GMII_MNG_CTL_PHY_ADD_SHIFT) |
+ ((reg & GMII_MNG_CTL_REG_ADD_MASK) <<
+ GMII_MNG_CTL_REG_ADD_SHIFT) |
+ GMII_MNG_CTL_READ_PHYREG);
+
+ /* Wait for management interface to be ready */
+ while(!(tsmacregread(LM32_TSMAC_GMII_MNG_CTL_BYTE0) & GMII_MNG_CTL_CMD_FIN));
+
+ return tsmacregread(LM32_TSMAC_GMII_MNG_DAT_BYTE0);
+}
+
+void tsmacphywrite(unsigned int reg, uint16_t value)
+{
+ tsmacregwrite(LM32_TSMAC_GMII_MNG_DAT_BYTE0, value);
+ tsmacregwrite(LM32_TSMAC_GMII_MNG_CTL_BYTE0,
+ ((DEFAULT_PHY_ADDRESS & GMII_MNG_CTL_PHY_ADD_MASK) <<
+ GMII_MNG_CTL_PHY_ADD_SHIFT) |
+ ((reg & GMII_MNG_CTL_REG_ADD_MASK) <<
+ GMII_MNG_CTL_REG_ADD_SHIFT) |
+ GMII_MNG_CTL_WRITE_PHYREG);
+
+ /* Wait for management interface to be ready */
+ while(!(tsmacregread(LM32_TSMAC_GMII_MNG_CTL_BYTE0) & GMII_MNG_CTL_CMD_FIN));
+}
+
+/*
+ * Event definitions
+ */
+#define INTERRUPT_EVENT RTEMS_EVENT_1
+#define START_TRANSMIT_EVENT RTEMS_EVENT_2
+
+static struct tsmac_softc tsmac_softc[TSMAC_NUM];
+
+#ifdef CPU_U32_FIX
+
+/*
+ * Routine to align the received packet so that the ip header
+ * is on a 32-bit boundary. Necessary for cpu's that do not
+ * allow unaligned loads and stores and when the 32-bit DMA
+ * mode is used.
+ *
+ * Transfers are done on word basis to avoid possibly slow byte
+ * and half-word writes.
+ *
+ * Copied over from sonic.c driver
+ */
+
+void ipalign(struct mbuf *m)
+{
+ unsigned int *first, *last, data;
+ unsigned int tmp = 0;
+
+ if ((((int) m->m_data) & 2) && (m->m_len)) {
+ last = (unsigned int *) ((((int) m->m_data) + m->m_len + 8) & ~3);
+ first = (unsigned int *) (((int) m->m_data) & ~3);
+ tmp = *first << 16;
+ first++;
+ do {
+ data = *first;
+ *first = tmp | (data >> 16);
+ tmp = data << 16;
+ first++;
+ } while (first <= last);
+
+ m->m_data = (caddr_t)(((int) m->m_data) + 2);
+ }
+}
+#endif
+
+/*
+ * Receive task
+ */
+static void tsmac_rxDaemon(void *arg)
+{
+ struct tsmac_softc *tsmac = (struct tsmac_softc *) arg;
+ struct ifnet *ifp = &tsmac->arpcom.ac_if;
+ rtems_event_set events;
+ int rxq, count, len, data;
+
+#ifdef DEBUG
+ printk(TSMAC_NAME ": tsmac_rxDaemon\n");
+#endif
+
+ for(;;)
+ {
+ rtems_bsdnet_event_receive( RTEMS_ALL_EVENTS,
+ RTEMS_WAIT | RTEMS_EVENT_ANY,
+ RTEMS_NO_TIMEOUT,
+ &events);
+
+#ifdef DEBUG
+ printk(TSMAC_NAME ": tsmac_rxDaemon wakeup\n");
+#endif
+
+ for (;;)
+ {
+ struct mbuf* m;
+ struct ether_header* eh;
+ uint32_t *buf;
+
+ /* Get number of RX frames in RX FIFO */
+ rxq = tsmacread(LM32_TSMAC_RX_FRAMES_CNT);
+
+ if (rxq == 0)
+ break;
+
+ /* Get lenght of frame */
+ len = tsmacread(LM32_TSMAC_RX_LEN_FIFO);
+#ifdef DEBUG
+ printk(TSMAC_NAME ": Frames %d, len 0x%04x (%d)\n",
+ rxq, len, len);
+#endif
+
+ /*
+ * Get memory for packet
+ */
+ MGETHDR(m, M_WAIT, MT_DATA);
+ MCLGET(m, M_WAIT);
+
+ m->m_pkthdr.rcvif = ifp;
+
+ buf = (uint32_t *) mtod(m, uint32_t*);
+ for (count = 0; count < len; count += 4)
+ {
+ data = tsmacread(LM32_TSMAC_RX_DATA_FIFO);
+ *buf++ = data;
+#ifdef DEBUG
+ printk("%08x ", data);
+#endif
+ }
+#ifdef DEBUG
+ printk("\n");
+#endif
+
+ m->m_len = m->m_pkthdr.len =
+ len - sizeof(uint32_t) - sizeof(struct ether_header);
+ eh = mtod(m, struct ether_header*);
+ m->m_data += sizeof(struct ether_header);
+
+#ifdef CPU_U32_FIX
+ ipalign(m); /* Align packet on 32-bit boundary */
+#endif
+
+ /* Notify the ip stack that there is a new packet */
+ ether_input(ifp, eh, m);
+
+ /*
+ * Release RX frame
+ */
+ }
+ }
+}
+
+static unsigned char tsmac_txbuf[2048];
+
+static void tsmac_sendpacket(struct ifnet *ifp, struct mbuf *m)
+{
+ struct mbuf *nm = m;
+ int len = 0, i;
+ uint32_t *buf;
+
+#ifdef DEBUG
+ printk(TSMAC_NAME ": tsmac_sendpacket\n");
+#endif
+
+ do
+ {
+#ifdef DEBUG
+ printk("mbuf: 0x%08x len %03x: ", nm->m_data, nm->m_len);
+ for (i = 0; i < nm->m_len; i++)
+ {
+ printk("%02x", mtod(nm, unsigned char*)[i]);
+ if (i & 1)
+ printk(" ");
+ }
+ printk("\n");
+#endif
+
+ if (nm->m_len > 0)
+ {
+ memcpy(&tsmac_txbuf[len], (char *)nm->m_data, nm->m_len);
+ len += nm->m_len;
+ }
+ }
+ while ((nm = nm->m_next) != 0);
+
+ buf = (uint32_t *) tsmac_txbuf;
+ for (i = 0; i < len; i += 4)
+ {
+#ifdef DEBUG
+ printk("%08x", *buf);
+#endif
+ tsmacwrite(LM32_TSMAC_TX_DATA_FIFO, *buf++);
+ }
+#ifdef DEBUG
+ printk("\n");
+#endif
+
+ /*
+ * Enqueue TX frame
+ */
+ tsmacwrite(LM32_TSMAC_TX_LEN_FIFO, len);
+}
+
+/*
+ * Transmit task
+ */
+static void tsmac_txDaemon(void *arg)
+{
+ struct tsmac_softc *tsmac = (struct tsmac_softc *) arg;
+ struct ifnet *ifp = &tsmac->arpcom.ac_if;
+ struct mbuf *m;
+ rtems_event_set events;
+ int txq;
+
+#ifdef DEBUG
+ printk(TSMAC_NAME ": tsmac_txDaemon\n");
+#endif
+
+ for (;;)
+ {
+ /*
+ * Wait for packet
+ */
+ rtems_bsdnet_event_receive (START_TRANSMIT_EVENT | INTERRUPT_EVENT,
+ RTEMS_EVENT_ANY | RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT, &events);
+#ifdef DEBUG
+ printk(TSMAC_NAME ": tsmac_txDaemon event\n");
+#endif
+ for (;;)
+ {
+ /*
+ * Here we should read amount of transmit memory available
+ */
+
+ txq = 2048;
+
+ if (txq < ifp->if_mtu)
+ {
+ /*
+ * Here we need to enable transmit done IRQ
+ */
+#ifdef DEBUG
+ printk(TSMAC_NAME ": TXMA %d < MTU + CW%d\n", txq,
+ ifp->if_mtu);
+#endif
+ break;
+ }
+
+ /*
+ * Get the next mbuf chain to transmit.
+ */
+ IF_DEQUEUE(&ifp->if_snd, m);
+#ifdef DEBUG
+ printk(TSMAC_NAME ": mbuf %08x\n", (int) m);
+#endif
+ if (!m)
+ break;
+ tsmac_sendpacket(ifp, m);
+
+ m_freem(m);
+ }
+ ifp->if_flags &= ~IFF_OACTIVE;
+ }
+}
+
+/*
+ * Initialize TSMAC hardware
+ */
+void tsmac_init_hardware(struct tsmac_softc *tsmac)
+{
+ unsigned char *mac_addr;
+ int version_id, phyid, stat;
+
+#ifdef DEBUG
+ printk(TSMAC_NAME ": tsmac_init_hardware\n");
+#endif
+
+ version_id = tsmacread(LM32_TSMAC_VERID);
+#ifdef DEBUG
+ printk(TSMAC_NAME ": Version ID %08x\n", version_id);
+#endif
+
+#ifdef DEBUG
+ printk(TSMAC_NAME ": MAC MODE %04x\n", tsmacregread(LM32_TSMAC_MODE_BYTE0));
+ printk(TSMAC_NAME ": MAC TX_RX_CTL %04x\n", tsmacregread(LM32_TSMAC_TX_RX_CTL_BYTE0));
+ printk(TSMAC_NAME ": MAC MAX_PKT_SIZE %04x\n", tsmacregread(LM32_TSMAC_MAX_PKT_SIZE_BYTE0));
+ printk(TSMAC_NAME ": MAC IPG_VAL %04x\n", tsmacregread(LM32_TSMAC_IPG_VAL_BYTE0));
+ printk(TSMAC_NAME ": MAC MAC_ADDR0 %04x\n",
+ tsmacregread(LM32_TSMAC_MAC_ADDR_0_BYTE0));
+ printk(TSMAC_NAME ": MAC MAC_ADDR1 %04x\n",
+ tsmacregread(LM32_TSMAC_MAC_ADDR_1_BYTE0));
+ printk(TSMAC_NAME ": MAC MAC_ADDR2 %04x\n",
+ tsmacregread(LM32_TSMAC_MAC_ADDR_2_BYTE0));
+ printk(TSMAC_NAME ": MAC TX_RX_STS %04x\n",
+ tsmacregread(LM32_TSMAC_TX_RX_STS_BYTE0));
+#endif
+
+ /*
+ * Set our physical address
+ */
+ mac_addr = tsmac->arpcom.ac_enaddr;
+ tsmacregwrite(LM32_TSMAC_MAC_ADDR_0_BYTE0, (mac_addr[0] << 8) | mac_addr[1]);
+ tsmacregwrite(LM32_TSMAC_MAC_ADDR_1_BYTE0, (mac_addr[2] << 8) | mac_addr[3]);
+ tsmacregwrite(LM32_TSMAC_MAC_ADDR_2_BYTE0, (mac_addr[4] << 8) | mac_addr[5]);
+
+#ifdef DEBUG
+ printk(TSMAC_NAME ": After setting MAC address.\n");
+ printk(TSMAC_NAME ": MAC MAC_ADDR0 %04x\n",
+ tsmacregread(LM32_TSMAC_MAC_ADDR_0_BYTE0));
+ printk(TSMAC_NAME ": MAC MAC_ADDR1 %04x\n",
+ tsmacregread(LM32_TSMAC_MAC_ADDR_1_BYTE0));
+ printk(TSMAC_NAME ": MAC MAC_ADDR2 %04x\n",
+ tsmacregread(LM32_TSMAC_MAC_ADDR_2_BYTE0));
+#endif
+
+ /*
+ * Configure PHY
+ */
+
+ phyid = tsmacphyread(PHY_PHYIDR1);
+#ifdef DEBUG
+ printk(TSMAC_NAME ": PHYIDR1 %08x\n", phyid);
+#endif
+ phyid = tsmacphyread(PHY_PHYIDR2);
+#ifdef DEBUG
+ printk(TSMAC_NAME ": PHYIDR2 %08x\n", phyid);
+#endif
+
+#ifdef TSMAC_FORCE_10BASET
+ /* Force 10baseT mode, no AN, full duplex */
+ tsmacphywrite(PHY_BMCR, PHY_BMCR_DUPLEX_MODE);
+ stat = tsmacphyread(PHY_BMCR);
+#ifdef DEBUG
+ printk(TSMAC_NAME ": PHY BMCR %04x, wrote %04x\n", stat,
+ PHY_BMCR_DUPLEX_MODE);
+#endif
+ stat = tsmacphyread(PHY_BMSR);
+#ifdef DEBUG
+ printk(TSMAC_NAME ": PHY BMSR %04x\n", stat);
+#endif
+ /* Support for 10baseT modes only */
+ tsmacphywrite(PHY_ANAR, PHY_ANAR_10_FD | PHY_ANAR_10 | PHY_ANAR_SEL_DEF);
+ stat = tsmacphyread(PHY_ANAR);
+#ifdef DEBUG
+ printk(TSMAC_NAME ": PHY ANAR %04x, wrote %04x\n", stat,
+ PHY_ANAR_10_FD | PHY_ANAR_10 | PHY_ANAR_SEL_DEF);
+#endif
+#endif /* TSMAC_FORCE_10BASET */
+ stat = tsmacphyread(PHY_PHYSTS);
+#ifdef DEBUG
+ printk(TSMAC_NAME ": PHY PHYSTS %04x\n", stat);
+#endif
+
+ /* Enable receive and transmit interrupts */
+ tsmacwrite(LM32_TSMAC_INTR_ENB, INTR_ENB |
+ INTR_RX_SMRY | INTR_TX_SMRY |
+ INTR_RX_PKT_RDY | INTR_TX_PKT_SENT);
+}
+
+/*
+ * Initialize and start the device
+ */
+void tsmac_init(void *arg)
+{
+ struct tsmac_softc *tsmac = &tsmac_softc[0];
+ struct ifnet *ifp = &tsmac->arpcom.ac_if;
+
+#ifdef DEBUG
+ printk(TSMAC_NAME ": tsmac_init, tsmac->txDaemonTid = 0x%x\n",
+ tsmac->txDaemonTid);
+#endif
+
+ if (tsmac->txDaemonTid == 0)
+ {
+ /*
+ * Initialize hardware
+ */
+ tsmac_init_hardware(tsmac);
+
+ /*
+ * Start driver tasks
+ */
+ tsmac->txDaemonTid = rtems_bsdnet_newproc ("TSMACtx", 4096,
+ tsmac_txDaemon, tsmac);
+ tsmac->rxDaemonTid = rtems_bsdnet_newproc ("TSMACrx", 4096,
+ tsmac_rxDaemon, tsmac);
+ /*
+ * Setup interrupt handler
+ */
+ set_vector( tsmac_interrupt_handler, TSMAC_VECTOR, 1 );
+
+ /* Interrupt line for TSMAC */
+ lm32_interrupt_unmask(TSMAC_IRQMASK);
+ }
+
+ ifp->if_flags |= IFF_RUNNING;
+
+ /*
+ * Receive broadcast
+ */
+
+ tsmacregwrite(LM32_TSMAC_TX_RX_CTL_BYTE0, TX_RX_CTL_RECEIVE_BRDCST |
+ TX_RX_CTL_RECEIVE_PAUSE);
+
+ /*
+ * Enable transmitter
+ * Flow control enable
+ * Enable receiver
+ */
+
+ tsmacregwrite(LM32_TSMAC_MODE_BYTE0, MODE_TX_EN | MODE_RX_EN | MODE_FC_EN);
+
+ /*
+ * Wake up receive task to receive packets in queue
+ */
+ rtems_event_send(tsmac->rxDaemonTid, INTERRUPT_EVENT);
+}
+
+void tsmac_stop(struct ifnet *ifp)
+{
+ struct tsmac_softc *tsmac = ifp->if_softc;
+
+ /*
+ * Mask tsmac interrupts
+ */
+ lm32_interrupt_mask(TSMAC_IRQMASK);
+
+ ifp->if_flags &= ~IFF_RUNNING;
+
+ /*
+ * Disable transmitter and receiver
+ */
+ tsmacregwrite(LM32_TSMAC_MODE_BYTE0, 0);
+}
+
+/*
+ * Send packet
+ */
+void tsmac_start(struct ifnet *ifp)
+{
+ struct tsmac_softc *tsmac = ifp->if_softc;
+
+ rtems_event_send (tsmac->txDaemonTid, START_TRANSMIT_EVENT);
+ ifp->if_flags |= IFF_OACTIVE;
+}
+
+void tsmac_stats(struct tsmac_softc *tsmac)
+{
+ uint32_t data;
+ int stat;
+
+ /*
+ * Update counters from TSMAC MIB counters
+ */
+
+ tsmac->rxPktIgnore = tsmacread(LM32_TSMAC_RX_PKT_IGNR_CNT);
+ tsmac->rxLenCheckError = tsmacread(LM32_TSMAC_RX_LEN_CHK_ERR_CNT);
+ tsmac->rxLongFrame = tsmacread(LM32_TSMAC_RX_LNG_FRM_CNT);
+ tsmac->rxShortFrame = tsmacread(LM32_TSMAC_RX_SHRT_FRM_CNT);
+ tsmac->rxIPGViolation = tsmacread(LM32_TSMAC_RX_IPG_VIOL_CNT);
+ tsmac->rxCRCError = tsmacread(LM32_TSMAC_RX_CRC_ERR_CNT);
+ tsmac->rxOKPackets = tsmacread(LM32_TSMAC_RX_OK_PKT_CNT);
+ tsmac->rxControlFrame = tsmacread(LM32_TSMAC_RX_CTL_FRM_CNT);
+ tsmac->rxPauseFrame = tsmacread(LM32_TSMAC_RX_PAUSE_FRM_CNT);
+ tsmac->rxMulticast = tsmacread(LM32_TSMAC_RX_MULTICAST_CNT);
+ tsmac->rxBroadcast = tsmacread(LM32_TSMAC_RX_BRDCAST_CNT);
+ tsmac->rxVLANTag = tsmacread(LM32_TSMAC_RX_VLAN_TAG_CNT);
+ tsmac->rxPreShrink = tsmacread(LM32_TSMAC_RX_PRE_SHRINK_CNT);
+ tsmac->rxDribNib = tsmacread(LM32_TSMAC_RX_DRIB_NIB_CNT);
+ tsmac->rxUnsupOPCD = tsmacread(LM32_TSMAC_RX_UNSUP_OPCD_CNT);
+ tsmac->rxByteCnt = tsmacread(LM32_TSMAC_RX_BYTE_CNT);
+
+ tsmac->txUnicast = tsmacread(LM32_TSMAC_TX_UNICAST_CNT);
+ tsmac->txPauseFrame = tsmacread(LM32_TSMAC_TX_PAUSE_FRM_CNT);
+ tsmac->txMulticast = tsmacread(LM32_TSMAC_TX_MULTICAST_CNT);
+ tsmac->txBroadcast = tsmacread(LM32_TSMAC_TX_BRDCAST_CNT);
+ tsmac->txVLANTag = tsmacread(LM32_TSMAC_TX_VLAN_TAG_CNT);
+ tsmac->txBadFCS = tsmacread(LM32_TSMAC_TX_BAD_FCS_CNT);
+ tsmac->txJumboCnt = tsmacread(LM32_TSMAC_TX_JUMBO_CNT);
+ tsmac->txByteCnt = tsmacread(LM32_TSMAC_TX_BYTE_CNT);
+
+ printk("RX Interrupts: %8d", tsmac->rxInterrupts);
+ printk(" RX Len Chk Error: %8d", tsmac->rxLenCheckError);
+ printk(" RX Long Frame: %8d\n", tsmac->rxLongFrame);
+ printk("RX Short Frame: %8d", tsmac->rxShortFrame);
+ printk(" RX IPG Violation: %8d", tsmac->rxIPGViolation);
+ printk(" RX CRC Errors: %8d\n", tsmac->rxCRCError);
+ printk("RX OK Packets: %8d", tsmac->rxOKPackets);
+ printk(" RX Control Frame: %8d", tsmac->rxControlFrame);
+ printk(" RX Pause Frame: %8d\n", tsmac->rxPauseFrame);
+ printk("RX Multicast: %8d", tsmac->rxMulticast);
+ printk(" RX Broadcast: %8d", tsmac->rxBroadcast);
+ printk(" RX VLAN Tag: %8d\n", tsmac->rxVLANTag);
+ printk("RX Pre Shrink: %8d", tsmac->rxPreShrink);
+ printk(" RX Dribb. Nibble: %8d", tsmac->rxDribNib);
+ printk(" RX Unsupp. OPCD: %8d\n", tsmac->rxUnsupOPCD);
+ printk("RX Byte Count: %8d", tsmac->rxByteCnt);
+ printk(" RX FIFO Full: %8d\n", tsmac->rxFifoFull);
+
+ printk("TX Interrupts: %8d", tsmac->txInterrupts);
+ printk(" TX Unicast: %8d", tsmac->txUnicast);
+ printk(" TX Pause Frame: %8d\n", tsmac->txPauseFrame);
+ printk("TX Multicast: %8d", tsmac->txMulticast);
+ printk(" TX Broadcast: %8d", tsmac->txBroadcast);
+ printk(" TX VLAN Tag: %8d\n", tsmac->txVLANTag);
+ printk("TX Bad FSC: %8d", tsmac->txBadFCS);
+ printk(" TX Jumbo Frame: %8d", tsmac->txJumboCnt);
+ printk(" TX Byte Count: %8d\n", tsmac->txByteCnt);
+ printk("TX FIFO Full: %8d\n", tsmac->txFifoFull);
+}
+
+/*
+ * TSMAC ioctl handler
+ */
+
+int tsmac_ioctl(struct ifnet *ifp, ioctl_command_t command, caddr_t data)
+{
+ struct tsmac_softc *tsmac = ifp->if_softc;
+ int error = 0;
+
+ switch (command) {
+ case SIOCGIFADDR:
+ case SIOCSIFADDR:
+ ether_ioctl (ifp, command, data);
+ break;
+
+ case SIOCSIFFLAGS:
+ switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
+ case IFF_RUNNING:
+ tsmac_stop ((struct ifnet *) tsmac);
+ break;
+
+ case IFF_UP:
+ tsmac_init ((struct ifnet *) tsmac);
+ break;
+
+ case IFF_UP | IFF_RUNNING:
+ tsmac_stop ((struct ifnet *) tsmac);
+ tsmac_init ((struct ifnet *) tsmac);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case SIO_RTEMS_SHOW_STATS:
+ tsmac_stats (tsmac);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ return error;
+}
+
+/*
+ * Attach a TSMAC driver
+ */
+int rtems_tsmac_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching)
+{
+ struct tsmac_softc *tsmac;
+ struct ifnet *ifp;
+ int mtu, i;
+ int unit;
+ char *unitName;
+
+ if ((unit = rtems_bsdnet_parse_driver_name(config, &unitName)) < 0)
+ {
+ printk(TSMAC_NAME ": Driver name parsing failed.\n");
+ return 0;
+ }
+
+ if ((unit < 0) || (unit >= TSMAC_NUM))
+ {
+ printk(TSMAC_NAME ": Bad unit number %d.\n", unit);
+ return 0;
+ }
+
+ tsmac = &tsmac_softc[unit];
+
+ ifp = &tsmac->arpcom.ac_if;
+ if (ifp->if_softc != NULL)
+ {
+ printk(TSMAC_NAME ": Driver already in use.\n");
+ return 0;
+ }
+
+ /* Base address for TSMAC */
+ if (config->bpar == 0)
+ {
+ printk(TSMAC_NAME ": Using default base address 0x%08x.\n", TS_MAC_CORE_BASE_ADDRESS);
+ config->bpar = TS_MAC_CORE_BASE_ADDRESS;
+ }
+ tsmac->ioaddr = config->bpar;
+
+ /* Hardware address for TSMAC */
+ if (config->hardware_address == 0)
+ {
+ printk(TSMAC_NAME ": Using default hardware address.\n");
+ tsmac->arpcom.ac_enaddr[0] = TSMAC_MAC0;
+ tsmac->arpcom.ac_enaddr[1] = TSMAC_MAC1;
+ tsmac->arpcom.ac_enaddr[2] = TSMAC_MAC2;
+ tsmac->arpcom.ac_enaddr[3] = TSMAC_MAC3;
+ tsmac->arpcom.ac_enaddr[4] = TSMAC_MAC4;
+ tsmac->arpcom.ac_enaddr[5] = TSMAC_MAC5;
+ }
+ else
+ memcpy(tsmac->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
+
+ printk(TSMAC_NAME ": MAC address ");
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ {
+ printk("%02x", tsmac->arpcom.ac_enaddr[i]);
+ if (i != ETHER_ADDR_LEN-1)
+ printk(":");
+ else
+ printk("\n");
+ }
+
+ if (config->mtu)
+ mtu = config->mtu;
+ else
+ mtu = ETHERMTU;
+
+ /*
+ * Set up network interface values
+ */
+ ifp->if_softc = tsmac;
+ ifp->if_unit = unit;
+ ifp->if_name = unitName;
+ ifp->if_mtu = mtu;
+ ifp->if_init = tsmac_init;
+ ifp->if_ioctl = tsmac_ioctl;
+ ifp->if_start = tsmac_start;
+ ifp->if_output = ether_output;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
+
+ if (ifp->if_snd.ifq_maxlen == 0)
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
+
+ if_attach(ifp);
+ ether_ifattach(ifp);
+}
+
+rtems_isr tsmac_interrupt_handler(rtems_vector_number vector)
+{
+ struct tsmac_softc *tsmac = &tsmac_softc[0];
+ uint32_t irq_stat, rx_stat, tx_stat;
+
+ irq_stat = tsmacread(LM32_TSMAC_INTR_SRC);
+ if (irq_stat & INTR_RX_PKT_RDY)
+ {
+ tsmac->rxInterrupts++;
+ rtems_event_send(tsmac->rxDaemonTid, INTERRUPT_EVENT);
+ }
+
+ if (irq_stat & INTR_TX_PKT_SENT)
+ {
+ tsmac->txInterrupts++;
+ rtems_event_send(tsmac->txDaemonTid, INTERRUPT_EVENT);
+ }
+
+ rx_stat = tsmacread(LM32_TSMAC_RX_STATUS);
+ if (rx_stat & STAT_RX_FIFO_FULL)
+ tsmac->rxFifoFull++;
+
+ tx_stat = tsmacread(LM32_TSMAC_TX_STATUS);
+ if (tx_stat & STAT_TX_FIFO_FULL)
+ tsmac->txFifoFull++;
+
+ lm32_interrupt_ack(TSMAC_IRQMASK);
+}
+
diff --git a/c/src/lib/libbsp/lm32/shared/tsmac/tsmac.h b/c/src/lib/libbsp/lm32/shared/tsmac/tsmac.h
new file mode 100644
index 0000000000..1c7f063bb0
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/tsmac/tsmac.h
@@ -0,0 +1,160 @@
+/*
+ * This file contains definitions for LatticeMico32 TSMAC (Tri-Speed MAC)
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ * Jukka Pietarinen <jukka.pietarinen@mrf.fi>, 2008,
+ * Micro-Research Finland Oy
+ */
+
+#ifndef _BSPTSMAC_H
+#define _BSPTSMAC_H
+
+/* FIFO Registers */
+
+#define LM32_TSMAC_RX_LEN_FIFO (0x000)
+#define LM32_TSMAC_RX_DATA_FIFO (0x004)
+#define LM32_TSMAC_TX_LEN_FIFO (0x008)
+#define LM32_TSMAC_TX_DATA_FIFO (0x00C)
+
+/* Control and Status Registers */
+
+#define LM32_TSMAC_VERID (0x100)
+#define LM32_TSMAC_INTR_SRC (0x104)
+#define INTR_RX_SMRY (0x00020000)
+#define INTR_TX_SMRY (0x00010000)
+#define INTR_RX_FIFO_FULL (0x00001000)
+#define INTR_RX_ERROR (0x00000800)
+#define INTR_RX_FIFO_ERROR (0x00000400)
+#define INTR_RX_FIFO_ALMOST_FULL (0x00000200)
+#define INTR_RX_PKT_RDY (0x00000100)
+#define INTR_TX_FIFO_FULL (0x00000010)
+#define INTR_TX_DISCFRM (0x00000008)
+#define INTR_TX_FIFO_ALMOST_EMPTY (0x00000004)
+#define INTR_TX_FIFO_ALMOST_FULL (0x00000002)
+#define INTR_TX_PKT_SENT (0x00000001)
+#define LM32_TSMAC_INTR_ENB (0x108)
+#define INTR_ENB (0x00040000)
+#define LM32_TSMAC_RX_STATUS (0x10C)
+#define STAT_RX_FIFO_FULL (0x00000010)
+#define STAT_RX_ERROR (0x00000008)
+#define STAT_RX_FIFO_ERROR (0x00000004)
+#define STAT_RX_FIFO_ALMOST_FULL (0x00000002)
+#define STAT_RX_PKT_RDY (0x00000001)
+#define LM32_TSMAC_TX_STATUS (0x110)
+#define STAT_TX_FIFO_FULL (0x00000010)
+#define STAT_TX_DISCFRM (0x00000008)
+#define STAT_TX_FIFO_ALMOST_EMPTY (0x00000004)
+#define STAT_TX_FIFO_ALMOST_FULL (0x00000002)
+#define STAT_TX_PKT_SENT (0x00000001)
+#define LM32_TSMAC_RX_FRAMES_CNT (0x114)
+#define LM32_TSMAC_TX_FRAMES_CNT (0x118)
+#define LM32_TSMAC_RX_FIFO_TH (0x11C)
+#define LM32_TSMAC_TX_FIFO_TH (0x120)
+#define LM32_TSMAC_SYS_CTL (0x124)
+#define SYS_CTL_TX_FIFO_FLUSH (0x00000010)
+#define SYS_CTL_RX_FIFO_FLUSH (0x00000008)
+#define SYS_CTL_TX_SNDPAUSREQ (0x00000004)
+#define SYS_CTL_TX_FIFOCTRL (0x00000002)
+#define SYS_CTL_IGNORE_NEXT_PKT (0x00000001)
+#define LM32_TSMAC_PAUSE_TMR (0x128)
+
+/* Tri-Speed MAC Registers */
+
+#define LM32_TSMAC_MAC_REGS_DATA (0x200)
+#define LM32_TSMAC_MAC_REGS_ADDR_RW (0x204)
+#define REGS_ADDR_WRITE (0x80000000)
+#define LM32_TSMAC_MODE_BYTE0 (0x000)
+#define MODE_TX_EN (1<<3)
+#define MODE_RX_EN (1<<2)
+#define MODE_FC_EN (1<<1)
+#define MODE_GBIT_EN (1<<0)
+#define LM32_TSMAC_TX_RX_CTL_BYTE0 (0x002)
+#define TX_RX_CTL_RECEIVE_SHORT (1<<8)
+#define TX_RX_CTL_RECEIVE_BRDCST (1<<7)
+#define TX_RX_CTL_DIS_RTRY (1<<6)
+#define TX_RX_CTL_HDEN (1<<5)
+#define TX_RX_CTL_RECEIVE_MLTCST (1<<4)
+#define TX_RX_CTL_RECEIVE_PAUSE (1<<3)
+#define TX_RX_CTL_TX_DIS_FCS (1<<2)
+#define TX_RX_CTL_DISCARD_FCS (1<<1)
+#define TX_RX_CTL_PRMS (1<<0)
+#define LM32_TSMAC_MAX_PKT_SIZE_BYTE0 (0x004)
+#define LM32_TSMAC_IPG_VAL_BYTE0 (0x008)
+#define LM32_TSMAC_MAC_ADDR_0_BYTE0 (0x00A)
+#define LM32_TSMAC_MAC_ADDR_1_BYTE0 (0x00C)
+#define LM32_TSMAC_MAC_ADDR_2_BYTE0 (0x00E)
+#define LM32_TSMAC_TX_RX_STS_BYTE0 (0x012)
+#define TX_RX_STS_RX_IDLE (1<<10)
+#define TX_RX_STS_TAGGED_FRAME (1<<9)
+#define TX_RX_STS_BRDCST_FRAME (1<<8)
+#define TX_RX_STS_MULTCST_FRAME (1<<7)
+#define TX_RX_STS_IPG_SHRINK (1<<6)
+#define TX_RX_STS_SHORT_FRAME (1<<5)
+#define TX_RX_STS_LONG_FRAME (1<<4)
+#define TX_RX_STS_ERROR_FRAME (1<<3)
+#define TX_RX_STS_CRC (1<<2)
+#define TX_RX_STS_PAUSE_FRAME (1<<1)
+#define TX_RX_STS_TX_IDLE (1<<0)
+#define LM32_TSMAC_GMII_MNG_CTL_BYTE0 (0x014)
+#define GMII_MNG_CTL_CMD_FIN (1<<14)
+#define GMII_MNG_CTL_READ_PHYREG (0)
+#define GMII_MNG_CTL_WRITE_PHYREG (1<<13)
+#define GMII_MNG_CTL_PHY_ADD_MASK (0x001f)
+#define GMII_MNG_CTL_PHY_ADD_SHIFT (8)
+#define GMII_MNG_CTL_REG_ADD_MASK (0x001f)
+#define GMII_MNG_CTL_REG_ADD_SHIFT (0)
+#define LM32_TSMAC_GMII_MNG_DAT_BYTE0 (0x016)
+#define LM32_TSMAC_MLT_TAB_0_BYTE0 (0x022)
+#define LM32_TSMAC_MLT_TAB_1_BYTE0 (0x024)
+#define LM32_TSMAC_MLT_TAB_2_BYTE0 (0x026)
+#define LM32_TSMAC_MLT_TAB_3_BYTE0 (0x028)
+#define LM32_TSMAC_MLT_TAB_4_BYTE0 (0x02A)
+#define LM32_TSMAC_MLT_TAB_5_BYTE0 (0x02C)
+#define LM32_TSMAC_MLT_TAB_6_BYTE0 (0x02E)
+#define LM32_TSMAC_MLT_TAB_7_BYTE0 (0x030)
+#define LM32_TSMAC_VLAN_TAG_BYTE0 (0x032)
+#define LM32_TSMAC_PAUS_OP_BYTE0 (0x034)
+
+/* Receive Statistics Counters */
+
+#define LM32_TSMAC_RX_PKT_IGNR_CNT (0x300)
+#define LM32_TSMAC_RX_LEN_CHK_ERR_CNT (0x304)
+#define LM32_TSMAC_RX_LNG_FRM_CNT (0x308)
+#define LM32_TSMAC_RX_SHRT_FRM_CNT (0x30C)
+#define LM32_TSMAC_RX_IPG_VIOL_CNT (0x310)
+#define LM32_TSMAC_RX_CRC_ERR_CNT (0x314)
+#define LM32_TSMAC_RX_OK_PKT_CNT (0x318)
+#define LM32_TSMAC_RX_CTL_FRM_CNT (0x31C)
+#define LM32_TSMAC_RX_PAUSE_FRM_CNT (0x320)
+#define LM32_TSMAC_RX_MULTICAST_CNT (0x324)
+#define LM32_TSMAC_RX_BRDCAST_CNT (0x328)
+#define LM32_TSMAC_RX_VLAN_TAG_CNT (0x32C)
+#define LM32_TSMAC_RX_PRE_SHRINK_CNT (0x330)
+#define LM32_TSMAC_RX_DRIB_NIB_CNT (0x334)
+#define LM32_TSMAC_RX_UNSUP_OPCD_CNT (0x338)
+#define LM32_TSMAC_RX_BYTE_CNT (0x33C)
+
+/* Transmit Statistics Counters */
+
+#define LM32_TSMAC_TX_UNICAST_CNT (0x400)
+#define LM32_TSMAC_TX_PAUSE_FRM_CNT (0x404)
+#define LM32_TSMAC_TX_MULTICAST_CNT (0x408)
+#define LM32_TSMAC_TX_BRDCAST_CNT (0x40C)
+#define LM32_TSMAC_TX_VLAN_TAG_CNT (0x410)
+#define LM32_TSMAC_TX_BAD_FCS_CNT (0x414)
+#define LM32_TSMAC_TX_JUMBO_CNT (0x418)
+#define LM32_TSMAC_TX_BYTE_CNT (0x41C)
+
+#ifdef CPU_U32_FIX
+void ipalign(struct mbuf *m);
+#endif
+
+#endif /* _BSPTSMAC_H */