summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/i386
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1999-04-23 16:35:11 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1999-04-23 16:35:11 +0000
commit16a384cfb161f6a3dbcd69fc3b788b6dbc229669 (patch)
treedbbb2e908c64a7f8de5d4c99c16559158b99f1cf /c/src/lib/libbsp/i386
parentAdded lstat(). (diff)
downloadrtems-16a384cfb161f6a3dbcd69fc3b788b6dbc229669.tar.bz2
New BSP from Tony R. Ambardar <tonya@ece.ubc.ca> from the
University of British Columbia. The BSP is for: Yes, this is the "entry model" of a series of boards from Technologic Systems. Costs <$200 I believe. They have a WWW page at www.t-systems.com. I am letting them know about the availability of this BSP too.
Diffstat (limited to 'c/src/lib/libbsp/i386')
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/Makefile.in31
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/README43
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/bsp_specs23
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/clock/Makefile.in70
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/clock/ckinit.c191
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/clock/rtc.c226
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/console/Makefile.in74
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/console/console.c399
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/include/Makefile.in50
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/include/bsp.h186
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/include/coverhd.h104
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/include/wd80x3.h123
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/network/Makefile.in66
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/network/ne2000.c1041
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/start/80386ex.h254
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/start/80386ex.inc252
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/start/Makefile.in72
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/start/macros.inc115
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/start/start.S501
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/start/ts_1325.inc50
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/startup/Makefile.in79
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/startup/README17
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/startup/bspstart.c161
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/startup/linkcmds124
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/startup/setvec.c55
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/timer/Makefile.in70
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/timer/timer.c195
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/timer/timerisr.S40
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/tools/Makefile.in26
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/tools/README68
-rwxr-xr-xc/src/lib/libbsp/i386/ts_386ex/tools/coff2bin23
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/tools/dos_sup/loader.combin0 -> 934 bytes
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/tools/dos_sup/loader_hybrid_com.asm575
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/tools/dos_sup/ts1325.inc48
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/Makefile41
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/Makefile.ts_386ex41
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/i386_ports.adb29
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/i386_ports.ads47
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/init.c86
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-button.adb22
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-button.ads22
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-led.adb46
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-led.ads26
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-parallel.adb13
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-parallel.ads21
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325.ads2
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325_test.adb115
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/wrapup/Makefile.in70
48 files changed, 5933 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/i386/ts_386ex/Makefile.in b/c/src/lib/libbsp/i386/ts_386ex/Makefile.in
new file mode 100644
index 0000000000..29cc2940c6
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/Makefile.in
@@ -0,0 +1,31 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = ../../../../../..
+subdir = c/src/lib/libbsp/i386/ts_386ex
+
+INSTALL = @INSTALL@
+
+RTEMS_ROOT = $(top_srcdir)/@RTEMS_TOPdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+VPATH = @srcdir@
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/directory.cfg
+
+# We only build the Network library if HAS_NETWORKING was defined
+NETWORK_yes_V = network
+NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
+
+# wrapup is the one that actually builds and installs the library
+# from the individual .rel files built in other directories
+SUB_DIRS=include start startup clock console timer $(NETWORK) wrapup
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
diff --git a/c/src/lib/libbsp/i386/ts_386ex/README b/c/src/lib/libbsp/i386/ts_386ex/README
new file mode 100644
index 0000000000..b164be92d0
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/README
@@ -0,0 +1,43 @@
+#
+# $Id$
+#
+
+This BSP is for the Technologic Systems TS-1325, an i386EX PC/AT
+compatible SBC equipped with 2 standard serial ports and a parallel
+port suitable for general digital I/O. It comes with 2MB RAM and 1MB
+Flash ROM. Additional information is available at the TS web site:
+http://www.t-systems.com.
+
+The BSP uses software floating-point emulation, so one must build the
+cross-compilation tools with this support. The BSP also supports the
+on-board RTC, and an NE2000 compatible network card. It has been used
+successfully with C (gcc-2.8.1) and Ada95 (gnat-3.11p), including
+networking applications in both languages.
+
+The TS-1325 runs a version of DOS, and should be configured with a RAM
+disk and Zmodem software (see WWW site). RTEMS executables are loaded
+and run in DOS conventional memory, giving a 600K file-size limit. The
+1MB extended memory is used for the RTEMS workspace, heap, stack and
+BSS. Console output is to COM2 @ 115200 baud, 8-N-1. The high baud
+rate is needed to speed up serial-line Zmodem file transfers. The
+TS-1325 DOS console I/O is by default 9600 baud, and should be changed
+to 115200 baud (see WWW site).
+
+A typical development cycle involves these steps:
+
+1. Cross-compile the application, yielding a COFF executable. Convert this
+ to raw binary format, using objcopy or the coff2bin script (see the
+ tools subdirectory in the BSP).
+
+2. Use Zmodem to download the raw exec to the TS-1325's ram-disk
+ (faster than the A: flash disk). A terminal program supporting
+ Zmodem is needed on the host e.g. minicom under Linux.
+
+3. Use the DOS-based RTEMS loader "loader.com" (see tools
+ subdirectory) to load and run the executable.
+
+Additional documentation and support software is in the tools BSP subdirectory.
+
+Happy Coding!
+
+Tony Ambardar, 4/21/99
diff --git a/c/src/lib/libbsp/i386/ts_386ex/bsp_specs b/c/src/lib/libbsp/i386/ts_386ex/bsp_specs
new file mode 100644
index 0000000000..64ef6d2731
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/bsp_specs
@@ -0,0 +1,23 @@
+%rename cpp old_cpp
+%rename lib old_lib
+%rename endfile old_endfile
+%rename startfile old_startfile
+%rename link old_link
+
+*cpp:
+%(old_cpp) %{qrtems: -D__embedded__} -Asystem(embedded)
+
+*lib:
+%{!qrtems: %(old_lib)} %{qrtems: --start-group \
+%{!qrtems_debug: -lrtemsall} %{qrtems_debug: -lrtemsall_g} \
+-lc -lgcc --end-group \
+%{!qnolinkcmds: -T linkcmds%s}}
+
+*startfile:
+%{!qrtems: %(old_startfile)} %{qrtems: \
+%{!qrtems_debug: start.o%s} \
+%{qrtems_debug: start_g.o%s}}
+
+*link:
+%{!qrtems: %(old_link)} %{qrtems: -dc -dp -N -e _init_i386ex}
+
diff --git a/c/src/lib/libbsp/i386/ts_386ex/clock/Makefile.in b/c/src/lib/libbsp/i386/ts_386ex/clock/Makefile.in
new file mode 100644
index 0000000000..ae44755dc5
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/clock/Makefile.in
@@ -0,0 +1,70 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = ../../../../../../..
+subdir = c/src/lib/libbsp/i386/ts_386ex/clock
+
+INSTALL = @INSTALL@
+
+RTEMS_ROOT = $(top_srcdir)/@RTEMS_TOPdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+VPATH = @srcdir@
+
+PGM=${ARCH}/clock.rel
+
+# C source names, if any, go here -- minus the .c
+C_PIECES=ckinit rtc
+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_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_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
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
diff --git a/c/src/lib/libbsp/i386/ts_386ex/clock/ckinit.c b/c/src/lib/libbsp/i386/ts_386ex/clock/ckinit.c
new file mode 100644
index 0000000000..80b644b5a4
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/clock/ckinit.c
@@ -0,0 +1,191 @@
+/* Clock_initialize
+ *
+ * This routine initializes the Timer/Counter on the Intel
+ * 386ex evaluation board.
+ *
+ * The tick frequency is 1 millisecond.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * 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$
+ */
+
+#include <bsp.h>
+#include <irq.h>
+
+#include <rtems/libio.h>
+
+#include <stdlib.h>
+
+rtems_unsigned32 Clock_isrs; /* ISRs until next tick */
+static rtems_unsigned32 Clock_initial_isr_value;
+
+volatile rtems_unsigned32 Clock_driver_ticks;
+
+void Clock_exit( void );
+
+/*
+ * These are set by clock driver during its init
+ */
+
+rtems_device_major_number rtems_clock_major = ~0;
+rtems_device_major_number rtems_clock_minor = 0;
+
+/*
+ * This is the ISR handler.
+ */
+
+void Clock_isr()
+{
+ /* enable_tracing(); */
+ Clock_driver_ticks += 1;
+ if ( Clock_isrs == 1 ) {
+ rtems_clock_tick();
+ Clock_isrs = Clock_initial_isr_value; /* BSP_Configuration.microseconds_per_tick / 1000;*/
+ }
+ else
+ Clock_isrs -= 1;
+}
+
+void ClockOff(const rtems_irq_connect_data* unused)
+{
+ outport_byte (TIMER_CONFIG, 0x80 ); /* disable the counter timer */
+}
+
+void ClockOn(const rtems_irq_connect_data* unused)
+{
+ outport_byte (TIMER_CONFIG, 0x00 ); /* enable the counter timer */
+}
+
+int ClockIsOn(const rtems_irq_connect_data* unused)
+{
+ return ((i8259s_cache & 0x1) == 0);
+}
+
+static rtems_irq_connect_data clockIrqData = {BSP_PERIODIC_TIMER,
+ Clock_isr,
+ ClockOn,
+ ClockOff,
+ ClockIsOn};
+
+
+rtems_device_driver Clock_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ unsigned timer_counter_init_value;
+ unsigned char clock_lsb, clock_msb;
+
+#ifdef BSP_DEBUG
+ printk("Initializing clock driver in Clock_initialize().\n");
+#endif
+
+#ifdef LOAD_RTC_AT_START
+ /* Initialize clock from on-board real time clock. This breaks the */
+ /* test code which assumes which assumes the application will do it. */
+ {
+ rtems_time_of_day now;
+
+ /* External Prototypes */
+ extern void init_rtc(void); /* defined in 'rtc.c' */
+ extern long rtc_read(rtems_time_of_day *); /* defined in 'rtc.c' */
+
+#ifdef BSP_DEBUG
+ printk("Loading clock from on-board real-time clock.\n");
+#endif
+
+ init_rtc();
+ if (rtc_read(&now) >= 0)
+ rtems_clock_set(&now);
+ }
+#endif
+
+ Clock_driver_ticks = 0;
+
+ Clock_isrs =
+ Clock_initial_isr_value =
+ BSP_Configuration.microseconds_per_tick / 1000; /* ticks per clock_isr */
+
+ /*
+ * configure the counter timer ( should be based on microsecs/tick )
+ * NB. The divisor(Clock_isrs) resolves the is the same number that appears in confdefs.h
+ * when setting the microseconds_per_tick value.
+ */
+ ClockOff ( &clockIrqData );
+
+ timer_counter_init_value = BSP_Configuration.microseconds_per_tick / Clock_isrs;
+ clock_lsb = (unsigned char)timer_counter_init_value;
+ clock_msb = timer_counter_init_value >> 8;
+
+ outport_byte (TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
+ outport_byte (TIMER_CNTR0, clock_lsb ); /* load LSB first */
+ outport_byte (TIMER_CNTR0, clock_msb ); /* then MSB */
+
+ if (!BSP_install_rtems_irq_handler (&clockIrqData)) {
+ printk("Unable to initialize system clock\n");
+ rtems_fatal_error_occurred(1);
+ }
+
+ /*
+ * make major/minor avail to others such as shared memory driver
+ */
+
+ rtems_clock_major = major;
+ rtems_clock_minor = minor;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver Clock_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ 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();
+ }
+ else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
+ {
+ if (!BSP_install_rtems_irq_handler (&clockIrqData)) {
+ printk("Error installing clock interrupt handler!\n");
+ rtems_fatal_error_occurred(1);
+ }
+#ifdef BSP_DEBUG
+ else
+ printk("Clock installed AGAIN\n");
+#endif
+ }
+
+done:
+ return RTEMS_SUCCESSFUL;
+}
+
+void Clock_exit()
+{
+ ClockOff(&clockIrqData);
+ BSP_remove_rtems_irq_handler (&clockIrqData);
+}
diff --git a/c/src/lib/libbsp/i386/ts_386ex/clock/rtc.c b/c/src/lib/libbsp/i386/ts_386ex/clock/rtc.c
new file mode 100644
index 0000000000..14a20e5f3f
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/clock/rtc.c
@@ -0,0 +1,226 @@
+/*-------------------------------------------------------------------------+
+| rtc.c v1.1 - PC386 BSP - 1997/08/07
++--------------------------------------------------------------------------+
+| This file contains the real time clock manipulation package for the
+| PC386 board.
++--------------------------------------------------------------------------+
+| (C) Copyright 1997 -
+| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
+|
+| http://pandora.ist.utl.pt
+|
+| Instituto Superior Tecnico * Lisboa * PORTUGAL
++--------------------------------------------------------------------------+
+| Disclaimer:
+|
+| This file is provided "AS IS" without warranty of any kind, either
+| expressed or implied.
++--------------------------------------------------------------------------+
+| This code is based on:
+| rtc.c,v 1.4 1995/12/19 20:07:15 joel Exp - go32 BSP
+| With the following copyright notice:
+| **************************************************************************
+| * 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 found in the file LICENSE in this distribution or at
+| * http://www.OARcorp.com/rtems/license.html.
+| **************************************************************************
+|
+| $Id$
++--------------------------------------------------------------------------*/
+
+
+#include <string.h>
+
+#include <bsp.h>
+
+/*-------------------------------------------------------------------------+
+| Constants
++--------------------------------------------------------------------------*/
+#define IO_RTC 0x70 /* RTC */
+
+#define RTC_SEC 0x00 /* seconds */
+#define RTC_SECALRM 0x01 /* seconds alarm */
+#define RTC_MIN 0x02 /* minutes */
+#define RTC_MINALRM 0x03 /* minutes alarm */
+#define RTC_HRS 0x04 /* hours */
+#define RTC_HRSALRM 0x05 /* hours alarm */
+#define RTC_WDAY 0x06 /* week day */
+#define RTC_DAY 0x07 /* day of month */
+#define RTC_MONTH 0x08 /* month of year */
+#define RTC_YEAR 0x09 /* month of year */
+#define RTC_STATUSA 0x0a /* status register A */
+#define RTCSA_TUP 0x80 /* time update, don't look now */
+
+#define RTC_STATUSB 0x0b /* status register B */
+
+#define RTC_INTR 0x0c /* status register C (R) interrupt source */
+#define RTCIR_UPDATE 0x10 /* update intr */
+#define RTCIR_ALARM 0x20 /* alarm intr */
+#define RTCIR_PERIOD 0x40 /* periodic intr */
+#define RTCIR_INT 0x80 /* interrupt output signal */
+
+#define RTC_STATUSD 0x0d /* status register D (R) Lost Power */
+#define RTCSD_PWR 0x80 /* clock lost power */
+
+#define RTC_DIAG 0x0e /* status register E - bios diagnostic */
+#define RTCDG_BITS "\020\010clock_battery\007ROM_cksum\006config_unit\005memory_size\004fixed_disk\003invalid_time"
+
+#define RTC_CENTURY 0x32 /* current century - increment in Dec99 */
+
+
+/*-------------------------------------------------------------------------+
+| Auxiliary Functions
++--------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------+
+| Function: bcd
+| Description: Convert 2 digit number to its BCD representation.
+| Global Variables: None.
+| Arguments: i - Number to convert.
+| Returns: BCD representation of number.
++--------------------------------------------------------------------------*/
+static inline rtems_unsigned8
+bcd(rtems_unsigned8 i)
+{
+ return ((i / 16) * 10 + (i % 16));
+} /* bcd */
+
+#define QUICK_READ /* Quick read of the RTC: don't return number of seconds. */
+
+#ifndef QUICK_READ
+
+#define SECS_PER_DAY (24 * 60 * 60)
+#define SECS_PER_REG_YEAR (365 * SECS_PER_DAY)
+
+/*-------------------------------------------------------------------------+
+| Function: ytos
+| Description: Convert years to seconds (since 1970).
+| Global Variables: None.
+| Arguments: y - year to convert (1970 <= y <= 2100).
+| Returns: number of seconds since 1970.
++--------------------------------------------------------------------------*/
+static inline rtems_unsigned32
+ytos(rtems_unsigned16 y)
+{ /* v NUM LEAP YEARS v */
+ return ((y - 1970) * SECS_PER_REG_YEAR + (y - 1970 + 1) / 4 * SECS_PER_DAY);
+} /* ytos */
+
+
+/*-------------------------------------------------------------------------+
+| Function: mtos
+| Description: Convert months to seconds since January.
+| Global Variables: None.
+| Arguments: m - month to convert, leap - is this a month of a leap year.
+| Returns: number of seconds since January.
++--------------------------------------------------------------------------*/
+static inline rtems_unsigned32
+mtos(rtems_unsigned8 m, rtems_boolean leap)
+{
+ static rtems_unsigned16 daysMonth[] = { 0, 0, 31, 59, 90, 120, 151, 181,
+ 212, 243, 273, 304, 334, 365 };
+ /* Days since beginning of year until beginning of month. */
+
+ return ((daysMonth[m] + (leap ? 1 : 0)) * SECS_PER_DAY);
+} /* mtos */
+
+#endif /* QUICK_READ */
+
+/*-------------------------------------------------------------------------+
+| Function: rtcin
+| Description: Perform action on RTC and return its result.
+| Global Variables: None.
+| Arguments: what - what to write to RTC port (what to do).
+| Returns: result received from RTC port after action performed.
++--------------------------------------------------------------------------*/
+static inline rtems_unsigned8
+rtcin(rtems_unsigned8 what)
+{
+ rtems_unsigned8 r;
+
+ outport_byte(IO_RTC, what);
+ inport_byte (IO_RTC+1, r);
+ return r;
+} /* rtcin */
+
+
+/*-------------------------------------------------------------------------+
+| Functions
++--------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------+
+| Function: init_rtc
+| Description: Initialize real-time clock (RTC).
+| Global Variables: None.
+| Arguments: None.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+void
+init_rtc(void)
+{
+ rtems_unsigned8 s;
+
+ /* initialize brain-dead battery powered clock */
+ outport_byte(IO_RTC, RTC_STATUSA);
+ outport_byte(IO_RTC+1, 0x26);
+ outport_byte(IO_RTC, RTC_STATUSB);
+ outport_byte(IO_RTC+1, 2);
+
+ outport_byte(IO_RTC, RTC_DIAG);
+ inport_byte (IO_RTC+1, s);
+ if (s)
+ printk("RTC BIOS diagnostic error %b\n", s);
+
+ /* FIXME: This was last line's original version. How was it supposed to work?
+ printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS); */
+} /* init_rtc */
+
+
+/*-------------------------------------------------------------------------+
+| Function: rtc_read
+| Description: Read present time from RTC and return it.
+| Global Variables: None.
+| Arguments: tod - to return present time in 'rtems_time_of_day' format.
+| Returns: number of seconds from 1970/01/01 corresponding to 'tod'.
++--------------------------------------------------------------------------*/
+long int
+rtc_read(rtems_time_of_day *tod)
+{
+ rtems_unsigned8 sa;
+ rtems_unsigned32 sec = 0;
+
+ memset(tod, 0, sizeof *tod); /* zero tod structure */
+
+ /* do we have a realtime clock present? (otherwise we loop below) */
+ sa = rtcin(RTC_STATUSA);
+ if (sa == 0xff || sa == 0)
+ return -1;
+
+ /* ready for a read? */
+ while ((sa&RTCSA_TUP) == RTCSA_TUP)
+ sa = rtcin(RTC_STATUSA);
+
+ tod->year = bcd(rtcin(RTC_YEAR)) + 1900; /* year */
+ if (tod->year < 1970) tod->year += 100;
+ tod->month = bcd(rtcin(RTC_MONTH)); /* month */
+ tod->day = bcd(rtcin(RTC_DAY)); /* day */
+ (void) bcd(rtcin(RTC_WDAY)); /* weekday */
+ tod->hour = bcd(rtcin(RTC_HRS)); /* hour */
+ tod->minute = bcd(rtcin(RTC_MIN)); /* minutes */
+ tod->second = bcd(rtcin(RTC_SEC)); /* seconds */
+ tod->ticks = 0;
+
+#ifndef QUICK_READ /* Quick read of the RTC: don't return number of seconds. */
+ sec = ytos(tod->year);
+ sec += mtos(tod->month, (tod->year % 4) == 0);
+ sec += tod->day * SECS_PER_DAY;
+ sec += tod->hour * 60 * 60; /* hour */
+ sec += tod->minute * 60; /* minutes */
+ sec += tod->second; /* seconds */
+#endif /* QUICK_READ */
+
+ return (long int)sec;
+} /* rtc_read */
+
+
diff --git a/c/src/lib/libbsp/i386/ts_386ex/console/Makefile.in b/c/src/lib/libbsp/i386/ts_386ex/console/Makefile.in
new file mode 100644
index 0000000000..872b966f52
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/console/Makefile.in
@@ -0,0 +1,74 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = ../../../../../../..
+subdir = c/src/lib/libbsp/i386/ts_386ex/console
+
+INSTALL = @INSTALL@
+
+RTEMS_ROOT = $(top_srcdir)/@RTEMS_TOPdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+VPATH = @srcdir@
+
+PGM=${ARCH}/console.rel
+
+IMPORT_SRC=$(srcdir)/../../shared/io/printk.c
+
+# C source names, if any, go here -- minus the .c
+C_PIECES=console printk
+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_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+DEFINES +=
+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 +=
+
+preinstall:
+ ${CP} ${IMPORT_SRC} .
+
+${PGM}: ${SRCS} ${OBJS}
+ $(make-rel)
+
+all: ${ARCH} preinstall $(SRCS) $(PGM)
+
+# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
+install: all
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
diff --git a/c/src/lib/libbsp/i386/ts_386ex/console/console.c b/c/src/lib/libbsp/i386/ts_386ex/console/console.c
new file mode 100644
index 0000000000..2db6b52bd0
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/console/console.c
@@ -0,0 +1,399 @@
+/*-------------------------------------------------------------------------+
+| console.c v1.1 - i386ex BSP - 1997/08/07
++--------------------------------------------------------------------------+
+| This file contains the i386ex console I/O package. It is just a termios
+| wrapper.
++--------------------------------------------------------------------------+
+| (C) Copyright 1997 -
+| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
+|
+| http://pandora.ist.utl.pt
+|
+| Instituto Superior Tecnico * Lisboa * PORTUGAL
++--------------------------------------------------------------------------+
+| Disclaimer:
+|
+| This file is provided "AS IS" without warranty of any kind, either
+| expressed or implied.
++--------------------------------------------------------------------------+
+| This code is based on:
+| console.c,v 1.4 1995/12/19 20:07:23 joel Exp - go32 BSP
+| console.c,v 1.15 pc386 BSP
+| With the following copyright notice:
+| **************************************************************************
+| * 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 found in the file LICENSE in this distribution or at
+| * http://www.OARcorp.com/rtems/license.html.
+| **************************************************************************
+|
+| $Id$
++--------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+/* workaround for gcc development tools */
+#undef __assert
+void __assert (const char *file, int line, const char *msg);
+
+#include <bsp.h>
+#include <irq.h>
+#include <rtems/libio.h>
+#include <termios.h>
+#include <uart.h>
+#include <libcpu/cpuModel.h>
+
+/*
+ * Possible value for console input/output :
+ * BSP_UART_COM1
+ * BSP_UART_COM2
+ * BSP_CONSOLE_PORT_CONSOLE is not valid in this BSP.
+ * All references to either keyboard or video handling have been removed.
+ */
+
+int BSPConsolePort = BSP_UART_COM2;
+int BSPBaseBaud = 115200;
+int BSP_poll_read(int);
+
+extern BSP_polling_getchar_function_type BSP_poll_char;
+
+static int conSetAttr(int minor, const struct termios *);
+static void isr_on(const rtems_irq_connect_data *);
+static void isr_off(const rtems_irq_connect_data *);
+static int isr_is_on(const rtems_irq_connect_data *);
+
+/*
+ * Change references to com2 if required.
+ */
+
+static rtems_irq_connect_data console_isr_data =
+{ BSP_UART_COM2_IRQ,
+ BSP_uart_termios_isr_com2,
+ isr_on,
+ isr_off,
+ isr_is_on};
+
+static void
+isr_on(const rtems_irq_connect_data *unused)
+{
+ return;
+}
+
+static void
+isr_off(const rtems_irq_connect_data *unused)
+{
+ return;
+}
+
+static int
+isr_is_on(const rtems_irq_connect_data *irq)
+{
+ return BSP_irq_enabled_at_i8259s(irq->name);
+}
+
+void console_reserve_resources(rtems_configuration_table *conf)
+{
+ rtems_termios_reserve_resources(conf, 1);
+ return;
+}
+
+void __assert (const char *file, int line, const char *msg)
+{
+ static char exit_msg[] = "EXECUTIVE SHUTDOWN! Any key to reboot...";
+ unsigned char ch;
+
+ /*
+ * Note we cannot call exit or printf from here,
+ * assert can fail inside ISR too
+ */
+
+ /*
+ * Close console
+ */
+ close(2);
+ close(1);
+ close(0);
+
+ printk("\nassert failed: %s: ", file);
+ printk("%d: ", line);
+ printk("%s\n\n", msg);
+ printk(exit_msg);
+ ch = BSP_poll_char();
+ printk("\nShould jump to reset now!\n");
+}
+
+
+/*-------------------------------------------------------------------------+
+| Console device driver INITIALIZE entry point.
++--------------------------------------------------------------------------+
+| Initilizes the I/O console (keyboard + VGA display) driver.
++--------------------------------------------------------------------------*/
+rtems_device_driver
+console_initialize(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ rtems_status_code status;
+
+ /*
+ * Set up TERMIOS
+ */
+ rtems_termios_initialize ();
+
+ /*
+ * Do device-specific initialization
+ */
+
+ /* 115200-8-N-1, without hardware flow control */
+ BSP_uart_init(BSPConsolePort, 115200, 0);
+
+ /* Set interrupt handler */
+ if(BSPConsolePort == BSP_UART_COM1)
+ {
+ console_isr_data.name = BSP_UART_COM1_IRQ;
+ console_isr_data.hdl = BSP_uart_termios_isr_com1;
+
+ }
+ else
+ {
+ assert(BSPConsolePort == BSP_UART_COM2);
+ console_isr_data.name = BSP_UART_COM2_IRQ;
+ console_isr_data.hdl = BSP_uart_termios_isr_com2;
+ }
+
+ status = BSP_install_rtems_irq_handler(&console_isr_data);
+
+ if (!status){
+ printk("Error installing serial console interrupt handler!\n");
+ rtems_fatal_error_occurred(status);
+ }
+ /*
+ * Register the device
+ */
+ status = rtems_io_register_name ("/dev/console", major, 0);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ printk("Error registering console device!\n");
+ rtems_fatal_error_occurred (status);
+ }
+
+ if(BSPConsolePort == BSP_UART_COM1)
+ {
+ printk("Initialized console on port COM1 115200-8-N-1\n\n");
+ }
+ else
+ {
+ printk("Initialized console on port COM2 115200-8-N-1\n\n");
+ }
+
+ return RTEMS_SUCCESSFUL;
+} /* console_initialize */
+
+
+static int console_open_count = 0;
+
+static int console_last_close(int major, int minor, void *arg)
+{
+ BSP_remove_rtems_irq_handler (&console_isr_data);
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------+
+| Console device driver OPEN entry point
++--------------------------------------------------------------------------*/
+rtems_device_driver
+console_open(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ rtems_status_code status;
+ static rtems_termios_callbacks cb =
+ {
+ NULL, /* firstOpen */
+ console_last_close, /* lastClose */
+ NULL, /* poll read */
+ BSP_uart_termios_write_com2, /* write */
+ conSetAttr, /* setAttributes */
+ NULL, /* stopRemoteTx */
+ NULL, /* startRemoteTx */
+ 1 /* outputUsesInterrupts */
+ };
+
+ if(BSPConsolePort == BSP_UART_COM2)
+ {
+ cb.write = BSP_uart_termios_write_com2;
+ }
+
+ status = rtems_termios_open (major, minor, arg, &cb);
+
+ if(status != RTEMS_SUCCESSFUL)
+ {
+ printk("Error openning console device\n");
+ return status;
+ }
+
+ /*
+ * Pass data area info down to driver
+ */
+ BSP_uart_termios_set(BSPConsolePort,
+ ((rtems_libio_open_close_args_t *)arg)->iop->data1);
+
+ /* Enable interrupts on channel */
+ BSP_uart_intr_ctrl(BSPConsolePort, BSP_UART_INTR_CTRL_TERMIOS);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*-------------------------------------------------------------------------+
+| Console device driver CLOSE entry point
++--------------------------------------------------------------------------*/
+rtems_device_driver
+console_close(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+
+ return (rtems_termios_close (arg));
+
+} /* console_close */
+
+
+/*-------------------------------------------------------------------------+
+| Console device driver READ entry point.
++--------------------------------------------------------------------------+
+| Read characters from the I/O console. We only have stdin.
++--------------------------------------------------------------------------*/
+rtems_device_driver
+console_read(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ rtems_status_code sc;
+
+ sc = rtems_termios_read (arg);
+
+ if ( sc != RTEMS_SUCCESSFUL )
+ printk("console_read: fails %s\n",rtems_status_text(sc));
+
+ return sc;
+
+} /* console_read */
+
+
+/*-------------------------------------------------------------------------+
+| Console device driver WRITE entry point.
++--------------------------------------------------------------------------+
+| Write characters to the I/O console. Stderr and stdout are the same.
++--------------------------------------------------------------------------*/
+rtems_device_driver
+console_write(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg)
+{
+ return rtems_termios_write (arg);
+
+} /* console_write */
+
+
+
+/*
+ * Handle ioctl request.
+ */
+rtems_device_driver
+console_control(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_ioctl (arg);
+}
+
+static int
+conSetAttr(int minor, const struct termios *t)
+{
+ int baud;
+
+ switch (t->c_cflag & CBAUD)
+ {
+ case B50:
+ baud = 50;
+ break;
+ case B75:
+ baud = 75;
+ break;
+ case B110:
+ baud = 110;
+ break;
+ case B134:
+ baud = 134;
+ break;
+ case B150:
+ baud = 150;
+ break;
+ case B200:
+ baud = 200;
+ break;
+ case B300:
+ baud = 300;
+ break;
+ case B600:
+ baud = 600;
+ break;
+ case B1200:
+ baud = 1200;
+ break;
+ case B1800:
+ baud = 1800;
+ break;
+ case B2400:
+ baud = 2400;
+ break;
+ case B4800:
+ baud = 4800;
+ break;
+ case B9600:
+ baud = 9600;
+ break;
+ case B19200:
+ baud = 19200;
+ break;
+ case B38400:
+ baud = 38400;
+ break;
+ case B57600:
+ baud = 57600;
+ break;
+ case B115200:
+ baud = 115200;
+ break;
+ default:
+ baud = 0;
+ rtems_fatal_error_occurred (RTEMS_INTERNAL_ERROR);
+ return 0;
+ }
+
+ BSP_uart_set_baud(BSPConsolePort, baud);
+
+ return 0;
+}
+
+/*
+ * BSP initialization
+ */
+
+BSP_output_char_function_type BSP_output_char =
+ (BSP_output_char_function_type) BSP_output_char_via_serial;
+
+BSP_polling_getchar_function_type BSP_poll_char =
+ (BSP_polling_getchar_function_type) BSP_poll_char_via_serial;
+
+int BSP_poll_read(int ttyMinor){
+
+ return BSP_poll_char_via_serial();
+}
diff --git a/c/src/lib/libbsp/i386/ts_386ex/include/Makefile.in b/c/src/lib/libbsp/i386/ts_386ex/include/Makefile.in
new file mode 100644
index 0000000000..49be342e7a
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/include/Makefile.in
@@ -0,0 +1,50 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = ../../../../../../..
+subdir = c/src/lib/libbsp/i386/ts_386ex/include
+
+INSTALL = @INSTALL@
+
+RTEMS_ROOT = $(top_srcdir)/@RTEMS_TOPdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+VPATH = @srcdir@
+
+# We only install wd80x3.h if HAS_NETWORKING was defined
+NE2000_yes_V = $(srcdir)/wd80x3.h
+NE2000 = $(NE2000_$(HAS_NETWORKING)_V)
+
+H_FILES = $(srcdir)/bsp.h $(srcdir)/coverhd.h $(NE2000)
+
+#
+# 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.
+#
+
+EQ_FILES =
+
+SRCS=$(H_FILES) $(EQ_FILES)
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+
+CLEAN_ADDITIONS +=
+CLOBBER_ADDITIONS +=
+
+all: $(SRCS)
+ $(INSTALL_CHANGE) -m 444 $(H_FILES) $(PROJECT_INCLUDE)
+ $(INSTALL_CHANGE) -m 444 $(EQ_FILES) $(PROJECT_INCLUDE)
+
+install: all
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
diff --git a/c/src/lib/libbsp/i386/ts_386ex/include/bsp.h b/c/src/lib/libbsp/i386/ts_386ex/include/bsp.h
new file mode 100644
index 0000000000..f19341c853
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/include/bsp.h
@@ -0,0 +1,186 @@
+/*
+ * This include file definitions related to an Intel i386ex board.
+ *
+ * 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$
+ */
+
+
+#ifndef __TS386_h
+#define __TS386_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <iosupp.h>
+#include <console.h>
+#include <clockdrv.h>
+#include <bspIo.h>
+#include <irq.h>
+
+/*
+ * Network driver configuration
+ */
+
+struct rtems_bsdnet_ifconfig;
+extern int rtems_ne_driver_attach (struct rtems_bsdnet_ifconfig *config);
+
+extern void Wait_X_ms (unsigned);
+
+#define RTEMS_BSP_NETWORK_DRIVER_NAME "ne1"
+#define RTEMS_BSP_NETWORK_DRIVER_ATTACH rtems_ne_driver_attach
+
+#define NE2000_BYTE_TRANSFERS
+
+/*
+ * Constants relating to the 8254 (or 8253) programmable interval timers.
+ */
+
+#define TIMER_CONFIG 0xF834
+#define IO_TIMER1 0xF040
+
+ /* Port address of the control port and timer channels */
+
+#define TIMER_CNTR0 (IO_TIMER1 + 0) /* timer 0 counter port */
+#define TIMER_CNTR1 (IO_TIMER1 + 1) /* timer 1 counter port */
+#define TIMER_CNTR2 (IO_TIMER1 + 2) /* timer 2 counter port */
+#define TIMER_MODE (IO_TIMER1 + 3) /* timer mode port */
+#define TIMER_SEL0 0x00 /* select counter 0 */
+#define TIMER_SEL1 0x40 /* select counter 1 */
+#define TIMER_SEL2 0x80 /* select counter 2 */
+#define TIMER_INTTC 0x00 /* mode 0, intr on terminal cnt */
+#define TIMER_ONESHOT 0x02 /* mode 1, one shot */
+#define TIMER_RATEGEN 0x04 /* mode 2, rate generator */
+#define TIMER_SQWAVE 0x06 /* mode 3, square wave */
+#define TIMER_SWSTROBE 0x08 /* mode 4, s/w triggered strobe */
+#define TIMER_HWSTROBE 0x0a /* mode 5, h/w triggered strobe */
+#define TIMER_LATCH 0x00 /* latch counter for reading */
+#define TIMER_LSB 0x10 /* r/w counter LSB */
+#define TIMER_MSB 0x20 /* r/w counter MSB */
+#define TIMER_16BIT 0x30 /* r/w counter 16 bits, LSB first */
+#define TIMER_BCD 0x01 /* count in BCD */
+
+/*
+ * Define the time limits for RTEMS Test Suite test durations.
+ * Long test and short test duration limits are provided. These
+ * values are in seconds and need to be converted to ticks for the
+ * application.
+ *
+ */
+
+#define MAX_LONG_TEST_DURATION 300 /* 5 minutes = 300 seconds */
+#define MAX_SHORT_TEST_DURATION 3 /* 3 seconds */
+
+/*
+ * Define the interrupt mechanism for Time Test 27
+ *
+ * NOTE: Use a software interrupt for the i386.
+ */
+
+#define MUST_WAIT_FOR_INTERRUTPT 0
+
+
+#define Install_tm27_vector(handler) \
+{ \
+ rtems_isr_entry dummy; \
+ rtems_interrupt_catch(handler, 0x90, &dummy); \
+}
+#define Cause_tm27_intr() asm volatile( "int $0x90" : : );
+
+#define Clear_tm27_intr()
+
+#define Lower_tm27_intr()
+
+/*
+ * Simple spin delay in microsecond units for device drivers.
+ * This is very dependent on the clock speed of the target.
+ */
+
+#define delay( _microseconds ) \
+ { \
+ rtems_unsigned32 _counter; \
+ \
+ _counter = (_microseconds); \
+ \
+ asm volatile ( "0: nop;" \
+ " mov %0,%0 ;" \
+ " loop 0b" : "=c" (_counter) \
+ : "0" (_counter) \
+ ); \
+ \
+ }
+
+/* Constants */
+
+#define RAM_START 0
+
+/* replaced the earlier EI kludge of 0xfffff */
+
+#define RAM_END 0x200000
+
+/* I/O addressing */
+
+/*
+ *#define Is_tx_ready( _status ) ( (_status) & 0x20 )
+ */
+/* dec 20. try the TE instead of TBE as the check */
+
+#define Is_tx_ready( _status ) ( (_status) & 0x40 )
+
+
+#define Is_rx_ready( _status ) ( (_status) & 0x01 )
+
+/* Structures */
+
+#ifdef F386_INIT
+#undef BSP_EXTERN
+#define BSP_EXTERN
+#else
+#undef BSP_EXTERN
+#define BSP_EXTERN extern
+#endif
+
+/*
+ * Device Driver Table Entries
+ */
+
+/*
+ * NOTE: Use the standard Console driver entry
+ */
+
+/*
+ * NOTE: Use the standard Clock driver entry
+ */
+
+/* miscellaneous stuff assumed to exist */
+
+extern rtems_configuration_table BSP_Configuration;
+
+#define IDT_SIZE 256
+#define GDT_SIZE 3
+
+extern interrupt_gate_descriptor Interrupt_descriptor_table[IDT_SIZE];
+extern segment_descriptors Global_descriptor_table [GDT_SIZE];
+
+BSP_EXTERN unsigned short Idt[3]; /* Interrupt Descriptor Table Address */
+BSP_EXTERN unsigned short Gdt[3]; /* Global Descriptor Table Address */
+BSP_EXTERN unsigned int Idt_base;
+BSP_EXTERN unsigned int Gdt_base;
+
+/* routines */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/c/src/lib/libbsp/i386/ts_386ex/include/coverhd.h b/c/src/lib/libbsp/i386/ts_386ex/include/coverhd.h
new file mode 100644
index 0000000000..de5e7aa742
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/include/coverhd.h
@@ -0,0 +1,104 @@
+/* coverhd.h
+ *
+ * This include file has defines to represent the overhead associated
+ * with calling a particular directive from C on this target.
+ *
+ * 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$
+ */
+
+#ifndef __COVERHD_h
+#define __COVERHD_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CALLING_OVERHEAD_INITIALIZE_EXECUTIVE 3
+#define CALLING_OVERHEAD_SHUTDOWN_EXECUTIVE 3
+#define CALLING_OVERHEAD_TASK_CREATE 4
+#define CALLING_OVERHEAD_TASK_IDENT 4
+#define CALLING_OVERHEAD_TASK_START 4
+#define CALLING_OVERHEAD_TASK_RESTART 3
+#define CALLING_OVERHEAD_TASK_DELETE 3
+#define CALLING_OVERHEAD_TASK_SUSPEND 3
+#define CALLING_OVERHEAD_TASK_RESUME 3
+#define CALLING_OVERHEAD_TASK_SET_PRIORITY 4
+#define CALLING_OVERHEAD_TASK_MODE 4
+#define CALLING_OVERHEAD_TASK_GET_NOTE 4
+#define CALLING_OVERHEAD_TASK_SET_NOTE 4
+#define CALLING_OVERHEAD_TASK_WAKE_WHEN 7
+#define CALLING_OVERHEAD_TASK_WAKE_AFTER 3
+#define CALLING_OVERHEAD_INTERRUPT_CATCH 4
+#define CALLING_OVERHEAD_CLOCK_GET 7
+#define CALLING_OVERHEAD_CLOCK_SET 7
+#define CALLING_OVERHEAD_CLOCK_TICK 2
+
+#define CALLING_OVERHEAD_TIMER_CREATE 3
+#define CALLING_OVERHEAD_TIMER_IDENT 3
+#define CALLING_OVERHEAD_TIMER_DELETE 3
+#define CALLING_OVERHEAD_TIMER_FIRE_AFTER 4
+#define CALLING_OVERHEAD_TIMER_FIRE_WHEN 8
+#define CALLING_OVERHEAD_TIMER_RESET 3
+#define CALLING_OVERHEAD_TIMER_CANCEL 3
+#define CALLING_OVERHEAD_SEMAPHORE_CREATE 4
+#define CALLING_OVERHEAD_SEMAPHORE_DELETE 3
+#define CALLING_OVERHEAD_SEMAPHORE_IDENT 4
+#define CALLING_OVERHEAD_SEMAPHORE_OBTAIN 4
+#define CALLING_OVERHEAD_SEMAPHORE_RELEASE 3
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_CREATE 4
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_IDENT 4
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_DELETE 3
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_SEND 3
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_URGENT 3
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_BROADCAST 4
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_RECEIVE 4
+#define CALLING_OVERHEAD_MESSAGE_QUEUE_FLUSH 3
+
+#define CALLING_OVERHEAD_EVENT_SEND 4
+#define CALLING_OVERHEAD_EVENT_RECEIVE 4
+#define CALLING_OVERHEAD_SIGNAL_CATCH 3
+#define CALLING_OVERHEAD_SIGNAL_SEND 3
+#define CALLING_OVERHEAD_PARTITION_CREATE 4
+#define CALLING_OVERHEAD_PARTITION_IDENT 4
+#define CALLING_OVERHEAD_PARTITION_DELETE 3
+#define CALLING_OVERHEAD_PARTITION_GET_BUFFER 4
+#define CALLING_OVERHEAD_PARTITION_RETURN_BUFFER 4
+#define CALLING_OVERHEAD_REGION_CREATE 4
+#define CALLING_OVERHEAD_REGION_IDENT 3
+#define CALLING_OVERHEAD_REGION_DELETE 3
+#define CALLING_OVERHEAD_REGION_GET_SEGMENT 4
+#define CALLING_OVERHEAD_REGION_RETURN_SEGMENT 4
+#define CALLING_OVERHEAD_PORT_CREATE 4
+#define CALLING_OVERHEAD_PORT_IDENT 3
+#define CALLING_OVERHEAD_PORT_DELETE 3
+#define CALLING_OVERHEAD_PORT_EXTERNAL_TO_INTERNAL 4
+#define CALLING_OVERHEAD_PORT_INTERNAL_TO_EXTERNAL 4
+
+#define CALLING_OVERHEAD_IO_INITIALIZE 4
+#define CALLING_OVERHEAD_IO_OPEN 4
+#define CALLING_OVERHEAD_IO_CLOSE 4
+#define CALLING_OVERHEAD_IO_READ 4
+#define CALLING_OVERHEAD_IO_WRITE 4
+#define CALLING_OVERHEAD_IO_CONTROL 4
+#define CALLING_OVERHEAD_FATAL_ERROR_OCCURRED 3
+#define CALLING_OVERHEAD_RATE_MONOTONIC_CREATE 3
+#define CALLING_OVERHEAD_RATE_MONOTONIC_IDENT 3
+#define CALLING_OVERHEAD_RATE_MONOTONIC_DELETE 3
+#define CALLING_OVERHEAD_RATE_MONOTONIC_CANCEL 3
+#define CALLING_OVERHEAD_RATE_MONOTONIC_PERIOD 3
+#define CALLING_OVERHEAD_MULTIPROCESSING_ANNOUNCE 2
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/c/src/lib/libbsp/i386/ts_386ex/include/wd80x3.h b/c/src/lib/libbsp/i386/ts_386ex/include/wd80x3.h
new file mode 100644
index 0000000000..4bad00993c
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/include/wd80x3.h
@@ -0,0 +1,123 @@
+
+/* Register descriptions */
+/* Controller DP8390. */
+
+#define DATAPORT 0x10 /* Port Window. */
+#define RESET 0x1f /* Issue a read for reset */
+#define W83CREG 0x00 /* I/O port definition */
+#define ADDROM 0x08
+
+/* page 0 read or read/write registers */
+
+#define CMDR 0x00+RO
+#define CLDA0 0x01+RO /* current local dma addr 0 for read */
+#define CLDA1 0x02+RO /* current local dma addr 1 for read */
+#define BNRY 0x03+RO /* boundary reg for rd and wr */
+#define TSR 0x04+RO /* tx status reg for rd */
+#define NCR 0x05+RO /* number of collision reg for rd */
+#define FIFO 0x06+RO /* FIFO for rd */
+#define ISR 0x07+RO /* interrupt status reg for rd and wr */
+#define CRDA0 0x08+RO /* current remote dma address 0 for rd */
+#define CRDA1 0x09+RO /* current remote dma address 1 for rd */
+#define RSR 0x0C+RO /* rx status reg for rd */
+#define CNTR0 0x0D+RO /* tally cnt 0 for frm alg err for rd */
+#define CNTR1 RO+0x0E /* tally cnt 1 for crc err for rd */
+#define CNTR2 0x0F+RO /* tally cnt 2 for missed pkt for rd */
+
+/* page 0 write registers */
+
+#define PSTART 0x01+RO /* page start register */
+#define PSTOP 0x02+RO /* page stop register */
+#define TPSR 0x04+RO /* tx start page start reg */
+#define TBCR0 0x05+RO /* tx byte count 0 reg */
+#define TBCR1 0x06+RO /* tx byte count 1 reg */
+#define RSAR0 0x08+RO /* remote start address reg 0 */
+#define RSAR1 0x09+RO /* remote start address reg 1 */
+#define RBCR0 0x0A+RO /* remote byte count reg 0 */
+#define RBCR1 0x0B+RO /* remote byte count reg 1 */
+#define RCR 0x0C+RO /* rx configuration reg */
+#define TCR 0x0D+RO /* tx configuration reg */
+#define DCR RO+0x0E /* data configuration reg */
+#define IMR 0x0F+RO /* interrupt mask reg */
+
+/* page 1 registers */
+
+#define PAR 0x01+RO /* physical addr reg base for rd and wr */
+#define CURR 0x07+RO /* current page reg for rd and wr */
+#define MAR 0x08+RO /* multicast addr reg base fro rd and WR */
+#define MARsize 8 /* size of multicast addr space */
+
+/*-----W83CREG command bits-----*/
+#define MSK_RESET 0x80 /* W83CREG masks */
+#define MSK_ENASH 0x40
+#define MSK_DECOD 0x3F /* memory decode bits, corresponding */
+ /* to SA 18-13. SA 19 assumed to be 1 */
+
+/*-----CMDR command bits-----*/
+#define MSK_STP 0x01 /* stop the chip */
+#define MSK_STA 0x02 /* start the chip */
+#define MSK_TXP 0x04 /* initial txing of a frm */
+#define MSK_RRE 0x08 /* remote read */
+#define MSK_RWR 0x10 /* remote write */
+#define MSK_RD2 0x20 /* no DMA used */
+#define MSK_PG0 0x00 /* select register page 0 */
+#define MSK_PG1 0x40 /* select register page 1 */
+#define MSK_PG2 0x80 /* select register page 2 */
+
+/*-----ISR and TSR status bits-----*/
+#define MSK_PRX 0x01 /* rx with no error */
+#define MSK_PTX 0x02 /* tx with no error */
+#define MSK_RXE 0x04 /* rx with error */
+#define MSK_TXE 0x08 /* tx with error */
+#define MSK_OVW 0x10 /* overwrite warning */
+#define MSK_CNT 0x20 /* MSB of one of the tally counters is set */
+#define MSK_RDC 0x40 /* remote dma completed */
+#define MSK_RST 0x80 /* reset state indicator */
+
+/*-----DCR command bits-----*/
+#define MSK_WTS 0x01 /* word transfer mode selection */
+#define MSK_BOS 0x02 /* byte order selection */
+#define MSK_LAS 0x04 /* long addr selection */
+#define MSK_BMS 0x08 /* burst mode selection */
+#define MSK_ARM 0x10 /* autoinitialize remote */
+#define MSK_FT00 0x00 /* burst lrngth selection */
+#define MSK_FT01 0x20 /* burst lrngth selection */
+#define MSK_FT10 0x40 /* burst lrngth selection */
+#define MSK_FT11 0x60 /* burst lrngth selection */
+
+/*-----RCR command bits-----*/
+#define MSK_SEP 0x01 /* save error pkts */
+#define MSK_AR 0x02 /* accept runt pkt */
+#define MSK_AB 0x04 /* 8390 RCR */
+#define MSK_AM 0x08 /* accept multicast */
+#define MSK_PRO 0x10 /* accept all pkt with physical adr */
+#define MSK_MON 0x20 /* monitor mode */
+
+/*-----TCR command bits-----*/
+#define MSK_CRC 0x01 /* inhibit CRC, do not append crc */
+#define MSK_LOOP 0x02 /* set loopback mode */
+#define MSK_BCST 0x04 /* Accept broadcasts */
+#define MSK_LB01 0x06 /* encoded loopback control */
+#define MSK_ATD 0x08 /* auto tx disable */
+#define MSK_OFST 0x10 /* collision offset enable */
+
+/*-----receive status bits-----*/
+#define SMK_PRX 0x01 /* rx without error */
+#define SMK_CRC 0x02 /* CRC error */
+#define SMK_FAE 0x04 /* frame alignment error */
+#define SMK_FO 0x08 /* FIFO overrun */
+#define SMK_MPA 0x10 /* missed pkt */
+#define SMK_PHY 0x20 /* physical/multicase address */
+#define SMK_DIS 0x40 /* receiver disable. set in monitor mode */
+#define SMK_DEF 0x80 /* deferring */
+
+/*-----transmit status bits-----*/
+#define SMK_PTX 0x01 /* tx without error */
+#define SMK_DFR 0x02 /* non deferred tx */
+#define SMK_COL 0x04 /* tx collided */
+#define SMK_ABT 0x08 /* tx abort because of excessive collisions */
+#define SMK_CRS 0x10 /* carrier sense lost */
+#define SMK_FU 0x20 /* FIFO underrun */
+#define SMK_CDH 0x40 /* collision detect heartbeat */
+#define SMK_OWC 0x80 /* out of window collision */
+
diff --git a/c/src/lib/libbsp/i386/ts_386ex/network/Makefile.in b/c/src/lib/libbsp/i386/ts_386ex/network/Makefile.in
new file mode 100644
index 0000000000..62b211072f
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/network/Makefile.in
@@ -0,0 +1,66 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = ../../../../../../..
+subdir = c/src/lib/libbsp/i386/ts_386ex/network
+
+INSTALL = @INSTALL@
+
+RTEMS_ROOT = $(top_srcdir)/@RTEMS_TOPdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+VPATH = @srcdir@
+
+PGM=${ARCH}/network.rel
+
+# C source names, if any, go here -- minus the .c
+C_PIECES=ne2000
+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_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+DEFINES += -D_COMPILING_BSD_KERNEL_ -DKERNEL -DINET -DNFS \
+ -DDIAGNOSTIC -DBOOTP_COMPAT
+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
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
diff --git a/c/src/lib/libbsp/i386/ts_386ex/network/ne2000.c b/c/src/lib/libbsp/i386/ts_386ex/network/ne2000.c
new file mode 100644
index 0000000000..666653f421
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/network/ne2000.c
@@ -0,0 +1,1041 @@
+/* ne2k.c -- RTEMS NE2000 Ethernet driver.
+ * Written by Ian Lance Taylor, Zembu Labs.
+ * October, 1998.
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ *
+ * Both the ne2000 and the wd80x3 are based on the National Semiconductor
+ * 8390 chip, so there is a fair amount of overlap between the two
+ * drivers. It would be possible in principle to combine some code into
+ * a separate set of subroutines called by both. In fact, the drivers in
+ * both OpenBSD and Linux work this way. I didn't bother, because for
+ * the relatively simple drivers used by RTEMS, the overlap is not
+ * especially large, and any reasonable use of subroutines would lead to
+ * slightly less efficient code.
+
+ * This ne2000 driver uses two transmit buffers. While one packet is
+ * being transmitted over the Ethernet, RTEMS will upload another. Since
+ * uploading a packet to the ne2000 is rather slow, I don't think there
+ * is any point to having more than two transmit buffers. However, the
+ * code does make it possible, by changing NE_TX_BUFS, although that
+ * would of course reduce the number of receive buffers.
+ *
+ * I suspect that the wd80x3 driver would benefit slightly from copying
+ * the multiple transmit buffer code. However, I have no way to test
+ * that.
+ */
+
+#include <bsp.h>
+#include <wd80x3.h>
+
+#include <stdio.h>
+#include <assert.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 <irq.h>
+
+/* Define this to force byte-wide data transfers with the NIC. This
+ is needed for boards like the TS-1325 386EX PC, which support only
+ an 8-bit PC/104 bus. Undefine this on a normal PC.*/
+
+/* #define NE2000_BYTE_TRANSFERS */
+
+/* Define this to print debugging messages with printk. */
+
+/* #define DEBUG_NE2000 */
+
+/* We expect to be able to read a complete packet into an mbuf. */
+
+#if (MCLBYTES < 1520)
+# error "Driver must have MCLBYTES >= 1520"
+#endif
+
+/* The 8390 macro definitions in wd80x3.h expect RO to be defined. */
+#define RO 0
+
+/* Minimum size of Ethernet packet. */
+#define ET_MINLEN 60
+
+/* The number of NE2000 devices supported by this driver. */
+
+#define NNEDRIVER 1
+
+/* RTEMS event number used by the interrupt handler to signal the
+ driver task. This must not be any of the events used by the
+ network task synchronization. */
+#define INTERRUPT_EVENT RTEMS_EVENT_1
+
+/* RTEMS event number used to start the transmit daemon. This must
+ not be the same as INTERRUPT_EVENT. */
+#define START_TRANSMIT_EVENT RTEMS_EVENT_2
+
+/* Interrupts we want to handle from the device. */
+
+#define NE_INTERRUPTS \
+ (MSK_PRX | MSK_PTX | MSK_RXE | MSK_TXE | MSK_OVW | MSK_CNT)
+
+/* The size of a page in device memory. */
+
+#define NE_PAGE_SIZE (256)
+
+/* The first page address in device memory. */
+
+#define NE_START_PAGE (0x40)
+
+/* The last page address, plus 1. */
+
+#define NE_STOP_PAGE (0x80)
+
+/* The number of pages used for a single transmit buffer. This is
+ 1536 bytes, enough for a full size packet. */
+
+#define NE_TX_PAGES (6)
+
+/* The number of transmit buffers. We use two, so we can load one
+ packet while the other is being sent. */
+
+#define NE_TX_BUFS (2)
+
+/* We use the first pages in memory as transmit buffers, and the
+ remaining ones as receive buffers. */
+
+#define NE_FIRST_TX_PAGE (NE_START_PAGE)
+
+#define NE_FIRST_RX_PAGE (NE_FIRST_TX_PAGE + NE_TX_PAGES * NE_TX_BUFS)
+
+/* Data we store for each NE2000 device. */
+
+struct ne_softc {
+ /* The bsdnet information structure. */
+ struct arpcom arpcom;
+
+ /* The interrupt request number. */
+ unsigned int irno;
+ /* The base IO port number. */
+ unsigned int port;
+
+ /* Whether we accept broadcasts. */
+ int accept_broadcasts;
+
+ /* The thread ID of the transmit task. */
+ rtems_id tx_daemon_tid;
+ /* The thread ID of the receive task. */
+ rtems_id rx_daemon_tid;
+
+ /* Whether we use byte-transfers with the device. */
+ rtems_boolean byte_transfers;
+
+ /* The number of memory buffers which the transmit daemon has loaded
+ with data to be sent, but which have not yet been completely
+ sent. */
+ int inuse;
+ /* The index of the next available transmit memory buffer. */
+ int nextavail;
+ /* The index of the next transmit buffer to send. */
+ int nextsend;
+ /* Nonzero if the device is currently transmitting a packet. */
+ int transmitting;
+ /* The length of the data stored in each transmit buffer. */
+ int sendlen[NE_TX_BUFS];
+
+ /* Set if we have a packet overrun while receiving. */
+ int overrun;
+ /* Set if we should resend after an overrun. */
+ int resend;
+
+ /* Statistics. */
+ struct {
+ /* Number of packets received. */
+ unsigned long rx_packets;
+ /* Number of packets sent. */
+ unsigned long tx_packets;
+ /* Number of interrupts. */
+ unsigned long interrupts;
+ /* Number of receive acknowledgements. */
+ unsigned long rx_acks;
+ /* Number of transmit acknowledgements. */
+ unsigned long tx_acks;
+ /* Number of packet overruns. */
+ unsigned long overruns;
+ /* Number of frame errors. */
+ unsigned long rx_frame_errors;
+ /* Number of CRC errors. */
+ unsigned long rx_crc_errors;
+ /* Number of missed packets. */
+ unsigned long rx_missed_errors;
+ } stats;
+};
+
+/* The list of NE2000 devices on this system. */
+
+static struct ne_softc ne_softc[NNEDRIVER];
+
+/* Find the NE2000 device which is attached at a particular interrupt
+ vector. */
+
+static struct ne_softc *
+ne_device_for_irno (int irno)
+{
+ int i;
+
+ for (i = 0; i < NNEDRIVER; ++i)
+ {
+ if (ne_softc[i].irno == irno
+ && ne_softc[i].arpcom.ac_if.if_softc != NULL)
+ return &ne_softc[i];
+ }
+
+ return NULL;
+}
+
+/* Read data from an NE2000 device. Read LEN bytes at ADDR, storing
+ them into P. */
+
+static void
+ne_read_data (struct ne_softc *sc, int addr, int len, unsigned char *p)
+{
+ unsigned int port = sc->port;
+ unsigned int dport = port + DATAPORT;
+
+ outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STA);
+ outport_byte (port + RBCR0, len);
+ outport_byte (port + RBCR1, len >> 8);
+ outport_byte (port + RSAR0, addr);
+ outport_byte (port + RSAR1, addr >> 8);
+ outport_byte (port + CMDR, MSK_PG0 | MSK_RRE | MSK_STA);
+
+ if (sc->byte_transfers)
+ while (len > 0) {
+ unsigned char d;
+
+ inport_byte (dport, d);
+ *p++ = d;
+ len--;
+ }
+ else /* word transfers */
+ while (len > 0) {
+ unsigned short d;
+
+ inport_word (dport, d);
+ *p++ = d;
+ *p++ = d >> 8;
+ len -= 2;
+ }
+
+ outport_byte (port + ISR, MSK_RDC);
+}
+
+/* Handle the current NE2000 status. This is called when the device
+ signals an interrupt. It is also called at other times while
+ NE2000 interrupts have been disabled. */
+
+static void
+ne_check_status (struct ne_softc *sc)
+{
+ unsigned int port = sc->port;
+ unsigned char status;
+
+ /* It seems that we need to use a loop here, because if the NE2000
+ signals an interrupt because packet transmission is complete, and
+ then receives a packet while interrupts are disabled, it seems to
+ sometimes fail to signal the interrupt for the received packet
+ when interrupts are reenabled. (Based on the behaviour of the
+ Realtek 8019AS chip). */
+
+ while (1) {
+ inport_byte (port + ISR, status);
+ if (status == 0)
+ break;
+
+#ifdef DEBUG_NE2000
+ printk ("NE2000 status 0x%x (8259 enabled: %s; mask: %x)\n", status,
+ i8259s_cache & (1 << sc->irno) ? "no" : "yes",
+ i8259s_cache);
+#endif
+
+ /* Check for incoming packet overwrite. */
+ if (status & MSK_OVW) {
+ unsigned char status2;
+
+ ++sc->stats.overruns;
+ outport_byte (port + CMDR, MSK_PG0 | MSK_STP | MSK_RD2);
+ Wait_X_ms (2);
+ outport_byte (port + RBCR0, 0);
+ outport_byte (port + RBCR1, 0);
+ inport_byte (port + ISR, status2);
+ status |= status2 & (MSK_PTX | MSK_TXE);
+ outport_byte (port + TCR, MSK_LOOP);
+ outport_byte (port + CMDR, MSK_PG0 | MSK_STA | MSK_RD2);
+ sc->overrun = 1;
+ if ((status & (MSK_PTX | MSK_TXE)) == 0)
+ sc->resend = 1;
+ rtems_event_send (sc->rx_daemon_tid, INTERRUPT_EVENT);
+ }
+
+ /* Check for transmitted packet. The transmit daemon may now be
+ able to send another packet to the device. */
+ if ((status & (MSK_PTX | MSK_TXE)) != 0) {
+ ++sc->stats.tx_acks;
+ outport_byte (port + ISR, status & (MSK_PTX | MSK_TXE));
+ --sc->inuse;
+ sc->transmitting = 0;
+ if (sc->inuse > 0 || (sc->arpcom.ac_if.if_flags & IFF_OACTIVE) != 0)
+ rtems_event_send (sc->tx_daemon_tid, START_TRANSMIT_EVENT);
+ }
+
+ /* Check for received packet. */
+ if ((status & (MSK_PRX | MSK_RXE)) != 0) {
+ ++sc->stats.rx_acks;
+ outport_byte (port + ISR, status & (MSK_PRX | MSK_RXE));
+ rtems_event_send (sc->rx_daemon_tid, INTERRUPT_EVENT);
+ }
+
+ /* Check for counter change. */
+ if ((status & MSK_CNT) != 0) {
+ unsigned char add;
+
+ inport_byte (port + CNTR0, add);
+ sc->stats.rx_frame_errors += add;
+ inport_byte (port + CNTR1, add);
+ sc->stats.rx_crc_errors += add;
+ inport_byte (port + CNTR2, add);
+ sc->stats.rx_missed_errors += add;
+ outport_byte (port + ISR, MSK_CNT);
+ }
+ }
+
+ outport_byte (port + CMDR, MSK_PG0 | MSK_STA | MSK_RD2);
+}
+
+/* Handle an NE2000 interrupt. */
+
+static rtems_isr
+ne_interrupt_handler (rtems_vector_number v)
+{
+ struct ne_softc *sc;
+
+ sc = ne_device_for_irno (v);
+ if (sc == NULL)
+ return;
+
+ ++sc->stats.interrupts;
+
+ ne_check_status (sc);
+}
+
+/* Turn NE2000 interrupts on. */
+
+static void
+ne_interrupt_on (const rtems_irq_connect_data *irq)
+{
+ struct ne_softc *sc;
+
+#ifdef DEBUG_NE2000
+ printk ("ne_interrupt_on\n");
+#endif
+ sc = ne_device_for_irno (irq->name);
+ if (sc != NULL)
+ outport_byte (sc->port + IMR, NE_INTERRUPTS);
+}
+
+/* Turn NE2000 interrupts off. See ne_interrupt_on. */
+
+static void
+ne_interrupt_off (const rtems_irq_connect_data *irq)
+{
+ struct ne_softc *sc;
+
+#ifdef DEBUG_NE2000
+ printk ("ne_interrupt_off\n");
+#endif
+ sc = ne_device_for_irno (irq->name);
+ if (sc != NULL)
+ outport_byte (sc->port + IMR, 0);
+}
+
+/* Return whether NE2000 interrupts are on. */
+
+static int
+ne_interrupt_is_on (const rtems_irq_connect_data *irq)
+{
+ return BSP_irq_enabled_at_i8259s (irq->name);
+}
+
+/* Initialize the NE2000 hardware. */
+
+static void
+ne_init_hardware (struct ne_softc *sc)
+{
+ unsigned int port = sc->port;
+ int i;
+ rtems_irq_connect_data irq;
+
+#ifdef DEBUG_NE2000
+ printk ("ne_init_hardware\n");
+#endif
+
+ /* Initialize registers. */
+
+ outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP);
+
+ if (sc->byte_transfers) {
+ outport_byte (port + DCR, MSK_FT10 | MSK_BMS);
+ }
+ else {
+ outport_byte (port + DCR, MSK_FT10 | MSK_BMS | MSK_WTS);
+ }
+
+ outport_byte (port + RBCR0, 0);
+ outport_byte (port + RBCR1, 0);
+ outport_byte (port + RCR, MSK_MON);
+ outport_byte (port + TCR, MSK_LOOP);
+ outport_byte (port + IMR, 0);
+ outport_byte (port + ISR, 0xff);
+ outport_byte (port + PSTOP, NE_STOP_PAGE);
+ outport_byte (port + PSTART, NE_FIRST_RX_PAGE);
+ outport_byte (port + BNRY, NE_STOP_PAGE - 1);
+
+ /* Set the Ethernet hardware address. */
+
+ outport_byte (port + CMDR, MSK_PG1 | MSK_RD2);
+ for (i = 0; i < ETHER_ADDR_LEN; ++i)
+ outport_byte (port + PAR + i, sc->arpcom.ac_enaddr[i]);
+
+#ifdef DEBUG_NE2000
+ printk ("Using ethernet address: ");
+ for (i = 0; i < ETHER_ADDR_LEN; ++i)
+ printk("%x ",sc->arpcom.ac_enaddr[i]);
+ printk ("\n");
+#endif
+
+ /* Clear the multicast address. */
+ for (i = 0; i < MARsize; ++i)
+ outport_byte (port + MAR + i, 0);
+
+ outport_byte (port + CURR, NE_FIRST_RX_PAGE);
+
+ outport_byte (port + CMDR, MSK_PG0 | MSK_RD2);
+
+ /* Put the device on line. */
+ outport_byte (port + CMDR, MSK_PG0 | MSK_STA | MSK_RD2);
+
+ /* Set up interrupts. */
+
+ irq.name = sc->irno;
+ irq.hdl = ne_interrupt_handler;
+ irq.on = ne_interrupt_on;
+ irq.off = ne_interrupt_off;
+ irq.isOn = ne_interrupt_is_on;
+
+ if (! BSP_install_rtems_irq_handler (&irq))
+ rtems_panic ("Can't attach NE interrupt handler for irq %d.\n",
+ sc->irno);
+
+ /* Prepare to receive packets. */
+
+ outport_byte (port + TCR, 0);
+ outport_byte (port + RCR, (sc->accept_broadcasts ? MSK_AB : 0));
+}
+
+/* The NE2000 packet receive daemon. This task is started when the
+ NE2000 driver is initialized. */
+
+static void
+ne_rx_daemon (void *arg)
+{
+ struct ne_softc *sc = (struct ne_softc *) arg;
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ unsigned int port = sc->port;
+ unsigned int dport = port + DATAPORT;
+
+ while (1) {
+ rtems_event_set events;
+
+ /* Wait for the interrupt handler to tell us that there is a
+ packet ready to receive. */
+ rtems_bsdnet_event_receive (INTERRUPT_EVENT,
+ RTEMS_WAIT | RTEMS_EVENT_ANY,
+ RTEMS_NO_TIMEOUT,
+ &events);
+
+ /* Don't let the device interrupt us now. */
+ outport_byte (port + IMR, 0);
+
+ while (1) {
+ unsigned char startpage, currpage;
+ unsigned short statnext, len;
+ int next;
+ struct mbuf *m;
+ unsigned char *p;
+ int startaddr;
+ int toend;
+ struct ether_header *eh;
+
+ inport_byte (port + BNRY, startpage);
+
+ outport_byte (port + CMDR, MSK_PG1 | MSK_RD2);
+ inport_byte (port + CURR, currpage);
+ outport_byte (port + CMDR, MSK_PG0 | MSK_RD2);
+
+ ++startpage;
+ if (startpage >= NE_STOP_PAGE)
+ startpage = NE_FIRST_RX_PAGE;
+
+ if (startpage == currpage)
+ break;
+
+#ifdef DEBUG_NE2000
+ printk ("ne_rx_daemon: start page %x; current page %x\n",
+ startpage, currpage);
+#endif
+
+ /* Read the buffer header. This is 1 byte receive status, 1
+ byte page of next buffer, 2 bytes length. */
+ outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STA);
+ outport_byte (port + RBCR0, 4);
+ outport_byte (port + RBCR1, 0);
+ outport_byte (port + RSAR0, 0);
+ outport_byte (port + RSAR1, startpage);
+ outport_byte (port + CMDR, MSK_PG0 | MSK_RRE | MSK_STA);
+
+ if (sc->byte_transfers) {
+ unsigned char data;
+
+ inport_byte (dport, data); /* Throw away status */
+ inport_byte (dport, data);
+ next = data;
+
+ inport_byte (dport, data);
+ len = data;
+ inport_byte (dport, data);
+ len |= data << 8;
+ }
+ else { /* Word transfers */
+ inport_word (dport, statnext);
+ inport_word (dport, len);
+
+ next = statnext >> 8;
+ }
+
+ outport_byte (port + ISR, MSK_RDC);
+
+ if (next >= NE_STOP_PAGE)
+ next = NE_FIRST_RX_PAGE;
+
+ /* The first four bytes of the length are the buffer header. */
+ len -= 4;
+ startaddr = startpage * NE_PAGE_SIZE + 4;
+
+ MGETHDR (m, M_WAIT, MT_DATA);
+ MCLGET (m, M_WAIT);
+ m->m_pkthdr.rcvif = ifp;
+
+ p = mtod (m, unsigned char *);
+ m->m_len = m->m_pkthdr.len = len - sizeof (struct ether_header);
+
+ toend = NE_STOP_PAGE * NE_PAGE_SIZE - startaddr;
+ if (toend < len) {
+ ne_read_data (sc, startaddr, toend, p);
+ p += toend;
+ len -= toend;
+ startaddr = NE_FIRST_RX_PAGE * NE_PAGE_SIZE;
+ }
+
+ if (len > 0)
+ ne_read_data (sc, startaddr, len, p);
+
+ eh = mtod (m, struct ether_header *);
+ m->m_data += sizeof (struct ether_header);
+ ether_input (ifp, eh, m);
+
+ ++sc->stats.rx_packets;
+
+ outport_byte (port + BNRY, next - 1);
+ }
+
+ if (sc->overrun) {
+ outport_byte (port + ISR, MSK_OVW);
+ outport_byte (port + TCR, 0);
+ if (sc->resend)
+ outport_byte (port + CMDR, MSK_PG0 | MSK_TXP | MSK_RD2 | MSK_STA);
+ sc->resend = 0;
+ sc->overrun = 0;
+ }
+
+ /* Reenable device interrupts. */
+ outport_byte (port + IMR, NE_INTERRUPTS);
+ }
+}
+
+/* Load an NE2000 packet onto the device. */
+
+static void
+ne_loadpacket (struct ne_softc *sc, struct mbuf *m)
+{
+ unsigned int port = sc->port;
+ unsigned int dport = port + DATAPORT;
+ struct mbuf *mhold = m;
+ int leftover;
+ unsigned char leftover_data;
+ int timeout;
+
+#ifdef DEBUG_NE2000
+ printk ("Uploading NE2000 packet\n");
+#endif
+
+ /* Reset remote DMA complete flag. */
+ outport_byte (port + ISR, MSK_RDC);
+
+ /* Write out the count. */
+ outport_byte (port + RBCR0, m->m_pkthdr.len);
+ outport_byte (port + RBCR1, m->m_pkthdr.len >> 8);
+
+ sc->sendlen[sc->nextavail] = m->m_pkthdr.len;
+
+ /* Tell the device which address we want to write to. */
+ outport_byte (port + RSAR0, 0);
+ outport_byte (port + RSAR1,
+ NE_FIRST_TX_PAGE + (sc->nextavail * NE_TX_PAGES));
+
+ /* Set up the write. */
+ outport_byte (port + CMDR, MSK_PG0 | MSK_RWR | MSK_STA);
+
+ /* Transfer the mbuf chain to device memory. NE2000 devices require
+ that the data be transferred as words, so we need to handle odd
+ length mbufs. Never occurs if we force byte transfers. */
+
+ leftover = 0;
+ leftover_data = '\0';
+
+ for (; m != NULL; m = m->m_next) {
+ int len;
+ unsigned char *data;
+
+ len = m->m_len;
+ if (len == 0)
+ continue;
+
+ data = mtod (m, unsigned char *);
+
+ if (leftover) {
+ unsigned char next;
+
+ /* Data left over from previous mbuf in chain. */
+ next = *data++;
+ --len;
+ outport_word (dport, leftover_data | (next << 8));
+ leftover = 0;
+ }
+
+ /* If using byte transfers, len always ends up as zero so
+ there are no leftovers. */
+
+ if (sc->byte_transfers)
+ while (len > 0) {
+ outport_byte (dport, *data++);
+ len--;
+ }
+ else
+ while (len > 1) {
+ outport_word (dport, data[0] | (data[1] << 8));
+ data += 2;
+ len -= 2;
+ }
+
+ if (len > 0)
+ {
+ leftover = 1;
+ leftover_data = *data++;
+ }
+ }
+
+ if (leftover)
+ outport_word (dport, leftover_data);
+
+ m_freem (mhold);
+
+ /* Wait for the device to complete accepting the data, with a
+ limiting counter so that we don't wait too long. */
+ for (timeout = 0; timeout < 100; ++timeout)
+ {
+ unsigned char status;
+
+ inport_byte (port + ISR, status);
+
+#ifdef DEBUG_NE2000
+ if ((status &~ MSK_RDC) != 0)
+ printk ("Status 0x%x while waiting for acknowledgement of uploaded packet\n",
+ status);
+#endif
+
+ if ((status & MSK_RDC) != 0) {
+ outport_byte (port + ISR, MSK_RDC);
+ break;
+ }
+ }
+
+ if (timeout >= 100)
+ printk ("Timed out waiting for acknowledgement of uploaded NE2000 packet\n");
+
+ ++sc->nextavail;
+ if (sc->nextavail == NE_TX_BUFS)
+ sc->nextavail = 0;
+}
+
+/* Tell the NE2000 to transmit a buffer whose contents we have already
+ loaded onto the device. */
+
+static void
+ne_transmit (struct ne_softc *sc)
+{
+ unsigned int port = sc->port;
+ int len;
+
+#ifdef DEBUG_NE2000
+ printk ("Transmitting NE2000 packet\n");
+#endif
+
+ len = sc->sendlen[sc->nextsend];
+ if (len < ET_MINLEN)
+ len = ET_MINLEN;
+ outport_byte (port + TBCR0, len);
+ outport_byte (port + TBCR1, len >> 8);
+
+ outport_byte (port + TPSR, NE_FIRST_TX_PAGE + (sc->nextsend * NE_TX_PAGES));
+
+ outport_byte (port + CMDR, MSK_PG0 | MSK_TXP | MSK_RD2 | MSK_STA);
+
+ ++sc->nextsend;
+ if (sc->nextsend == NE_TX_BUFS)
+ sc->nextsend = 0;
+
+ ++sc->stats.tx_packets;
+}
+
+/* The NE2000 packet transmit daemon. This task is started when the
+ NE2000 driver is initialized. */
+
+static void
+ne_tx_daemon (void *arg)
+{
+ struct ne_softc *sc = (struct ne_softc *) arg;
+ unsigned int port = sc->port;
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+
+ while (1) {
+ rtems_event_set events;
+
+ /* Wait for a packet to be ready for sending, or for there to be
+ room for another packet in the device memory. */
+ rtems_bsdnet_event_receive (START_TRANSMIT_EVENT,
+ RTEMS_EVENT_ANY | RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT,
+ &events);
+
+#ifdef DEBUG_NE2000
+ printk ("ne_tx_daemon\n");
+#endif
+
+ /* This daemon handles both uploading data onto the device and
+ telling the device to transmit data which has been uploaded.
+ These are separate tasks, because while the device is
+ transmitting one buffer we will upload another. */
+
+ /* Don't let the device interrupt us now. */
+ outport_byte (port + IMR, 0);
+
+ while (1) {
+ struct mbuf *m;
+
+ /* If the device is not transmitting a packet, and we have
+ uploaded a packet, tell the device to transmit it. */
+ if (! sc->transmitting && sc->inuse > 0) {
+ sc->transmitting = 1;
+ ne_transmit (sc);
+ }
+
+ /* If we don't have any more buffers to send, quit now. */
+ if (ifp->if_snd.ifq_head == NULL) {
+ ifp->if_flags &= ~IFF_OACTIVE;
+ break;
+ }
+
+ /* Allocate a buffer to load data into. If there are none
+ available, quit until a buffer has been transmitted. */
+ if (sc->inuse >= NE_TX_BUFS)
+ break;
+
+ ++sc->inuse;
+
+ IF_DEQUEUE (&ifp->if_snd, m);
+ if (m == NULL)
+ panic ("ne_tx_daemon");
+
+ ne_loadpacket (sc, m);
+
+ /* Check the device status. It may have finished transmitting
+ the last packet. */
+ ne_check_status (sc);
+ }
+
+ /* Reenable device interrupts. */
+ outport_byte (port + IMR, NE_INTERRUPTS);
+ }
+}
+
+/* Start sending an NE2000 packet. */
+
+static void
+ne_start (struct ifnet *ifp)
+{
+ struct ne_softc *sc = ifp->if_softc;
+
+ /* Tell the transmit daemon to wake up and send a packet. */
+ rtems_event_send (sc->tx_daemon_tid, START_TRANSMIT_EVENT);
+ ifp->if_flags |= IFF_OACTIVE;
+}
+
+/* Initialize and start and NE2000. */
+
+static void
+ne_init (void *arg)
+{
+ struct ne_softc *sc = (struct ne_softc *) arg;
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+
+ if (sc->tx_daemon_tid == 0) {
+ sc->inuse = 0;
+ sc->nextavail = 0;
+ sc->nextsend = 0;
+ sc->transmitting = 0;
+
+ ne_init_hardware (sc);
+
+ sc->tx_daemon_tid = rtems_bsdnet_newproc ("SCtx", 4096, ne_tx_daemon, sc);
+ sc->rx_daemon_tid = rtems_bsdnet_newproc ("SCrx", 4096, ne_rx_daemon, sc);
+ }
+
+ ifp->if_flags |= IFF_RUNNING;
+}
+
+/* Stop an NE2000. */
+
+static void
+ne_stop (struct ne_softc *sc)
+{
+ unsigned int port = sc->port;
+ int i;
+
+ sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
+
+ /* Stop everything. */
+ outport_byte (port + CMDR, MSK_STP | MSK_RD2);
+
+ /* Wait for the interface to stop, using I as a time limit. */
+ for (i = 0; i < 5000; ++i)
+ {
+ unsigned char status;
+
+ inport_byte (port + ISR, status);
+ if ((status & MSK_RST) != 0)
+ break;
+ }
+
+ sc->inuse = 0;
+ sc->nextavail = 0;
+ sc->nextsend = 0;
+ sc->transmitting = 0;
+}
+
+/* Show NE2000 interface statistics. */
+
+static void
+ne_stats (struct ne_softc *sc)
+{
+ printf (" Received packets: %-8lu", sc->stats.rx_packets);
+ printf (" Transmitted packets: %-8lu\n", sc->stats.tx_packets);
+ printf (" Receive acks: %-8lu", sc->stats.rx_acks);
+ printf (" Transmit acks: %-8lu\n", sc->stats.tx_acks);
+ printf (" Packet overruns: %-8lu", sc->stats.overruns);
+ printf (" Frame errors: %-8lu\n", sc->stats.rx_frame_errors);
+ printf (" CRC errors: %-8lu", sc->stats.rx_crc_errors);
+ printf (" Missed packets: %-8lu\n", sc->stats.rx_missed_errors);
+ printf (" Interrupts: %-8lu\n", sc->stats.interrupts);
+}
+
+/* NE2000 driver ioctl handler. */
+
+static int
+ne_ioctl (struct ifnet *ifp, int command, caddr_t data)
+{
+ struct ne_softc *sc = ifp->if_softc;
+ int error = 0;
+
+ switch (command) {
+ case SIOCGIFADDR:
+ case SIOCSIFADDR:
+ error = ether_ioctl (ifp, command, data);
+ break;
+
+ case SIOCSIFFLAGS:
+ switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
+ case IFF_RUNNING:
+ ne_stop (sc);
+ break;
+
+ case IFF_UP:
+ ne_init (sc);
+ break;
+
+ case IFF_UP | IFF_RUNNING:
+ ne_stop (sc);
+ ne_init (sc);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case SIO_RTEMS_SHOW_STATS:
+ ne_stats (sc);
+ break;
+
+ /* FIXME: Multicast commands must be added here. */
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return error;
+}
+
+/* Attach an NE2000 driver to the system. */
+
+int
+rtems_ne_driver_attach (struct rtems_bsdnet_ifconfig *config)
+{
+ int i;
+ struct ne_softc *sc;
+ struct ifnet *ifp;
+ int mtu;
+
+ /* Find a free driver. */
+ sc = NULL;
+ for (i = 0; i < NNEDRIVER; ++i) {
+ sc = &ne_softc[i];
+ ifp = &sc->arpcom.ac_if;
+ if (ifp->if_softc == NULL)
+ break;
+ }
+
+ if (sc == NULL) {
+ printf ("Too many NE2000 drivers.\n");
+ return 0;
+ }
+
+ memset (sc, 0, sizeof *sc);
+
+ /* Check whether we do byte-wide or word-wide transfers. */
+
+#ifdef NE2000_BYTE_TRANSFERS
+ sc->byte_transfers = TRUE;
+#else
+ sc->byte_transfers = FALSE;
+#endif
+
+ /* Handle the options passed in by the caller. */
+
+ if (config->mtu != 0)
+ mtu = config->mtu;
+ else
+ mtu = ETHERMTU;
+
+ if (config->irno != 0)
+ sc->irno = config->irno;
+ else {
+ /* We use 5 as the default IRQ. */
+ sc->irno = 5;
+ }
+
+ if (config->port != 0)
+ sc->port = config->port;
+ else {
+ /* We use 0x300 as the default IO port number. */
+ sc->port = 0x300;
+ }
+
+ sc->accept_broadcasts = ! config->ignore_broadcast;
+
+ if (config->hardware_address != NULL)
+ memcpy (sc->arpcom.ac_enaddr, config->hardware_address,
+ ETHER_ADDR_LEN);
+ else
+ {
+ unsigned char prom[16];
+ int ia;
+
+ /* Read the PROM to get the Ethernet hardware address. */
+
+ outport_byte (sc->port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP);
+
+ if (sc->byte_transfers) {
+ outport_byte (sc->port + DCR, MSK_FT10 | MSK_BMS);
+ }
+ else {
+ outport_byte (sc->port + DCR, MSK_FT10 | MSK_BMS | MSK_WTS);
+ }
+
+ outport_byte (sc->port + RBCR0, 0);
+ outport_byte (sc->port + RBCR1, 0);
+ outport_byte (sc->port + RCR, MSK_MON);
+ outport_byte (sc->port + TCR, MSK_LOOP);
+ outport_byte (sc->port + IMR, 0);
+ outport_byte (sc->port + ISR, 0xff);
+
+ ne_read_data (sc, 0, sizeof prom, prom);
+
+ outport_byte (sc->port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP);
+
+ for (ia = 0; ia < ETHER_ADDR_LEN; ++ia)
+ sc->arpcom.ac_enaddr[ia] = prom[ia * 2];
+ }
+
+ /* Set up the network interface. */
+
+ ifp->if_softc = sc;
+ ifp->if_unit = i + 1;
+ ifp->if_name = "ne";
+ ifp->if_mtu = mtu;
+ ifp->if_init = ne_init;
+ ifp->if_ioctl = ne_ioctl;
+ ifp->if_start = ne_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;
+
+ /* Attach the interface. */
+
+ if_attach (ifp);
+ ether_ifattach (ifp);
+
+ return 1;
+}
diff --git a/c/src/lib/libbsp/i386/ts_386ex/start/80386ex.h b/c/src/lib/libbsp/i386/ts_386ex/start/80386ex.h
new file mode 100644
index 0000000000..24e4b9a8ee
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/start/80386ex.h
@@ -0,0 +1,254 @@
+/*
+ * Submitted by:
+ *
+ * Erik Ivanenko
+ * University of Toronto
+ * erik.ivanenko@utoronto.ca
+ *
+ * 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$
+ */
+
+/* REMAP ADDRESSING Registers */
+#define REMAPCFGH 0x0023
+#define REMAPCFGL 0x0022
+#define REMAPCFG 0x0022
+/* INTERRUPT CONTROL REGISTERS -- SLOT 15 ADDRESSES */
+#define ICW1M 0xF020
+#define ICW1S 0xF0A0
+#define ICW2M 0xF021
+#define ICW2S 0xF0A1
+#define ICW3M 0xF021
+#define ICW3S 0xF0A1
+#define ICW4M 0xF021
+#define ICW4S 0xF0A1
+#define OCW1M 0xF021
+#define OCW1S 0xF0A1
+#define OCW2M 0xF020
+#define OCW2S 0xF0A0
+#define OCW3M 0xF020
+#define OCW3S 0xF0A0
+/* INTERRUPT CONTROL REGISTERS -- SLOT 0 ADDRESSES */
+#define ICW1MDOS 0x0020
+#define ICW1SDOS 0x00A0
+#define ICW2MDOS 0x0021
+#define ICW2SDOS 0x00A1
+#define ICW3MDOS 0x0021
+#define ICW3SDOS 0x00A1
+#define ICW4MDOS 0x0021
+#define ICW4SDOS 0x00A1
+#define OCW1MDOS 0x0021
+#define OCW1SDOS 0x00A1
+#define OCW2MDOS 0x0020
+#define OCW2SDOS 0x00A0
+#define OCW3MDOS 0x0020
+#define OCW3SDOS 0x00A0
+
+
+/* CONFIGURATION Registers */
+#define DMACFG 0xF830
+#define INTCFG 0xF832
+#define TMRCFG 0xF834
+#define SIOCFG 0xF836
+#define P1CFG 0xF820
+#define P2CFG 0xF822
+#define P3CFG 0xF824
+#define PINCFG 0xF826
+
+/* WATCHDOG TIMER Registers */
+#define WDTRLDH 0xF4C0
+#define WDTRLDL 0xF4C2
+#define WDTCNTH 0xF4C4
+#define WDTCNTL 0xF4C6
+#define WDTCLR 0xF4C8
+#define WDTSTATUS 0xF4CA
+
+/* TIMER CONTROL REGISTERS -- SLOT 15 ADDRESSES */
+#define TMR0 0xF040
+#define TMR1 0xF041
+#define TMR2 0xF042
+#define TMRCON 0xF043
+/* TIMER CONTROL REGISTERS -- SLOT 0 ADDRESSES */
+#define TMR0DOS 0x0040
+#define TMR1DOS 0x0041
+#define TMR2DOS 0x0042
+#define TMRCONDOS 0x0043
+
+/* INPUT/OUTPUT PORT UNIT Registers */
+#define P1PIN 0xF860
+#define P1LTC 0xF862
+#define P1DIR 0xF864
+#define P2PIN 0xF868
+#define P2LTC 0xF86A
+#define P2DIR 0xF86C
+#define P3PIN 0xF870
+#define P3LTC 0xF872
+#define P3DIR 0xF874
+
+/* ASYNCHRONOUS SERIAL CHANNEL 0 -- SLOT 15 ADDRESSES */
+#define RBR0 0xF4F8
+#define THR0 0xF4F8
+#define TBR0 0xF4F8
+#define DLL0 0xF4F8
+#define IER0 0xF4F9
+#define DLH0 0xF4F9
+#define IIR0 0xF4FA
+#define LCR0 0xF4FB
+#define MCR0 0xF4FC
+#define LSR0 0xF4FD
+#define MSR0 0xF4FE
+#define SCR0 0xF4FF
+/* ASYNCHRONOUS SERIAL CHANNEL 0 -- SLOT 0 ADDRESSES */
+#define RBR0DOS 0x03F8
+#define THR0DOS 0x03F8
+#define TBR0DOS 0x03F8
+#define DLL0DOS 0x03F8
+#define IER0DOS 0x03F9
+#define DLH0DOS 0x03F9
+#define IIR0DOS 0x03FA
+#define LCR0DOS 0x03FB
+#define MCR0DOS 0x03FC
+#define LSR0DOS 0x03FD
+#define MSR0DOS 0x03FE
+#define SCR0DOS 0x03FF
+
+/* ASYNCHRONOUS SERIAL CHANNEL 1 -- SLOT 15 ADDRESSES */
+#define RBR1 0xF8F8
+#define THR1 0xF8F8
+#define TBR1 0XF8F8
+#define DLL1 0xF8F8
+#define IER1 0xF8F9
+#define DLH1 0xF8F9
+#define IIR1 0xF8FA
+#define LCR1 0xF8FB
+#define MCR1 0xF8FC
+#define LSR1 0xF8FD
+#define MSR1 0xF8FE
+#define SCR1 0xF8FF
+/* ASYNCHRONOUS SERIAL CHANNEL 1 -- SLOT 0 ADDRESSES */
+#define RBR1DOS 0x02F8
+#define THR1DOS 0x02F8
+#define TBR1DOS 0x02F8
+#define DLL1DOS 0x02F8
+#define IER1DOS 0x02F9
+#define DLH1DOS 0x02F9
+#define IIR1DOS 0x02FA
+#define LCR1DOS 0x02FB
+#define MCR1DOS 0x02FC
+#define LSR1DOS 0x02FD
+#define MSR1DOS 0x02FE
+#define SCR1DOS 0x02FF
+
+/* SYNCHRONOUS SERIAL CHANNEL REGISTERS */
+#define SSIOTBUF 0xF480
+#define SSIORBUF 0xF482
+#define SSIOBAUD 0xF484
+#define SSIOCON1 0xF486
+#define SSIOCON2 0xF488
+#define SSIOCTR 0xF48A
+
+/* CHIP SELECT UNIT Registers */
+#define CS0ADL 0xF400
+#define CS0ADH 0xF402
+#define CS0MSKL 0xF404
+#define CS0MSKH 0xF406
+#define CS1ADL 0xF408
+#define CS1ADH 0xF40A
+#define CS1MSKL 0xF40C
+#define CS1MSKH 0xF40E
+#define CS2ADL 0xF410
+#define CS2ADH 0xF412
+#define CS2MSKL 0xF414
+#define CS2MSKH 0xF416
+#define CS3ADL 0xF418
+#define CS3ADH 0xF41A
+#define CS3MSKL 0xF41C
+#define CS3MSKH 0xF41E
+#define CS4ADL 0xF420
+#define CS4ADH 0xF422
+#define CS4MSKL 0xF424
+#define CS4MSKH 0xF426
+#define CS5ADL 0xF428
+#define CS5ADH 0xF42A
+#define CS5MSKL 0xF42C
+#define CS5MSKH 0xF42E
+#define CS6ADL 0xF430
+#define CS6ADH 0xF432
+#define CS6MSKL 0xF434
+#define CS6MSKH 0xF436
+#define UCSADL 0xF438
+#define UCSADH 0xF43A
+#define UCSMSKL 0xF43C
+#define UCSMSKH 0xF43E
+
+/* REFRESH CONTROL UNIT Registers */
+
+#define RFSBAD 0xF4A0
+#define RFSCIR 0xF4A2
+#define RFSCON 0xF4A4
+#define RFSADD 0xF4A6
+
+/* POWER MANAGEMENT CONTROL Registers */
+
+#define PWRCON 0xF800
+#define CLKPRS 0xF804
+
+/* DMA UNIT REGISTERS -- SLOT 15 ADDRESSES */
+#define DMA0TAR 0xF000
+#define DMA0BYC 0xF001
+#define DMA1TAR 0xF002
+#define DMA1BYC 0xF003
+#define DMACMD1 0xF008
+#define DMASTS 0xF008
+#define DMASRR 0xF009
+#define DMAMSK 0xF00A
+#define DMAMOD1 0xF00B
+#define DMACLRBP 0xF00C
+#define DMACLR 0xF00D
+#define DMACLRMSK 0xF00E
+#define DMAGRPMSK 0xF00F
+#define DMA0REQL 0xF010
+#define DMA0REQH 0xF011
+#define DMA1REQL 0xF012
+#define DMA1REQH 0xF013
+#define DMABSR 0xF018
+#define DMACHR 0xF019
+#define DMAIS 0xF019
+#define DMACMD2 0xF01A
+#define DMAMOD2 0xF01B
+#define DMAIEN 0xF01C
+#define DMAOVFE 0xF01D
+#define DMACLRTC 0xF01E
+#define DMA1TARPL 0xF083
+#define DMA1TARPH 0xF085
+#define DMA0TARPH 0xF086
+#define DMA0TARPL 0xF087
+#define DMA0BYCH 0xF098
+#define DMA1BYCH 0xF099
+
+/* DMA UNIT REGISTERS -- SLOT 0 ADDRESSES */
+#define DMA0TARDOS 0x0000
+#define DMA0BYCDOS 0x0001
+#define DMA1TARDOS 0x0002
+#define DMA1BYCDOS 0x0003
+#define DMACMD1DOS 0x0008
+#define DMASTSDOS 0x0008
+#define DMASRRDOS 0x0009
+#define DMAMSKDOS 0x000A
+#define DMAMOD1DOS 0x000B
+#define DMACLRBPDOS 0x000C
+#define DMACLRDOS 0x000D
+#define DMACLRMSKDOS 0x000E
+#define DMAGRPMSKDOS 0x000F
+#define DMA1TARPLDOS 0x0083
+#define DMA0TARPLDOS 0x0087
+
+/* A20GATE AND FAST CPU RESET -- SLOT 15 ADDRESS */
+#define PORT92 0xF092
+/* A20GATE AND FAST CPU RESET -- SLOT 0 ADDRESS */
+#define PORT92DOS 0x0092
+
+/* end of include file */
diff --git a/c/src/lib/libbsp/i386/ts_386ex/start/80386ex.inc b/c/src/lib/libbsp/i386/ts_386ex/start/80386ex.inc
new file mode 100644
index 0000000000..798dda4215
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/start/80386ex.inc
@@ -0,0 +1,252 @@
+/*
+ * Submitted by:
+ *
+ * Erik Ivanenko
+ * University of Toronto
+ * erik.ivanenko@utoronto.ca
+ *
+ * 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$
+ */
+
+/* REMAP ADDRESSING Registers */
+.set REMAPCFGH , 0x0023
+.set REMAPCFGL , 0x0022
+.set REMAPCFG , 0x0022
+/* INTERRUPT CONTROL REGISTERS -- SLOT 15 ADDRESSES */
+.set ICW1M , 0xF020
+.set ICW1S , 0xF0A0
+.set ICW2M , 0xF021
+.set ICW2S , 0xF0A1
+.set ICW3M , 0xF021
+.set ICW3S , 0xF0A1
+.set ICW4M , 0xF021
+.set ICW4S , 0xF0A1
+.set OCW1M , 0xF021
+.set OCW1S , 0xF0A1
+.set OCW2M , 0xF020
+.set OCW2S , 0xF0A0
+.set OCW3M , 0xF020
+.set OCW3S , 0xF0A0
+/* INTERRUPT CONTROL REGISTERS -- SLOT 0 ADDRESSES */
+.set ICW1MDOS , 0x0020
+.set ICW1SDOS , 0x00A0
+.set ICW2MDOS , 0x0021
+.set ICW2SDOS , 0x00A1
+.set ICW3MDOS , 0x0021
+.set ICW3SDOS , 0x00A1
+.set ICW4MDOS , 0x0021
+.set ICW4SDOS , 0x00A1
+.set OCW1MDOS , 0x0021
+.set OCW1SDOS , 0x00A1
+.set OCW2MDOS , 0x0020
+.set OCW2SDOS , 0x00A0
+.set OCW3MDOS , 0x0020
+.set OCW3SDOS , 0x00A0
+
+
+/* CONFIGURATION Registers */
+.set DMACFG , 0xF830
+.set INTCFG , 0xF832
+.set TMRCFG , 0xF834
+.set SIOCFG , 0xF836
+.set P1CFG , 0xF820
+.set P2CFG , 0xF822
+.set P3CFG , 0xF824
+.set PINCFG , 0xF826
+
+/* WATCHDOG TIMER Registers */
+.set WDTRLDH , 0xF4C0
+.set WDTRLDL , 0xF4C2
+.set WDTCNTH , 0xF4C4
+.set WDTCNTL , 0xF4C6
+.set WDTCLR , 0xF4C8
+.set WDTSTATUS , 0xF4CA
+
+/* TIMER CONTROL REGISTERS -- SLOT 15 ADDRESSES */
+.set TMR0 , 0xF040
+.set TMR1 , 0xF041
+.set TMR2 , 0xF042
+.set TMRCON , 0xF043
+/* TIMER CONTROL REGISTERS -- SLOT 0 ADDRESSES */
+.set TMR0DOS , 0x0040
+.set TMR1DOS , 0x0041
+.set TMR2DOS , 0x0042
+.set TMRCONDOS , 0x0043
+
+/* INPUT/OUTPUT PORT UNIT Registers */
+.set P1PIN , 0xF860
+.set P1LTC , 0xF862
+.set P1DIR , 0xF864
+.set P2PIN , 0xF868
+.set P2LTC , 0xF86A
+.set P2DIR , 0xF86C
+.set P3PIN , 0xF870
+.set P3LTC , 0xF872
+.set P3DIR , 0xF874
+
+/* ASYNCHRONOUS SERIAL CHANNEL 0 -- SLOT 15 ADDRESSES */
+.set RBR0 , 0xF4F8
+.set THR0 , 0xF4F8
+.set TBR0 , 0xF4F8
+.set DLL0 , 0xF4F8
+.set IER0 , 0xF4F9
+.set DLH0 , 0xF4F9
+.set IIR0 , 0xF4FA
+.set LCR0 , 0xF4FB
+.set MCR0 , 0xF4FC
+.set LSR0 , 0xF4FD
+.set MSR0 , 0xF4FE
+.set SCR0 , 0xF4FF
+/* ASYNCHRONOUS SERIAL CHANNEL 0 -- SLOT 0 ADDRESSES */
+.set RBR0DOS , 0x03F8
+.set THR0DOS , 0x03F8
+.set TBR0DOS , 0x03F8
+.set DLL0DOS , 0x03F8
+.set IER0DOS , 0x03F9
+.set DLH0DOS , 0x03F9
+.set IIR0DOS , 0x03FA
+.set LCR0DOS , 0x03FB
+.set MCR0DOS , 0x03FC
+.set LSR0DOS , 0x03FD
+.set MSR0DOS , 0x03FE
+.set SCR0DOS , 0x03FF
+
+/* ASYNCHRONOUS SERIAL CHANNEL 1 -- SLOT 15 ADDRESSES */
+.set RBR1 , 0xF8F8
+.set THR1 , 0xF8F8
+.set TBR1 , 0XF8F8
+.set DLL1 , 0xF8F8
+.set IER1 , 0xF8F9
+.set DLH1 , 0xF8F9
+.set IIR1 , 0xF8FA
+.set LCR1 , 0xF8FB
+.set MCR1 , 0xF8FC
+.set LSR1 , 0xF8FD
+.set MSR1 , 0xF8FE
+.set SCR1 , 0xF8FF
+/* ASYNCHRONOUS SERIAL CHANNEL 1 -- SLOT 0 ADDRESSES */
+.set RBR1DOS , 0x02F8
+.set THR1DOS , 0x02F8
+.set TBR1DOS , 0x02F8
+.set DLL1DOS , 0x02F8
+.set IER1DOS , 0x02F9
+.set DLH1DOS , 0x02F9
+.set IIR1DOS , 0x02FA
+.set LCR1DOS , 0x02FB
+.set MCR1DOS , 0x02FC
+.set LSR1DOS , 0x02FD
+.set MSR1DOS , 0x02FE
+.set SCR1DOS , 0x02FF
+
+/* SYNCHRONOUS SERIAL CHANNEL REGISTERS */
+.set SSIOTBUF , 0xF480
+.set SSIORBUF , 0xF482
+.set SSIOBAUD , 0xF484
+.set SSIOCON1 , 0xF486
+.set SSIOCON2 , 0xF488
+.set SSIOCTR , 0xF48A
+
+/* CHIP SELECT UNIT Registers */
+.set CS0ADL , 0xF400
+.set CS0ADH , 0xF402
+.set CS0MSKL , 0xF404
+.set CS0MSKH , 0xF406
+.set CS1ADL , 0xF408
+.set CS1ADH , 0xF40A
+.set CS1MSKL , 0xF40C
+.set CS1MSKH , 0xF40E
+.set CS2ADL , 0xF410
+.set CS2ADH , 0xF412
+.set CS2MSKL , 0xF414
+.set CS2MSKH , 0xF416
+.set CS3ADL , 0xF418
+.set CS3ADH , 0xF41A
+.set CS3MSKL , 0xF41C
+.set CS3MSKH , 0xF41E
+.set CS4ADL , 0xF420
+.set CS4ADH , 0xF422
+.set CS4MSKL , 0xF424
+.set CS4MSKH , 0xF426
+.set CS5ADL , 0xF428
+.set CS5ADH , 0xF42A
+.set CS5MSKL , 0xF42C
+.set CS5MSKH , 0xF42E
+.set CS6ADL , 0xF430
+.set CS6ADH , 0xF432
+.set CS6MSKL , 0xF434
+.set CS6MSKH , 0xF436
+.set UCSADL , 0xF438
+.set UCSADH , 0xF43A
+.set UCSMSKL , 0xF43C
+.set UCSMSKH , 0xF43E
+
+/* REFRESH CONTROL UNIT Registers */
+
+.set RFSBAD , 0xF4A0
+.set RFSCIR , 0xF4A2
+.set RFSCON , 0xF4A4
+.set RFSADD , 0xF4A6
+
+/* POWER MANAGEMENT CONTROL Registers */
+
+.set PWRCON , 0xF800
+.set CLKPRS , 0xF804
+
+/* DMA UNIT REGISTERS -- SLOT 15 ADDRESSES */
+.set DMA0TAR , 0xF000
+.set DMA0BYC , 0xF001
+.set DMA1TAR , 0xF002
+.set DMA1BYC , 0xF003
+.set DMACMD1 , 0xF008
+.set DMASTS , 0xF008
+.set DMASRR , 0xF009
+.set DMAMSK , 0xF00A
+.set DMAMOD1 , 0xF00B
+.set DMACLRBP , 0xF00C
+.set DMACLR , 0xF00D
+.set DMACLRMSK , 0xF00E
+.set DMAGRPMSK , 0xF00F
+.set DMA0REQL , 0xF010
+.set DMA0REQH , 0xF011
+.set DMA1REQL , 0xF012
+.set DMA1REQH , 0xF013
+.set DMABSR , 0xF018
+.set DMACHR , 0xF019
+.set DMAIS , 0xF019
+.set DMACMD2 , 0xF01A
+.set DMAMOD2 , 0xF01B
+.set DMAIEN , 0xF01C
+.set DMAOVFE , 0xF01D
+.set DMACLRTC , 0xF01E
+.set DMA1TARPL , 0xF083
+.set DMA1TARPH , 0xF085
+.set DMA0TARPH , 0xF086
+.set DMA0TARPL , 0xF087
+.set DMA0BYCH , 0xF098
+.set DMA1BYCH , 0xF099
+
+/* DMA UNIT REGISTERS -- SLOT 0 ADDRESSES */
+.set DMA0TARDOS , 0x0000
+.set DMA0BYCDOS , 0x0001
+.set DMA1TARDOS , 0x0002
+.set DMA1BYCDOS , 0x0003
+.set DMACMD1DOS , 0x0008
+.set DMASTSDOS , 0x0008
+.set DMASRRDOS , 0x0009
+.set DMAMSKDOS , 0x000A
+.set DMAMOD1DOS , 0x000B
+.set DMACLRBPDOS , 0x000C
+.set DMACLRDOS , 0x000D
+.set DMACLRMSKDOS , 0x000E
+.set DMAGRPMSKDOS , 0x000F
+.set DMA1TARPLDOS , 0x0083
+.set DMA0TARPLDOS , 0x0087
+
+/* A20GATE AND FAST CPU RESET -- SLOT 15 ADDRESS */
+.set PORT92 , 0xF092
+/* A20GATE AND FAST CPU RESET -- SLOT 0 ADDRESS */
+.set PORT92DOS , 0x0092
diff --git a/c/src/lib/libbsp/i386/ts_386ex/start/Makefile.in b/c/src/lib/libbsp/i386/ts_386ex/start/Makefile.in
new file mode 100644
index 0000000000..313955a579
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/start/Makefile.in
@@ -0,0 +1,72 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = ../../../../../../..
+subdir = c/src/lib/libbsp/i386/ts_386ex/start
+
+INSTALL = @INSTALL@
+
+RTEMS_ROOT = $(top_srcdir)/@RTEMS_TOPdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+VPATH = @srcdir@
+
+RTEMS_GAS_CODE16 = @RTEMS_GAS_CODE16@
+
+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) $(H_FILES) $(S_FILES)
+OBJS=$(C_O_FILES) $(S_O_FILES)
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+ifeq ($(RTEMS_GAS_CODE16),yes)
+CPPFLAGS += -DNEW_GAS
+endif
+
+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
+
+# Install the program(s), appending _g or _p as appropriate.
+# for include files, just use $(INSTALL_CHANGE)
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
diff --git a/c/src/lib/libbsp/i386/ts_386ex/start/macros.inc b/c/src/lib/libbsp/i386/ts_386ex/start/macros.inc
new file mode 100644
index 0000000000..b3814479a2
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/start/macros.inc
@@ -0,0 +1,115 @@
+/* macros.inc
+ *
+ * This file assists the board independent startup code
+ * by initializing the chip-select channels to
+ * reflect the proper memory configuration.
+ *
+ * NOTE: No stack has been established when this routine
+ * is invoked. It returns to start.s through ldsegs
+ *
+ * Submitted by:
+ *
+ * Erik Ivanenko
+ * University of Toronto
+ * erik.ivanenko@utoronto.ca
+ *
+ * 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$
+ */
+
+.set GDT_CODE_PTR , 0x08
+.set GDT_DATA_PTR , 0x10
+
+.set BOARD_SELECT , 0x301
+.set BOARD_DATA , 0x302
+.set BOARD_LATCH , 0x303
+
+
+#define SetExRegByte(_register,_value) \
+ movb $ ## _value, al; \
+ movw $ ## _register, dx; \
+ outb al, dx
+
+#define SetExRegWord(_register,_value) \
+ movw $ ## _value, ax; \
+ movw $ ## _register, dx ; \
+ outw ax, dx
+
+
+#define DESC2(lim_0_15, bas_0_15, bas_16_23, access, gran, bas_24_31) \
+ .word lim_0_15 ; \
+ .word bas_0_15 ; \
+ .byte bas_16_23 ; \
+ .byte access ; \
+ .byte gran ; \
+ .byte bas_24_31
+
+#define DESC3( _base, _limit) \
+.word _limit ; \
+.long _base
+
+/* THE GET_ACCESS IS CHANGED FROM 8E TO 9E */
+
+#define INTERRUPT_GATE( _vector ) \
+ .word _vector ; \
+ .word GDT_CODE_PTR ; \
+ .byte 0x0 ; \
+ .byte 0x8E ; \
+ .word 0x0
+
+#define rLOAD_INDEX( _selector, _segment_register) \
+ movl _selector , _segment_register ; \
+ addb al, ( eax )
+
+#define rLOAD_SEGMENT( _reg, _segment_register) \
+ mov _reg , _segment_register ; \
+
+/* #define rLOAD_SEGMENT( _reg, _segment_register) \
+ .code16 ; \
+ mov _reg , _segment_register ; \
+ .code32
+*/
+#define pLOAD_SEGMENT( _selector, _segment_register) \
+ movl $ ## _selector , eax ; .code16 ; \
+ mov ax, _segment_register ; .code32
+
+/* #define MOVE_WORD( _immed32, _reg ) \
+ data16 ; \
+ movl _immed32, _reg
+*/
+
+#define MOVE_WORD( _immed32, _reg ) \
+ movw _immed32, _reg
+
+/* #define MOVE_IMMED_WORD( _immed32, _reg ) \
+ data16 ; \
+ mov $ ## _immed32, _reg
+
+#define CS_OFF( _cs_symbol, _reg ) \
+ data16 ; \
+ mov _cs_symbol, _reg ; \
+ data16 ;\
+ andl $0x000ffff, _reg
+
+#define _16_NOPS \
+ nop ; \
+ nop ; \
+ nop ; \
+ nop ; \
+ nop ; \
+ nop ; \
+ nop ; \
+ nop ; \
+ nop ; \
+ nop ; \
+ nop ; \
+ nop ; \
+ nop ; \
+ nop ; \
+ nop ; \
+ nop ;
+*/
+
diff --git a/c/src/lib/libbsp/i386/ts_386ex/start/start.S b/c/src/lib/libbsp/i386/ts_386ex/start/start.S
new file mode 100644
index 0000000000..7a3c8509c1
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/start/start.S
@@ -0,0 +1,501 @@
+/*
+ * This file is the main boot and configuration file for the TS-1325. It is
+ * solely responsible for initializing the internal register set to reflect
+ * the proper board configuration. This version is modified from the i386ex
+ * BSP startup:
+ *
+ * 1) 1 MB RAM @ 0x0100000
+ * 2) 1 MB RAM @ 0x0 but with standard DOS memory usage.
+ * 3) Timer0 used as RTEMS clock ticker, 1 msec tick rate.
+ * 4) READY# is generated by CPU
+ *
+ * The file describes the ".initial" section, which contains:
+ * 1) device configuration code
+ * 2) interrupt descriptor table
+ * 3) global descriptor table
+ * 4) and initial boot code
+ *
+ * Modified by:
+ *
+ * Tony Ambardar
+ * University of British Columbia
+ * tonya@ece.ubc.ca
+ *
+ * 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 "asm.h"
+#include "macros.inc"
+#include "80386ex.inc"
+
+#include "ts_1325.inc" /* controls for LED and button */
+
+/*
+ * NEW_GAS Needed for binutils 2.9.1.0.7 and higher
+ */
+
+ EXTERN (boot_card) /* exits to bspstart */
+ EXTERN (_DOS_seg_base) /* defined in startup/linkcmds */
+ EXTERN (Clock_exit)
+
+ PUBLIC (Interrupt_descriptor_table)
+ PUBLIC ( SYM(IDTR) )
+ PUBLIC (_Global_descriptor_table)
+ PUBLIC ( SYM(GDTR) )
+
+ PUBLIC( SYM(_init_i386ex) )
+
+
+ .section .initial
+
+/*
+ * Enable access to peripheral register at expanded I/O addresses
+ */
+SYM(_init_i386ex):
+ .code16
+/*
+ LED_GREEN
+ WAIT_BUTTON
+*/
+# cli Move this up for now for debug.
+ movw $0x8000 , ax
+ outb al , $REMAPCFGH
+ xchg al , ah
+ outb al , $REMAPCFGL
+ outw ax , $REMAPCFG ;
+/*
+ LED_OFF
+ WAIT_BUTTON
+*/
+/*
+ * Configure operation of the A20 Address Line
+ */
+SYM(A20):
+ movw $PORT92 , dx
+
+ inb dx , al # clear A20 port reset
+ andb $0xfe , al # b0 Fast Reset(0)=disabled,(1)=reset triggered
+ orb $0x02 , al # Bit 1 Fast A20 = 0 (always 0) else enabled.
+ outb al , dx
+/*
+ LED_YELLOW
+ WAIT_BUTTON
+*/
+SYM(Watchdog):
+ movw $WDTSTATUS , dx # address the WDT status port
+ inb dx , al # get the WDT status
+ orb $0x01 , al # set the CLKDIS bit
+ outb al , dx # disable the clock to the WDT
+/*
+ LED_GREEN
+ WAIT_BUTTON
+*/
+/*
+ * Initialize Refresh Control Unit for:
+ * Refresh Address = 0x0000
+
+ * Refresh gate between rows is 20.0 (???) uSec
+ * Using a CLK2 frequency of 50Mhz ( 25Mhz CPU )
+ * The refresh unit is enabled
+ * The refresh pin is not used.
+ *
+ * Different TS units might have different refresh intervals, so
+ * comment out. Will be set up anyway after booting to DOS.
+ */
+
+/*
+SYM(InitRCU):
+ SetExRegWord( RFSCIR , 0x1F4) # refresh interval 500
+ SetExRegWord( RFSBAD , 0x0) # base address
+ SetExRegWord( RFSADD , 0x0) # address register
+ SetExRegWord( RFSCON , 0x8000) # enable bit
+*/
+
+/*
+ LED_OFF
+ WAIT_BUTTON
+*/
+/*
+ * Initialize clock and power mgmt unit for:
+ * Clock Frequency = 50 Mhz
+ * Prescaled clock output = 1 Mhz
+ * Normal halt instructions
+ *
+ * NOTE: Hope this doesn't change the COMCLK frequency
+ */
+
+SYM(InitClk):
+ SetExRegByte( PWRCON, 0x0 )
+ SetExRegWord( CLKPRS, 0x17) # 0x13 for 1.19318 MHz. 0x17 for 1MHz.
+
+/**************************************************************
+ * Initialize the Pin Configurations
+ *************************************************************/
+/*
+ LED_YELLOW
+ WAIT_BUTTON
+*/
+/*
+ * Initialize I/O port 1 for:
+ * PIN 0 = 0, Inport for external push-button switch
+ * PIN 1 = 1, RTS0# to package pin
+ * PIN 2 = 1, DTR0# to package pin
+ * PIN 3 = 1, DSR0# to package pin
+ * PIN 4 = 0, Inport ???
+ * PIN 5 = 0, Outport (Green LED, 1 = ON)
+ * PIN 6 = 0, Outport (Red LED, 1 = OFF)
+ * PIN 7 = 0, Inport ???
+ */
+
+SYM(InitPort1):
+ SetExRegByte( P1LTC , 0xd1 )
+ SetExRegByte( P1DIR , 0x91)
+ SetExRegByte( P1CFG , 0x0e)
+/*
+ LED_GREEN
+ WAIT_BUTTON
+*/
+/*
+ * Initialize I/O port 2 for:
+ * PIN 0 = 0, Outport ???
+ * PIN 1 = 0, Outport ???
+ * PIN 2 = 0, Outport ???
+ * PIN 3 = 0, Outport ???
+ * PIN 4 = 0, Outport ???
+ * PIN 5 = 1, Int. periph, RXD0
+ * PIN 6 = 1, Int. periph, TXD0
+ * PIN 7 = 0, Outport ???
+ */
+
+SYM(InitPort2):
+ SetExRegByte( P2LTC , 0x1f )
+ SetExRegByte( P2DIR , 0x00 )
+ SetExRegByte( P2CFG , 0x60)
+/*
+ LED_OFF
+ WAIT_BUTTON
+*/
+/*
+ * Initialize I/O port 3 P3CFG
+ * PIN 0 = 1, Int. periph, TMROUT0
+ * PIN 1 = 1, Int. periph, TMROUT1
+ * PIN 2 = 1, Int. periph, INT0 (IR1)
+ * PIN 3 = 1, Int. periph, INT1 (IR5)
+ * PIN 4 = 1, Int. periph, INT2 (IR6)
+ * PIN 5 = 1, Int. periph, INT2 (IR7)
+ * PIN 6 = 0, Outport ???
+ * PIN 7 = 1, Int. periph, COMCLK used for serial I/O
+ */
+
+SYM(InitPort3):
+ SetExRegByte( P3LTC , 0x00 )
+ SetExRegByte( P3DIR , 0xbf )
+ SetExRegByte( P3CFG , 0xbf ) # can check TMROUT0
+/*
+ LED_YELLOW
+ WAIT_BUTTON
+*/
+/*
+ * Initialize Peripheral Pin Configurations:
+ * PIN 0 = 1, Select RTS1#
+ * PIN 1 = 1, Select DTR1#
+ * PIN 2 = 1, Select TXD1#
+ * PIN 3 = 1, Select CTS1#
+ * PIN 4 = 1, CS5
+ * PIN 5 = 1, Timer2 pins enabled
+ * PIN 6 = 0, Select CS6#
+ * PIN 7 = 0, Don't care
+ */
+
+SYM(InitPeriph):
+ SetExRegByte( PINCFG , 0x3f)
+/*
+ LED_GREEN
+ WAIT_BUTTON
+*/
+/*
+ * Initialize the Asynchronous Serial Ports:
+ * BIT 7 = 1, Internal SIO1 modem signals
+ * BIT 6 = 1, Internal SIO0 modem signals
+ * BIT 2 = 0, PSCLK for SSIO clock
+ * BIT 1 = 1, SERCLK for SIO1 clock
+ * BIT 0 = 1, SERCLK for SIO0 clock
+ */
+
+SYM(InitSIO):
+ SetExRegByte( SIOCFG, 0x00 ) # COMCLK -> baud-rate generator
+ # modem signals -> package pins
+ SetExRegByte( LCR0, 0x80 ) # latch DLL0, DLH0
+ SetExRegByte( DLL0, 0x01 ) # 0x0C sets to 9600 baud 0x6 = 19.2K
+ SetExRegByte( DLH0, 0x00 ) # 0x4 is 28.8K baud, 0x1 is 115K baud
+ SetExRegByte( LCR0, 0x03 ) # enable r/w buffers, IER0 accessible
+ # mode 8-n-1
+ SetExRegByte( IER0, 0x00 ) # no generated interrupts
+
+ SetExRegByte( LCR1, 0x80 ) # latch DLL0, DLH0
+ SetExRegByte( DLL1, 0x01 ) # 0x0C set to 9600 baud, 0x6 = 19.2K
+ SetExRegByte( DLH1, 0x00 ) # 0x4 is 28.8K baud
+ SetExRegByte( LCR1, 0x03 ) # enable r/w buffers, IER1 accessible
+ # reg 8-n-1
+ SetExRegByte( IER1, 0x00 ) # no generated intrrupts
+/*
+ LED_OFF
+ WAIT_BUTTON
+*/
+SYM(InitMCR):
+ SetExRegByte( MCR0, 0x03 ) # standard mode, RTS,DTR activated
+ SetExRegByte( MCR1, 0x03 ) # standard mode, RTS,DTR activated
+
+/*
+ * Initialize Timer for:
+ * BIT 7 = 1, Timer clocks disabled
+ * BIT 6 = 0, Reserved
+ * BIT 5 = 1, TMRCLK2 instead of Vcc to Gate2
+ * BIT 4 = 0, PSCLK to CLK2
+ * BIT 3 = 1, TMRCLK1 instead of Vcc to Gate1
+ * BIT 2 = 0, PSCLK to Gate1
+ * BIT 1 = 0, Vcc to Gate0
+ * BIT 0 = 0, PSCLK to Gate0
+ */
+/*
+ LED_YELLOW
+ WAIT_BUTTON
+*/
+SYM(InitTimer):
+ SetExRegByte(TMRCFG , 0x80 ) # All counters disabled, Gates 0,1
+ # and 2 are set to Vcc
+
+ SetExRegByte(TMRCON , 0x34 ) # prepare to write counter 0 LSB,MSB
+ SetExRegByte(TMR0 , 0x00 ) # sfa
+ SetExRegByte(TMR0 , 0x00 ) # sfa
+
+
+ SetExRegByte(TMRCON , 0x70 ) # mode 0 disables on Gate= Vcc
+ SetExRegByte(TMR1 , 0x00 ) # sfa
+ SetExRegByte(TMR1 , 0x00 ) # sfa
+
+ SetExRegByte(TMRCON , 0xB0 ) # mode 0 disables on gate =Vcc
+ SetExRegByte(TMR2 , 0x00 ) #
+ SetExRegByte(TMR2 , 0x00 ) #
+
+/*
+ LED_GREEN
+ WAIT_BUTTON
+*/
+/*
+ * Initialize the DMACFG register for:
+ * BIT 7 = 1 , Disable DACK#1
+ * BITs 6:4 = 100, TMROUT2 connected to DRQ1
+ * BIT 3 = 1 , Disable DACK0#
+ * BIT 2:0 = 000, Pin is connected to DRQ0
+ *
+ * NOTE: not 100% sure of this...
+ */
+
+ SetExRegByte(DMACFG , 0xC0 )
+ SetExRegByte(DMACMD1, 0x00 ) # disable both DMA channels
+ SetExRegByte(DMAMOD1, 0x40 ) # DMA0 single transer mode
+/*
+ LED_OFF
+ WAIT_BUTTON
+*/
+/*
+ * Initialize the INTCFG register for:
+ * BIT 7 = 0, 8259 cascade disabled
+ * BIT 3 = 0, SLAVE IR6 connected to Vss
+ * BIT 2 = 0, SLAVE IR5 connected to Vss
+ * BIT 1 = 0, SLAVE IR1 connected to SSIOINT
+ * BIT 0 = 0, SLAVE IR0 connected to Vss
+ *
+ * NOTE: not 100% sure of this either... Why IR5 active?
+ */
+
+SYM(InitInt):
+
+ cli # !
+/*
+ LED_YELLOW
+ WAIT_BUTTON
+*/
+ SetExRegByte(ICW1S , 0x11 ) # EDGE TRIGGERED
+ SetExRegByte(ICW2S , 0x28 ) # Slave base vector after Master
+ SetExRegByte(ICW3S , 0x02 ) # slave cascaded to IR2 on master
+ SetExRegByte(ICW4S , 0x01 ) # fully nested mode, no EOI
+
+ SetExRegByte(ICW1M , 0x11 ) # edge triggered
+ SetExRegByte(ICW2M , 0x20 ) # base vector starts at byte 32
+ SetExRegByte(ICW3M , 0x04) # internal slave cascaded from master IR2
+ SetExRegByte(ICW4M , 0x01 ) # idem
+
+ SetExRegByte(OCW1M , 0xfb ) # mask master IRQs, but not IR2 (cascade)
+ SetExRegByte(OCW1S , 0xff ) # mask all slave IRQs
+ SetExRegByte(INTCFG , 0x00 ) # slave IRs -> Vss or SSIOINT
+
+/* The i8259s_cache (IRQ mask) location is in BSS, which is zeroed later!
+ * So to initialize the cache we should do the following command after
+ * the BSS is zeroed, and in 32-bit protected mode.
+ *
+ * movw $0xFFFB, SYM(i8259s_cache)
+ *
+ */
+
+/*
+ NOTE: not sure about this so comment out...
+
+SYM(SetCS4):
+ SetExRegWord(CS4ADL , 0x702) #Configure chip select 4
+ SetExRegWord(CS4ADH , 0x00)
+ SetExRegWord(CS4MSKH, 0x03F)
+ SetExRegWord(CS4MSKL, 0xFC01)
+*/
+/*
+ LED_GREEN
+ WAIT_BUTTON
+*/
+/*****************************
+ * Load the Global Descriptor
+ * Table Register
+ ****************************/
+
+ movl $SYM(GDTR), eax
+ andl $0xFFFF, eax
+
+#ifdef NEW_GAS
+ addr32
+ data32
+#endif
+
+ lgdt (eax) # location of GDT in segment
+
+/*
+ NOTE: not sure about this either so comment out for now...
+SYM(SetUCS):
+ SetExRegWord(UCSADL, 0xC503) # values taken from TS-1325 memory
+ SetExRegWord(UCSADH, 0x000D)
+ SetExRegWord(UCSMSKH, 0x0000)
+ SetExRegWord(UCSMSKL, 0x3C01) # configure upper chip select
+*/
+/*
+ LED_OFF
+ WAIT_BUTTON
+*/
+/***************************
+ * Switch to Protected Mode
+ ***************************/
+ mov cr0, eax
+ orw $0x1, ax
+ mov eax, cr0
+
+/**************************
+ * Flush prefetch queue,
+ * and load CS selector
+ *********************/
+/*
+ LED_YELLOW
+ WAIT_BUTTON
+*/
+ ljmpl $ GDT_CODE_PTR , $ SYM(_load_segment_registers) # sets the code selector
+
+/*
+ * Load the segment registers
+ */
+SYM(_load_segment_registers):
+ .code32
+/*
+ LED_GREEN
+ WAIT_BUTTON
+*/
+ pLOAD_SEGMENT( GDT_DATA_PTR, fs)
+ pLOAD_SEGMENT( GDT_DATA_PTR, gs)
+ pLOAD_SEGMENT( GDT_DATA_PTR, ss)
+ pLOAD_SEGMENT( GDT_DATA_PTR, ds)
+ pLOAD_SEGMENT( GDT_DATA_PTR, es)
+
+/*
+ * Set up the stack
+ */
+/*
+ LED_OFF
+ WAIT_BUTTON
+*/
+SYM(lidtr):
+ lidt SYM(IDTR)
+/*
+ LED_YELLOW
+ WAIT_BUTTON
+*/
+SYM (_establish_stack):
+ movl $_ebss, eax # stack starts right after bss
+ movl $stack_origin, esp # this is the high starting address
+ movl $stack_origin, ebp
+/*
+ LED_GREEN
+ WAIT_BUTTON
+*/
+/*
+ * Zero out the BSS segment
+ */
+SYM (zero_bss):
+ cld # make direction flag count up
+ movl $ SYM (_ebss),ecx # find end of .bss
+ movl $ SYM (_bss_start),edi # edi = beginning of .bss
+ subl edi,ecx # ecx = size of .bss in bytes
+ shrl ecx # size of .bss in longs
+ shrl ecx
+ xorl eax,eax # value to clear out memory
+ repne # while ecx != 0
+ stosl # clear a long in the bss
+/*
+ * Now we can initialize the IRQ mask in i8259s_cache
+ */
+ movw $0xFFFB, SYM(i8259s_cache)
+/*
+ LED_YELLOW # Indicate ready to run
+ WAIT_BUTTON
+*/
+ LED_GREEN # Indicate RTEMS running!
+
+/*
+ * Transfer control to User's Board Support Package
+ */
+ pushl $0 # environp
+ pushl $0 # argv
+ pushl $0 # argc
+ call SYM(boot_card)
+ addl $12,esp
+
+ LED_RED # Indicate RTEMS exited
+/*
+ WAIT_BUTTON
+*/
+ cli # stops interrupts after hlt!
+ hlt # shutdown
+
+
+ .balign 4 # align tables to 4 byte boundary
+
+SYM(IDTR): DESC3( SYM(Interrupt_descriptor_table), 0x07ff );
+
+SYM(Interrupt_descriptor_table): /* Now in data section */
+ .rept 256
+ .word 0,0,0,0
+ .endr
+
+
+/*
+ * Use the first (null) entry in the the GDT as a self-pointer for the GDTR.
+ * (looks like a common trick)
+ */
+
+SYM (_Global_descriptor_table):
+SYM(GDTR): DESC3( GDTR, 0x17 ); # one less than the size
+ .word 0 # padding to DESC2 size
+SYM(GDT_CODE): DESC2(0xffff,0,0x0,0x9B,0xDF,0x00);
+SYM(GDT_DATA): DESC2(0xffff,0,0x0,0x92,0xDF,0x00); # was CF
+SYM(GDT_END):
+
+END
diff --git a/c/src/lib/libbsp/i386/ts_386ex/start/ts_1325.inc b/c/src/lib/libbsp/i386/ts_386ex/start/ts_1325.inc
new file mode 100644
index 0000000000..e10999abc0
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/start/ts_1325.inc
@@ -0,0 +1,50 @@
+/*
+ These are just some useful macros that control the TS-1325's
+ LEDs and push-button switch. Useful for debugging.
+
+ NOTE: This *must* be 16-bit compatible code to work in start.s
+
+ Tony Ambardar
+*/
+
+ .macro LED_OFF
+ movw $P1LTC, dx
+ inb dx, al
+ orb $0b01000000, al
+ andb $0b11011111, al
+ outb al, dx
+ .endm
+
+ .macro LED_GREEN
+ movw $P1LTC, dx
+ inb dx, al
+ orb $0b01100000, al
+ outb al, dx
+ .endm
+
+ .macro LED_YELLOW
+ movw $P1LTC, dx
+ inb dx, al
+ orb $0b00100000, al
+ andb $0b10111111, al
+ outb al, dx
+ .endm
+
+ .macro LED_RED
+ movw $P1LTC, dx
+ inb dx, al
+ andb $0b10011111, al
+ outb al, dx
+ .endm
+
+ .macro WAIT_BUTTON # Wait till the button is pressed for a bit.
+ movw $P1PIN, dx # ~25-30 cycles per loop, 25MHz -> 1 sec.
+ movl $300000,ecx # "Timer" count determines how long.
+0: inb dx, al
+ andb $0b00000001,al
+ jnz 0b # Button pressed?
+ decl ecx
+ jnz 0b # CX count expired?
+ .endm
+
+
diff --git a/c/src/lib/libbsp/i386/ts_386ex/startup/Makefile.in b/c/src/lib/libbsp/i386/ts_386ex/startup/Makefile.in
new file mode 100644
index 0000000000..89e2fce951
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/startup/Makefile.in
@@ -0,0 +1,79 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = ../../../../../../..
+subdir = c/src/lib/libbsp/i386/ts_386ex/startup
+
+INSTALL = @INSTALL@
+
+RTEMS_ROOT = $(top_srcdir)/@RTEMS_TOPdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+VPATH = @srcdir@:@srcdir@/../../../shared:@srcdir@/../../shared/comm:@srcdir@/../../shared/irq:@srcdir@/../../shared/io
+
+PGM=${ARCH}/startup.rel
+
+# C source names, if any, go here -- minus the .c
+C_PIECES=bspclean bsplibc bsppost bspstart main sbrk irq irq_init i386-stub-glue uart i386-stub
+
+C_FILES=$(C_PIECES:%=%.c)
+C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
+
+H_FILES=
+
+# Assembly source names, if any, go here -- minus the .S
+# removed initcsu piece, ldsegs piece and flush
+S_PIECES=irq_asm
+S_FILES=$(S_PIECES:%=%.S)
+S_O_FILES=$(S_FILES:%.S=${ARCH}/%.o)
+
+SRCS=$(srcdir)/linkcmds $(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES)
+OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES)
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+#DEFINES += -DPRINTON
+
+DEFINES += -I$(srcdir)
+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 +=
+
+preinstall:
+ $(INSTALL_CHANGE) ${IMPORT_SRC} .
+
+# ${CP} ${IMPORT_SRC} .
+
+${PGM}: ${SRCS} ${OBJS}
+ $(make-rel)
+all: ${ARCH} preinstall $(SRCS) $(PGM)
+ $(INSTALL_CHANGE) $(srcdir)/linkcmds ${PROJECT_RELEASE}/lib
+
+# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
+install: all
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
diff --git a/c/src/lib/libbsp/i386/ts_386ex/startup/README b/c/src/lib/libbsp/i386/ts_386ex/startup/README
new file mode 100644
index 0000000000..17fde76a91
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/startup/README
@@ -0,0 +1,17 @@
+#
+# $Id$
+#
+
+
+The requirements for this BSP are only that the GAS used supports the
+.code16 directive. The GAS released with any GCC version 2.8.0 or better
+is required. The BSP was built with an egcs snapshot pre-1.0.2 and
+post-1.0.1. However, any egcs should work.
+
+
+The only "real" differences are in bspstart.c, where the initialization now
+configures all available RAM, (after setting up the Workspaces) as heap.
+The location of the stack was changed so that the heap was not trapped
+between low memory and the stack; the stack comes before the heap.
+
+
diff --git a/c/src/lib/libbsp/i386/ts_386ex/startup/bspstart.c b/c/src/lib/libbsp/i386/ts_386ex/startup/bspstart.c
new file mode 100644
index 0000000000..c0e92617e8
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/startup/bspstart.c
@@ -0,0 +1,161 @@
+/*
+ * 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-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.
+ *
+ * Ported to the i386ex and submitted by:
+ *
+ * Erik Ivanenko
+ * University of Toronto
+ * erik.ivanenko@utoronto.ca
+ *
+ * $Id$
+ */
+
+void bsp_clean_up(void);
+
+#include <bsp.h>
+#include <rtems/libio.h>
+
+#include <libcsupport.h>
+
+/*
+ * The original table from the application and our copy of it with
+ * some changes.
+ */
+
+extern rtems_configuration_table Configuration;
+rtems_configuration_table BSP_Configuration;
+
+rtems_cpu_table Cpu_table;
+
+/*
+ * Tells us where to put the workspace in case remote debugger is present.
+ */
+
+extern rtems_unsigned32 rdb_start;
+
+/*
+ * Use the shared implementations of the following routines
+ */
+
+void bsp_postdriver_hook(void);
+void bsp_libc_init( void *, unsigned32, int );
+
+/*
+ * Function: bsp_pretasking_hook
+ * Created: 95/03/10
+ *
+ * Description:
+ * BSP pretasking hook. Called just before drivers are initialized.
+ * Used to setup libc and install any BSP extensions.
+ *
+ * NOTES:
+ * Must not use libc (to do io) from here, since drivers are
+ * not yet initialized.
+ *
+ */
+
+void bsp_pretasking_hook(void)
+{
+ extern int heap_bottom;
+ rtems_unsigned32 heap_start;
+ rtems_unsigned32 heap_size;
+
+ heap_start = (rtems_unsigned32) &heap_bottom;
+ if (heap_start & (CPU_ALIGNMENT-1))
+ heap_start = (heap_start + CPU_ALIGNMENT) & ~(CPU_ALIGNMENT-1);
+
+ heap_size = BSP_Configuration.work_space_start -(void *) heap_start ;
+ heap_size &= 0xfffffff0; /* keep it as a multiple of 16 bytes */
+
+ heap_size &= 0xfffffff0; /* keep it as a multiple of 16 bytes */
+ bsp_libc_init((void *) heap_start, heap_size, 0);
+
+
+#ifdef RTEMS_DEBUG
+ rtems_debug_enable( RTEMS_DEBUG_ALL_MASK );
+#endif
+}
+
+/*
+ * bsp_start
+ *
+ * This routine does the bulk of the system initialization.
+ */
+
+void bsp_start( void )
+{
+ /*
+ * we do not use the pretasking_hook.
+ */
+
+ Cpu_table.pretasking_hook = bsp_pretasking_hook; /* init libc, etc. */
+ Cpu_table.postdriver_hook = bsp_postdriver_hook;
+ Cpu_table.interrupt_table_segment = get_ds();
+ Cpu_table.interrupt_table_offset = (void *)Interrupt_descriptor_table;
+ Cpu_table.interrupt_stack_size = 8192;
+ /*
+#if defined(RTEMS_POSIX_API)
+ BSP_Configuration.work_space_size *= 3;
+#endif
+ */
+ BSP_Configuration.work_space_start = (void *)
+ RAM_END - BSP_Configuration.work_space_size;
+
+ /*
+ * Account for the console's resources
+ */
+ console_reserve_resources( &BSP_Configuration );
+
+ /*
+ * Init rtems_interrupt_management
+ */
+ rtems_irq_mngt_init();
+
+ /*
+ * Init rtems exceptions management
+ */
+ rtems_exception_init_mngt();
+
+ /*
+ * The following information is very useful when debugging.
+ */
+
+#ifdef BSP_DEBUG
+ printk( "RAM_START = 0x%x\nRAM_END = 0x%x\n", RAM_START, RAM_END );
+ printk( "work_space_start = 0x%x\n",
+ BSP_Configuration.work_space_start );
+ printk( "work_space_size = 0x%x\n",
+ BSP_Configuration.work_space_size );
+ printk( "maximum_extensions = 0x%x\n",
+ BSP_Configuration.maximum_extensions );
+ printk( "microseconds_per_tick = 0x%x\n",
+ BSP_Configuration.microseconds_per_tick );
+ printk( "ticks_per_timeslice = 0x%x\n",
+ BSP_Configuration.ticks_per_timeslice );
+ printk( "maximum_devices = 0x%x\n",
+ BSP_Configuration.maximum_devices );
+ printk( "number_of_device_drivers = 0x%x\n",
+ BSP_Configuration.number_of_device_drivers );
+ printk( "Device_driver_table = 0x%x\n",
+ BSP_Configuration.Device_driver_table );
+
+ /* printk( "_heap_size = 0x%x\n", _heap_size );
+ printk( "_stack_size = 0x%x\n", _stack_size ); */
+#endif
+}
+
+void bsp_clean_up(void) {
+ printk("bsp_cleanup called\n");
+}
+
diff --git a/c/src/lib/libbsp/i386/ts_386ex/startup/linkcmds b/c/src/lib/libbsp/i386/ts_386ex/startup/linkcmds
new file mode 100644
index 0000000000..99911126bb
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/startup/linkcmds
@@ -0,0 +1,124 @@
+/*
+ * This file contains directives for the GNU linker which are specific
+ * to the Technologic Systems TS-1325 (i386ex) board.
+ *
+ * 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$
+ *
+ * Memory layout:
+ *
+ * 0x0008000 -> ... : initial section ( init 386ex, goto protected mode)
+ * ... -> ... : text section ( executable code )
+ * ... -> 0x00A0000 : data section ( initialized storage )
+ * 0x0100000 -> 0x0200000 : bss section, stack space, heap storage
+ */
+
+ ENTRY(_init_i386ex) ;
+SECTIONS
+{
+
+/***************************************************************************
+ * initial section:
+ *
+ * This section is the first in memory, preceding the text and data sections.
+ * It initializes the i386ex, sets up the gdt in RAM, loads the gdt,
+ * jumps to protected mode, loads the idt, zeros the bss section, sets up
+ * the stack and calls the rest of the RTEMS initialization.
+ ***************************************************************************/
+
+ _DOS_ld_addr = 0x0008000 ;
+
+ .initial _DOS_ld_addr :
+ {
+ *(.initial);
+ }
+
+/***************************************************************************
+ * text section:
+ *
+ * Nobody here but us opcodes.
+ ***************************************************************************/
+
+ .text BLOCK(0x10) :
+ {
+ CREATE_OBJECT_SYMBOLS
+ text_start = . ;
+ _text_start = . ;
+ *(.text ) ;
+ . = ALIGN (16);
+
+ *(.eh_fram)
+ . = ALIGN (16);
+
+ /*
+ * C++ constructors
+ */
+ __CTOR_LIST__ = .;
+ LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
+ *(.ctors)
+ LONG(0)
+ __CTOR_END__ = .;
+ . = ALIGN (4) ;
+ __DTOR_LIST__ = .;
+ LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
+ *(.dtors)
+ LONG(0)
+ __DTOR_END__ = .;
+ _rodata_start = . ;
+ *(.rodata)
+ *(.gnu.linkonce.r*)
+ _erodata = ALIGN( 0x10 ) ;
+ _etext = ALIGN( 0x10 );
+ _endtext = . ;
+ }
+
+/***************************************************************************
+ * data section:
+ *
+ * This section defines the location of the data section in RAM.
+ ***************************************************************************/
+
+ .data BLOCK(0x10) :
+ {
+ _sdata = .;
+ *(.data);
+ _edata = .;
+ }
+ _data_size = _edata - _sdata ;
+
+/***************************************************************************
+ * bss section:
+ *
+ * The bss section is the first section in extended RAM ( > 1MB).
+ ***************************************************************************/
+
+ .bss 0x100000 (NOLOAD) :
+ {
+ _bss_start = .;
+ *(.bss);
+ *(COMMON);
+ _ebss = ALIGN(0x10);
+ }
+ _bss_size = _ebss - _bss_start ;
+
+/***************************************************************************
+ * General variables:
+ *
+ * The stack_size variable is customizable here. The heap is located directly
+ * after the stack in RAM. A routine within bspstart.c uses these variables
+ * to ensure that the heap used by RTEMS is as large as the RAM remaining
+ * after all workspace configurations are complete.
+ ***************************************************************************/
+
+ stack_size = 0x8000 ;
+ stack_origin = _ebss + stack_size ;
+ heap_bottom = stack_origin + 4 ;
+
+}
diff --git a/c/src/lib/libbsp/i386/ts_386ex/startup/setvec.c b/c/src/lib/libbsp/i386/ts_386ex/startup/setvec.c
new file mode 100644
index 0000000000..9e7a0e758d
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/startup/setvec.c
@@ -0,0 +1,55 @@
+/* set_vector
+ *
+ * This routine installs an interrupt vector on the Force CPU-386.
+ *
+ * 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-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$
+ */
+
+#include <rtems.h>
+#include <bsp.h>
+
+i386_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 */
+)
+{
+ i386_isr_entry previous_isr;
+ interrupt_gate_descriptor idt;
+
+ if ( type )
+ rtems_interrupt_catch( handler, vector, (rtems_isr_entry *) &previous_isr );
+ else {
+ /* get the address of the old handler */
+
+ idt = Interrupt_descriptor_table[ vector ];
+
+ previous_isr = (i386_isr_entry)
+ ((idt.offset_16_31 << 16) | idt.offset_0_15);
+
+ /* build the IDT entry */
+ create_interrupt_gate_descriptor( &idt, handler );
+
+ /* install the IDT entry */
+ Interrupt_descriptor_table[ vector ] = idt;
+ }
+ return previous_isr;
+}
+
diff --git a/c/src/lib/libbsp/i386/ts_386ex/timer/Makefile.in b/c/src/lib/libbsp/i386/ts_386ex/timer/Makefile.in
new file mode 100644
index 0000000000..729885a081
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/timer/Makefile.in
@@ -0,0 +1,70 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = ../../../../../../..
+subdir = c/src/lib/libbsp/i386/ts_386ex/timer
+
+INSTALL = @INSTALL@
+
+RTEMS_ROOT = $(top_srcdir)/@RTEMS_TOPdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+VPATH = @srcdir@
+
+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=timerisr
+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_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_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
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
diff --git a/c/src/lib/libbsp/i386/ts_386ex/timer/timer.c b/c/src/lib/libbsp/i386/ts_386ex/timer/timer.c
new file mode 100644
index 0000000000..fbbe92e347
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/timer/timer.c
@@ -0,0 +1,195 @@
+/* Timer_init()
+ *
+ * This routine initializes the timer on the FORCE CPU-386 board.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * NOTE: This routine will not work if the optimizer is enabled
+ * for some compilers. The multiple writes to the Z8036
+ * may be optimized away.
+ *
+ * It is important that the timer start/stop overhead be
+ * determined when porting or modifying this code.
+ *
+ * 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$
+ */
+
+
+#include <rtems.h>
+#include <bsp.h>
+#include <stdlib.h>
+
+volatile rtems_unsigned32 Ttimer_val; /* Updated from ISR!!! */
+rtems_boolean Timer_driver_Find_average_overhead;
+
+extern void timerisr();
+
+/*
+ * Number of us per timer interrupt. Note: 1 us == 1 tick.
+ */
+
+#define US_PER_ISR 250
+
+void TimerOn(const rtems_raw_irq_connect_data* used)
+{
+
+ Ttimer_val = 0; /* clear timer ISR count */
+
+ /* Select timer, stay in mode 0 */
+ outport_byte (TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
+
+ /* Set to 250 usec interval */
+ outport_byte (TIMER_CNTR0, US_PER_ISR & 0xFF );
+ outport_byte (TIMER_CNTR0, (US_PER_ISR >> 8) & 0xFF );
+
+ /* Enable all timers */
+ outport_byte (TIMER_CONFIG, 0x00);
+
+ /*
+ * enable interrrupt at i8259 level
+ */
+ BSP_irq_enable_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE);
+}
+
+static int TimerIsOn (const rtems_raw_irq_connect_data *used)
+{
+ return BSP_irq_enabled_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE);
+}
+
+void TimerOff(const rtems_raw_irq_connect_data* used)
+{
+ /* Disable all timers */
+ outport_byte (TIMER_CONFIG, 0x80);
+
+ /*
+ * disable interrrupt at i8259 level
+ */
+ BSP_irq_disable_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE);
+ /* reset timer mode to standard (DOS) value */
+}
+
+static rtems_raw_irq_connect_data timer_raw_irq_data = {
+ BSP_PERIODIC_TIMER + BSP_IRQ_VECTOR_BASE,
+ timerisr,
+ TimerOn,
+ TimerOff,
+ TimerIsOn
+};
+
+static rtems_raw_irq_connect_data old_raw_irq_data = {
+ BSP_PERIODIC_TIMER + BSP_IRQ_VECTOR_BASE,
+};
+
+void Timer_exit()
+{
+ if (!i386_delete_idt_entry(&timer_raw_irq_data)) {
+ printk("Timer_exit:Timer raw handler removal failed\n");
+ rtems_fatal_error_occurred(1);
+ }
+}
+
+void Timer_initialize(void)
+{
+
+ static rtems_boolean First = TRUE;
+
+ if (First)
+ {
+ First = FALSE;
+
+ if (!i386_get_current_idt_entry (&old_raw_irq_data)) {
+ printk("Timer_initialize: failed to get old raw irq entry.\n");
+ rtems_fatal_error_occurred(1);
+ }
+
+ if (!i386_delete_idt_entry (&old_raw_irq_data)) {
+ printk("Timer_initialize: failed to delete old raw irq entry.\n");
+ rtems_fatal_error_occurred(1);
+ }
+
+ atexit(Timer_exit); /* Try not to hose the system at exit. */
+ if (!i386_set_idt_entry (&timer_raw_irq_data)) {
+ printk("Timer_initialize: raw handler installation failed.\n");
+ rtems_fatal_error_occurred(1);
+ }
+ }
+
+ /* wait for ISR to be called at least once */
+ Ttimer_val = 0;
+ while (Ttimer_val == 0)
+ continue;
+ Ttimer_val = 0;
+}
+
+
+#define AVG_OVERHEAD 3 /* It typically takes 3.0 microseconds */
+ /* (3 ticks) to start/stop the timer. */
+#define LEAST_VALID 4 /* Don't trust a value lower than this */
+
+int Read_timer(void)
+{
+ register rtems_unsigned32 clicks, total;
+ register rtems_unsigned8 lsb, msb;
+
+ /* latch the count */
+ outport_byte (TIMER_MODE, TIMER_SEL0|TIMER_LATCH );
+
+ /* read the count */
+ inport_byte (TIMER_CNTR0, lsb );
+ inport_byte (TIMER_CNTR0, msb );
+
+ /*
+ * Timer ISR increments Ttimer_val every US_PER_ISR clock ticks,
+ * where 1 tick == 1 us. Below, 'click' is in microseconds.
+ *
+ * This assumes the timer input clocks are sourced from the system's
+ * prescaled clock (PSCLK), which is set to be at 1MHz.
+ */
+ clicks = (msb << 8) | lsb;
+ total = Ttimer_val * US_PER_ISR + (US_PER_ISR - clicks);
+
+ if ( Timer_driver_Find_average_overhead == 1 )
+ return total; /* in one microsecond units */
+ else if ( total < LEAST_VALID )
+ return 0; /* below timer resolution */
+ else
+ return (total - AVG_OVERHEAD);
+}
+
+rtems_status_code Empty_function( void )
+{
+ return RTEMS_SUCCESSFUL;
+}
+
+void Set_find_average_overhead(
+ rtems_boolean find_flag
+)
+{
+ Timer_driver_Find_average_overhead = find_flag;
+}
+
+/*
+ * Wait_X_ms: a delay loop used by the network driver...
+ */
+
+#define SLOW_DOWN_IO 0x80 /* I/O port which does nothing */
+#define LOOP1MS 320 /* Just a guess.... */
+
+void Wait_X_ms (unsigned timeToWait)
+{
+ unsigned i, j;
+
+ for (j=0; j<timeToWait; j++)
+ for (i=0; i<LOOP1MS; i++)
+ outport_byte (SLOW_DOWN_IO, 0);
+}
diff --git a/c/src/lib/libbsp/i386/ts_386ex/timer/timerisr.S b/c/src/lib/libbsp/i386/ts_386ex/timer/timerisr.S
new file mode 100644
index 0000000000..606fc9ae2b
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/timer/timerisr.S
@@ -0,0 +1,40 @@
+/* timer_isr()
+ *
+ * This routine provides the ISR for the Z8036 timer on the MVME136
+ * board. The timer is set up to generate an interrupt at maximum
+ * intervals.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * 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$
+ */
+
+#include "asm.h"
+
+ BEGIN_CODE
+
+ EXTERN (Ttimer_val)
+
+ PUBLIC (timerisr)
+SYM (timerisr):
+ incl SYM (Ttimer_val) # add another tick
+ pushl eax
+ movb 0xa0,al /* signal generic End Of Interrupt (EOI) to slave PIC */
+ outb al, $0x20
+ movb $0x20, al
+ outb al, $0x20 /* signal generic EOI to Master PIC */
+ popl eax
+ iret
+
+END_CODE
+END
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/Makefile.in b/c/src/lib/libbsp/i386/ts_386ex/tools/Makefile.in
new file mode 100644
index 0000000000..a3963fc909
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/Makefile.in
@@ -0,0 +1,26 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = ../../../../../../..
+subdir = c/src/lib/libbsp/i386/ts_386ex/timer
+
+INSTALL = @INSTALL@
+
+RTEMS_ROOT = $(top_srcdir)/@RTEMS_TOPdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+VPATH = @srcdir@
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+
+CLEAN_ADDITIONS +=
+CLOBBER_ADDITIONS +=
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/README b/c/src/lib/libbsp/i386/ts_386ex/tools/README
new file mode 100644
index 0000000000..97f54cc0f0
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/README
@@ -0,0 +1,68 @@
+This directory contains various support software for using RTEMS on
+the TS-1325. Descriptions follow.
+
+
+DOS Loader
+==========
+
+The dos_sup directory contains a DOS-based loader (loader.com) for
+RTEMS executables on the TS-1325. Fully commented source code is
+included.
+
+Once an application has been compiled and the resulting COFF
+executable converted to raw binary format and transferred to the
+TS-1325, the DOS loader program must be used to load and execute
+it. The loader is simply invoked as "loader filename", where the
+filename cannot contain an explicit path.
+
+The loader will work with files stored either on the C: ram disk or
+the A: flash disk. Since Zmodem transfers to the C: ram disk are much
+faster than to the A: disk, most development work will be done using
+the C: disk. Once completed, an application may copied to the
+(non-volatile) A: disk. Additionally, one may add the line "loader
+filename" to the AUTOEXEC.BAT file, allow ing the application to be
+run automatically at boot time.
+
+Note that the DOS loader will abort and exit if it detects that the
+push-button switch is pressed, thus allowing one to break out of a
+patho logical "boot loop" situation.
+
+
+coff2bin
+========
+
+The coff2bin script is just a convenient wrapper for the objcopy
+command. It can convert a list of RTEMS-generated COFF files to raw
+binary images that can be loaded on the TS-1325. The converted files
+are saved in the current directory with a ".bin" extension.
+
+
+TS-1325 Ada95 Support
+=====================
+
+The TS-1325 includes a few peripherals which are very useful for
+embedded development: a push-button switch, an LED, and a parallel
+port which may be used for digital I/O. Note that the pinout for the
+parallel port is given in the TS-1325 manual.
+
+These devices are all supported by Ada packages allowing easy access;
+they may be found in the ts_1325_ada directory. Doing a make command
+here will build a program that tests and exercises all these support
+packages. Plugging in some kind of parallel-port "loop-back" connector
+would be useful during this test.
+
+Brief descriptions of the main packages are as follows:
+
+* ts1325-button: allows one to check or wait for a button press.
+
+* ts1325-led: allows safe reading and setting of the LED colour.
+
+* ts1325-parallel: used to read and write byte date to the parallel
+ port.
+
+* i386_ports: code to access the I/O address space, using Ada
+ inline assembly.
+
+
+Tony Ambardar, 4/21/99
+
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/coff2bin b/c/src/lib/libbsp/i386/ts_386ex/tools/coff2bin
new file mode 100755
index 0000000000..fbe5ed5ca3
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/coff2bin
@@ -0,0 +1,23 @@
+#!/bin/sh
+# Just a Q&D prog to convert a bunch of RTEMS generated COFF files to raw
+# binary images that can be loaded on the TS-1325. The converted files are
+# saved in the current directory.
+#
+# Tony Ambardar
+
+OBJCOPY=/usr/local/rtems/bin/i386-rtems-objcopy
+
+if [ $# = 0 ]
+then
+ echo "Description: Convert RTEMS coff files to raw binary files."
+ echo "Usage: coff2bin <list-of-coff-files>"
+ echo
+ exit 1
+fi
+
+for i in $*
+do
+ OUTFILE=$(basename `echo $i | sed 's/\.[a-zA-Z0-9]*$//g'`.bin)
+ $OBJCOPY -O binary $i $OUTFILE
+done
+
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/dos_sup/loader.com b/c/src/lib/libbsp/i386/ts_386ex/tools/dos_sup/loader.com
new file mode 100644
index 0000000000..945a7d2339
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/dos_sup/loader.com
Binary files differ
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/dos_sup/loader_hybrid_com.asm b/c/src/lib/libbsp/i386/ts_386ex/tools/dos_sup/loader_hybrid_com.asm
new file mode 100644
index 0000000000..cd951ec8fd
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/dos_sup/loader_hybrid_com.asm
@@ -0,0 +1,575 @@
+; loader_hybrid_com.asm
+;
+; This is a DOS command-line loader for RTEMS executables running on
+; the Technologic Systems TS-1325 Embedded PC.
+;
+; It loads a DOS file given on the command line to the address `KernelBase',
+; and then transfers control there. It uses DOS file I/O commands to read from
+; the A: flash disk, and direct memory access to read from the C: ramdisk.
+;
+; Copying uses protected flat mode, so kernelbase could be above 1MB.
+; It does not initialize protected mode before transferring control
+; to the RTEMS executable image.
+;
+; Compile with: nasm -o loader.com loader_hybrid_com.asm
+;
+; Tony Ambardar (c) 1999
+; E.C.E. Department
+; University of British Columbia
+
+%include "ts1325.inc" ; Some useful LED and button macros
+
+; IMPORTANT: [org xxx] MUST be the same as RelocAddr below.
+
+[org E000h]
+[bits 16]
+
+; Only these three definitions may need to change
+
+KernelBase equ 08000h ; Where (32-bit) to locate and run RTEMS executable
+
+RelocSeg equ 9000h ; Segment to relocate code.
+RelocAddr equ 0E000h ; Address to relocate code, same as "org" above
+
+; Next three used in GDT
+
+RelocBase equ RelocSeg*16
+Reloc15 equ RelocBase & 0FFFFh
+Reloc23 equ RelocBase / 10000h
+
+Buffer equ RelocAddr+400h ; In same segment as RelocSeg
+BuffSiz equ 200h ; Size of disk read + copy
+
+StackSeg equ RelocSeg
+StackSiz equ 40h
+StackAddr equ Buffer+BuffSiz+StackSiz
+
+; Used to jump to kernel in real mode
+
+KernelAddr equ KernelBase & 0FFFFh
+KernelSeg equ (KernelBase - KernelAddr) / 16
+
+; Used to load from the ramdisk
+
+Extended equ 100000h ; Start of extended memory / C: ramdisk
+OffsetBPB equ 0Bh ; Start of BIOS param block in bootsector
+
+; Command-line parameters
+
+ParamLen equ 80h ; Byte length of command line params
+ParamStr equ 82h ; Start of param string
+
+; The ORG address above means pre-relocation addresses are wrong. The
+; following macro fixes these up.
+
+%define PRE_RELOC_ADDR(addr) (addr-CodeStart+100h)
+
+CodeStart:
+
+mov dx, PRE_RELOC_ADDR(Greet)
+mov ah, 9h
+int 21h
+
+mov ax, 0b021h ; Exit to DOS if push-button switch pressed
+int 15h
+and al, 01h ; Bit 0 == 0 if button pressed
+jz ButtonExit
+
+xor cx, cx
+mov cl, [ParamLen] ; See if there is a command line arg
+jcxz NameError
+
+dec cx ; Nix leading space. Is this standard?
+cmp cx, 12 ; Limit to 12 chars: e.g. ABCDEFGH.IJK
+jg NameError
+ ; Damn. Should make sure of no ':' or '\' chars too.
+
+; Required by "relocated" [org] statement above
+
+mov di, PRE_RELOC_ADDR(FName)
+mov si, ParamStr
+repne
+movsb ; Copy command line arg
+
+; Make sure no ':' in filename. This forces using the default dir.
+
+mov di, PRE_RELOC_ADDR(FName)
+mov al, ':'
+mov cx, 12
+repne
+scasb
+je NameError
+
+jmp Relocate
+
+ButtonExit:
+mov dx, PRE_RELOC_ADDR(Button)
+jmp short DosPrint
+
+NameError:
+mov dx, PRE_RELOC_ADDR(FError)
+jmp short DosPrint
+
+DosError: ; Only call this AFTER relocation
+mov dx, RError
+
+DosPrint:
+mov ah, 9h
+int 21h
+
+DosExit:
+mov ax, 04C00h ; DOS Function: Exit program
+int 21h ; Call DOS. Terminate Program
+
+Relocate: ; Move this code down to RelocAddr
+
+cld
+mov ax, RelocSeg
+mov es, ax ; Set destination = RelocSeg:RelocAddr
+mov di, RelocAddr
+mov si, 100h ; Source is ds:0100h i.e. a COM file
+mov cx, CodeEnd - CodeStart ; Size of all code
+
+repne
+movsb
+
+; continue in copied code
+
+jmp RelocSeg:RelocAddr + (RelocStart - CodeStart)
+
+RelocStart:
+cli
+mov ax, StackSeg
+mov ss, ax
+mov sp, StackAddr
+mov ax, cs
+mov ds, ax
+mov es, ax ; Setup segments and stack
+sti
+
+mov ah, 19h
+int 21h
+mov [DDrive], al ; Save current default drive
+
+mov ax, 3d00h ; DOS Function: Open the file for reading
+mov dx, FName ; Presume DS points at filename segment
+int 21h
+jc DosError
+
+GoodOpen:
+mov [FHndl], ax ; Save file handle
+
+mov al, [DDrive] ; Check if loading from C: drive (ramdisk)
+cmp al, 2
+je LoadRamdisk
+
+LoadDosdisk:
+
+; Here we are loading from A: drive. Use DOS calls to load the file into
+; extended memory. Then copy from extended memory to `KernelBase'. This way
+; we avoid overwriting DOS file I/O structures if reading directly into
+; conventional (<640K) memory.
+
+mov edi, Extended ; Destination for code read @ 1 Meg
+
+ReadLoop:
+
+mov ah,3fh ; DOS Function: Read data from the file
+mov bx, [FHndl]
+mov dx, Buffer ; Address of data buffer
+mov cx, BuffSiz ; Request BuffSiz bytes
+int 21h
+jc DosError
+
+GoodRead:
+
+cmp ax, cx ; EOF reached? AX = # bytes read
+pushf
+
+add ax, 3
+shr ax, 2 ; Copy buffer by dwords, # = (ax + 3)/4
+movzx ecx, ax
+mov esi, RelocBase + Buffer ; Source for copy, destination is in edi
+
+call CopyData32 ; Do protected-mode copy
+
+popf
+je ReadLoop ; Still data left, so read next chunk
+
+mov esi, Extended ; Source for copy @ 1 Meg
+mov ecx, edi ; Make count in dwords
+sub ecx, esi
+add ecx, 3
+shr ecx, 2
+mov edi, KernelBase ; Destination copy
+
+call CopyData32 ; Move code into conventional memory
+jmp RunKernel
+
+LoadRamdisk:
+
+; Here we are loading from C: drive. Use protected mode to directly access
+; the virtual disk sectors in extended memory and copy to `KernelBase'.
+; This way we avoid using DOS file I/O calls, except for an `open' earlier
+; which tells us the file exists.
+
+; Copy C: "bootsector" to buffer and save the BIOS parameter block
+
+mov esi, Extended
+mov edi, RelocBase + Buffer ; Must be a 32-but address...
+mov ecx, 80h
+call CopyData32
+
+mov si, Buffer + OffsetBPB
+mov di, SavBPB
+mov cx, EndBPB - SavBPB
+repne
+movsb
+
+; Calculate FAT, root dir, and data start addresses for the ramdisk
+
+xor eax, eax
+mov ebx, eax
+mov ecx, ebx
+
+mov ax, [ResSec]
+
+mov bl, [NumFAT]
+imul bx, [SecFAT]
+
+mov cx, [NRoot]
+shr cx, 4 ; 10h directory entries per sector
+
+add bx, ax
+add cx, bx
+
+mov dx, [BpSect]
+imul ax, dx
+imul bx, dx
+imul cx, dx
+
+add eax, Extended
+add ebx, Extended
+add ecx, Extended
+
+mov [BegFAT], eax
+mov [BegRoot], ebx
+mov [BegData], ecx
+
+; Convert the saved filename to format used in directory entry. Assume
+; there's a `.' in it. Hopefully this won't haunt us later...
+
+mov di, FName ; Find the `.'
+mov al, '.'
+mov cx, 12
+repne
+scasb
+
+mov bx, di ; di points to filename extension
+
+mov di, DirName
+mov si, FName
+mov cx, bx ; Make count
+sub cx, si
+dec cx
+repne ; Copy initial part of filename
+movsb
+
+mov di, bx ; Find the terminating zero
+xor al,al
+mov cx, 4
+repne
+scasb
+
+mov cx, di ; Make count
+sub cx, bx
+dec cx
+mov si, bx
+mov di, DirName + 8
+repne ; Copy filename extension
+movsb
+
+mov si, DirName ; Convert the stupid thing to upper case
+mov di, si
+mov cx, 11
+
+Cvt2Upper:
+
+lodsb
+cmp al, 'a'
+jb NotLow
+cmp al, 'z'
+ja NotLow
+xor al, 20h
+
+NotLow:
+
+stosb
+loop Cvt2Upper
+
+; Now load in the root directory (temporarily) to find the first cluster
+; of our file. Use KernelSeg:KernelAddr as temporary storage.
+
+mov esi, [BegRoot]
+mov edi, KernelBase
+xor ecx, ecx
+mov cx, [NRoot]
+shl cx, 3 ; Each root entry is 8 dwords
+call CopyData32
+
+mov dx, [NRoot] ; Max # of dir entries
+
+mov cx, KernelSeg ; Setup segment selector for comparison
+mov es, cx
+mov di, KernelAddr
+
+FindEntry:
+
+mov cx, 11
+mov si, DirName
+push di
+rep cmpsb
+pop di
+je GotEntry
+add di, 20h ; Point to next dir entry
+dec dx
+jnz FindEntry
+
+int 3h ; Should never get here...
+
+GotEntry:
+
+mov eax, KernelBase ; Setup initial address for copy
+mov [CurrDst], eax
+
+add di, 32 - 6 ; Load first cluster number
+mov ax, [es:di]
+mov cx, ds ; Fix `es' selector just in case
+mov es, cx
+
+LoadKernel:
+
+call LoadCluster ; Load cluster `ax' to [CurrDst], update [CurrDst]
+
+call NextCluster ; Get next cluster number in ax
+
+cmp ax, 0FF8h ; Repeat until EOF
+jb LoadKernel
+
+RunKernel:
+
+mov ax, KernelSeg ; Setup data segment and transfer control
+mov ds, ax
+
+jmp KernelSeg:KernelAddr ; Huzzah!!
+
+
+; Load cluster `ax' to [CurrDst], update [CurrDst]
+
+LoadCluster:
+
+push ax
+sub ax, 2 ; Cluster numbers start at 2
+movzx eax, ax
+
+xor ecx, ecx ; Calculate bytes in a cluster
+mov cl, [SpClst]
+imul cx, [BpSect]
+
+imul eax, ecx
+add eax, [BegData] ; Start of cluster
+
+shr ecx, 2 ; Cluster size in dwords
+mov esi, eax ; Copy source
+mov edi, [CurrDst] ; Copy destination
+call CopyData32
+
+mov [CurrDst], edi ; Update dest
+pop ax ; Restore cluster number
+
+ret
+
+; Search FAT (FAT12 format) for next cluster in file after `ax'.
+
+NextCluster:
+
+movzx ecx, ax ; Calculate offset into FAT
+shr ax, 1
+pushf
+add cx, ax
+
+mov esi, [BegFAT] ; Copy word containing next cluster to buffer
+add esi, ecx
+mov edi, RelocBase + Buffer
+xor ecx, ecx
+inc ecx
+call CopyData32
+
+mov ax, [Buffer] ; Handle odd/even cluster numbers
+popf
+jnc EvenCluster
+shr ax, 4
+
+EvenCluster:
+
+and ax, 0FFFh
+ret
+
+; Enable the A20 line for accesses to extended memory.
+
+EnableA20:
+ in al,92h
+ or al,2
+ jmp short $+2
+ jmp short $+2
+ jmp short $+2
+ out 92h,al
+ ret
+
+; The CopyData32 routine copies ecx dwords from esi to edi. Both esi
+; and edi hold 32-bit values. CopyData32 runs in 32-bit protected mode.
+
+CopyData32:
+ cli
+
+ call EnableA20 ; Put here in case file I/O screws with this
+ ; or with the GDTR
+
+ lgdt [GDTStart] ; Initialize GDTR for 32-bit protected mode
+
+ mov eax, cr0
+ or al, 1
+ mov cr0, eax ;go to real flat mode
+
+; LED_GRN
+; PSW_WAIT
+
+ jmp dword 8h : RelocBase+ProtJmp
+[bits 32]
+ProtJmp:
+; LED_YEL
+; PSW_WAIT
+
+ mov ax, 10h
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+
+ rep movsd ;copy the sector to where it should be
+
+ mov ax, 20h
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+
+; LED_RED
+; PSW_WAIT
+
+ jmp 18h : RealJmp1 ;use code segment with 64K limit
+[bits 16]
+RealJmp1:
+; LED_OFF
+; PSW_WAIT
+
+ mov eax, cr0 ;back to real segmented mode
+ and eax, 0fffffffeh
+ mov cr0, eax
+
+ jmp RelocSeg : RealJmp2
+RealJmp2:
+; LED_GRN
+; PSW_WAIT
+
+ mov ax, cs
+ mov es, ax
+ mov ds, ax
+ mov ss, ax
+
+ sti
+ret
+
+; Storage for a Dos 3+ BIOS Parameter Block (for the C: ramdisk)
+
+SavBPB:
+
+BpSect dw 0h ; Bytes per sector, always 512
+SpClst db 0h ; Sectors per cluster
+ResSec dw 0h ; Num of reserved sectors
+NumFAT db 0h ; Num of FATs
+NRoot dw 0h ; Num of root directory entries
+TotSec dw 0h ; Total sectors
+Media db 0h ; Media descriptor byte
+SecFAT dw 0h ; Sectors per FAT
+
+EndBPB:
+
+CurrDst dd 0h ; Current destination address for copying RTEMS exec
+
+; Important (32-bit) address for the C: ramdisk
+
+BegFAT dd 0h ; Start of the FAT
+BegRoot dd 0h ; Start of root directory
+BegData dd 0h ; Start of data clusters
+
+DDrive db 0h ; Default drive: 0h = A:, 2h = C:
+
+DirName times 11 db 32 ; Room for 8.3 directory entry name
+
+FName times 13 db 0 ; Room for a 12 character null-terminated string
+FHndl dw 0000h
+
+Greet db "RTEMS DOS Loader (c) 1999 Tony R. Ambardar",13,10,"$"
+Button db "Button pressed -- Aborting.",13,10,"$"
+FError db "Missing or incorrect file name.",13,10,"$"
+RError db "Error opening or reading file.",13,10,"$"
+
+; Global Descriptor Table used for protectd mode.
+; Store the GDTR in the first null GDT entry
+
+GDTStart:
+
+dw GDTEnd - GDTStart - 1
+dd RelocBase + GDTStart
+dw 0
+
+; base=0h, limit=4Gb, present, code, exec/read, conform, 32-bit
+
+dw 0ffffh ;seg. lim. [15:0]
+dw 0 ;base[15:0]
+db 0 ;base[23:16]
+db 9eh ;p=1,dpl=0,s=1 ; code: execute/read, conforming
+db 0cfh ;c: gran=4K, D/B=1(32-bit) ; f: seg. lim. [19:16]
+db 0 ;base[31:24]
+
+; base=0h, limit=4Gb, present, data, read/write exp. up, 32-bit SP
+
+dw 0ffffh ;seg. lim. [15:0]
+dw 0 ;base[15:0]
+db 0 ;base[23:16]
+db 92h ;p=1,dpl=0,s=1 ; data: read/write expand-up
+db 0cfh ;c: gran=4K, D/B=1(32-bit) ; f: seg. lim. [19:16]
+db 0 ;base[31:24]
+
+; base=0h, limit=ffffh, present, code, exec/read, conform, 16-bit
+; NOTE: this descriptor is used to change back to real mode.
+
+dw 0ffffh ;seg. lim. [15:0]
+dw Reloc15 ;base[15:0]
+db Reloc23 ;base[23:16]
+db 9eh ;p=1,dpl=0,s=1 ; code: execute/read, conforming
+db 000h ;4: gran=1 byte, D/B=0(16-bit) ; 0: seg. lim. [19:16]
+db 0 ;base[31:24]
+
+; base=0h, limit=ffffh, present, data, read/write exp. up, 16-bit SP
+; NOTE: this descriptor is used to change back to real mode.
+
+dw 0ffffh ;seg. lim. [15:0]
+dw Reloc15 ;base[15:0]
+db Reloc23 ;base[23:16]
+db 92h ;p=1,dpl=0,s=1 ; data: read/write expand-up
+db 000h ;0: gran=1 byte, D/B=0(16-bit) ; 0: seg. lim. [19:16]
+db 0 ;base[31:24]
+
+GDTEnd:
+
+CodeEnd: ; end-of-code marker for copy
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/dos_sup/ts1325.inc b/c/src/lib/libbsp/i386/ts_386ex/tools/dos_sup/ts1325.inc
new file mode 100644
index 0000000000..40ed3659ab
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/dos_sup/ts1325.inc
@@ -0,0 +1,48 @@
+; Some nasm macros to turn on TS-1325 LEDs and wait for button presses.
+; This should be '%include'ed in your nasm source file.
+;
+; Tony Ambardar
+
+P1LTC equ 0F862h
+P1PIN equ 0F860h
+
+%macro LED_OFF 0
+ mov dx, P1LTC
+ in al, dx
+ or al, 01000000b ; turn off red
+ and al, 11011111b ; turn off green
+ out dx, al
+%endmacro
+
+%macro LED_GRN 0
+ mov dx, P1LTC
+ in al, dx
+ or al, 01100000b ; turn off red, turn on green
+ out dx, al
+%endmacro
+
+%macro LED_YEL 0
+ mov dx, P1LTC
+ in al, dx
+ or al, 00100000b ; turn on green
+ and al, 10111111b ; turn on red
+ out dx, al
+%endmacro
+
+%macro LED_RED 0
+ mov dx, P1LTC
+ in al, dx
+ and al, 10011111b ; turn on red, turn off green
+ out dx, al
+%endmacro
+
+%macro PSW_WAIT 0
+ mov dx, P1PIN ; Get PSW state
+ mov ecx, 80000h
+%%read in al, dx
+ test al, 00000001b ; is PSW asserted?
+ jnz %%read ; if not, we're done
+ dec ecx
+ jnz %%read
+%endmacro
+
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/Makefile b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/Makefile
new file mode 100644
index 0000000000..1ce881e04e
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/Makefile
@@ -0,0 +1,41 @@
+#
+# Makefile for TS-1325 Utilities example
+#
+
+MAIN=ts1325_test
+
+# Tool paths
+tooldir=/usr/local/rtems
+rtemsdir=${tooldir}/rtems/ts_386ex
+
+# Tool names
+GCC=${tooldir}/bin/i386-rtems-gcc
+GNATMAKE=${tooldir}/bin/i386-rtems-gnatmake
+SIZE=${tooldir}/bin/i386-rtems-size
+SIS=${tooldir}/bin/sis
+GDB=${tooldir}/bin/sis-gdb
+
+CARGS=-B${rtemsdir}/lib/ -specs bsp_specs -qrtems \
+-msoft-float -mno-fp-ret-in-387
+#CARGS=-B/usr/local/rtems/tools/build-i386-rtems/ts_386ex/lib/ -specs bsp_specs -qrtems
+
+all: init.o
+ $(GNATMAKE) -O -gnata -gnatE -gnato $(MAIN) -g \
+ -bargs -r \
+ -cargs $(CARGS) \
+ -largs $(CARGS) init.o
+ $(SIZE) $(MAIN)
+
+
+
+init.o: init.c
+ $(GCC) -O4 -g -Wall -ansi -fasm $(CARGS) -c init.c
+
+run:
+ $(SIS) $(MAIN)
+
+gdb:
+ $(GDB) $(MAIN)
+
+clean:
+ rm -f b_$(MAIN).c b_$(MAIN).o *.o *.ali $(MAIN)
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/Makefile.ts_386ex b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/Makefile.ts_386ex
new file mode 100644
index 0000000000..1ce881e04e
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/Makefile.ts_386ex
@@ -0,0 +1,41 @@
+#
+# Makefile for TS-1325 Utilities example
+#
+
+MAIN=ts1325_test
+
+# Tool paths
+tooldir=/usr/local/rtems
+rtemsdir=${tooldir}/rtems/ts_386ex
+
+# Tool names
+GCC=${tooldir}/bin/i386-rtems-gcc
+GNATMAKE=${tooldir}/bin/i386-rtems-gnatmake
+SIZE=${tooldir}/bin/i386-rtems-size
+SIS=${tooldir}/bin/sis
+GDB=${tooldir}/bin/sis-gdb
+
+CARGS=-B${rtemsdir}/lib/ -specs bsp_specs -qrtems \
+-msoft-float -mno-fp-ret-in-387
+#CARGS=-B/usr/local/rtems/tools/build-i386-rtems/ts_386ex/lib/ -specs bsp_specs -qrtems
+
+all: init.o
+ $(GNATMAKE) -O -gnata -gnatE -gnato $(MAIN) -g \
+ -bargs -r \
+ -cargs $(CARGS) \
+ -largs $(CARGS) init.o
+ $(SIZE) $(MAIN)
+
+
+
+init.o: init.c
+ $(GCC) -O4 -g -Wall -ansi -fasm $(CARGS) -c init.c
+
+run:
+ $(SIS) $(MAIN)
+
+gdb:
+ $(GDB) $(MAIN)
+
+clean:
+ rm -f b_$(MAIN).c b_$(MAIN).o *.o *.ali $(MAIN)
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/i386_ports.adb b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/i386_ports.adb
new file mode 100644
index 0000000000..9705d069d8
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/i386_ports.adb
@@ -0,0 +1,29 @@
+with System.Machine_Code;
+use System.Machine_Code;
+
+package body I386_Ports is
+
+ procedure Outport (Addr: in Port_Address; Data: in Byte) is
+ begin
+ Asm ("movb %0, %%al;" &
+ "movw %1, %%dx;" &
+ "outb %%al, %%dx",
+ No_Output_Operands,
+ (Byte'Asm_Input ("g", Data),
+ Port_Address'Asm_Input ("g", Addr)),
+ Clobber => "al dx",
+ Volatile => True);
+ end Outport;
+
+ procedure Inport (Addr: in Port_Address; Data: out Byte) is
+ begin
+ Asm ("movw %1, %%dx;" &
+ "inb %%dx, %%al;" &
+ "movb %%al, %0",
+ Byte'Asm_Output ("=g", Data),
+ Port_Address'Asm_Input ("g", Addr),
+ Clobber => "dx al",
+ Volatile => True);
+ end Inport;
+
+end I386_Ports;
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/i386_ports.ads b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/i386_ports.ads
new file mode 100644
index 0000000000..c27ea646e7
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/i386_ports.ads
@@ -0,0 +1,47 @@
+with Interfaces;
+
+package I386_Ports is
+
+ type Port_Address is new Interfaces.Unsigned_16;
+
+ type Byte is new Interfaces.Unsigned_8;
+
+ type Word is new Interfaces.Unsigned_16;
+
+ type Long is new Interfaces.Unsigned_32;
+
+ procedure Outport (Addr: in Port_Address; Data: in Byte);
+
+ procedure Inport (Addr: in Port_Address; Data: out Byte);
+
+ P1PIN: constant Port_Address;
+ P1LTC: constant Port_Address;
+ P1DIR: constant Port_Address;
+
+ P2PIN: constant Port_Address;
+ P2LTC: constant Port_Address;
+ P2DIR: constant Port_Address;
+
+ P3PIN: constant Port_Address;
+ P3LTC: constant Port_Address;
+ P3DIR: constant Port_Address;
+
+private
+
+ pragma Inline (Outport, Inport);
+
+ P1PIN: constant Port_Address := 16#F860#;
+ P1LTC: constant Port_Address := 16#F862#;
+ P1DIR: constant Port_Address := 16#F864#;
+
+ P2PIN: constant Port_Address := 16#F868#;
+ P2LTC: constant Port_Address := 16#F86A#;
+ P2DIR: constant Port_Address := 16#F86C#;
+
+ P3PIN: constant Port_Address := 16#F870#;
+ P3LTC: constant Port_Address := 16#F872#;
+ P3DIR: constant Port_Address := 16#F874#;
+
+end I386_Ports;
+
+
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/init.c b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/init.c
new file mode 100644
index 0000000000..89e1652f3f
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/init.c
@@ -0,0 +1,86 @@
+/*
+ * 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 be found in
+ * the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <bsp.h>
+
+#include <assert.h>
+#include <pthread.h>
+
+#ifdef GNAT_PID
+#include <unistd.h>
+pid_t getpid()
+{
+ return GNAT_PID;
+}
+#endif
+
+/*
+ * By having the POSIX_Init thread create a second thread just
+ * to invoke gnat_main, we can override all default attributes
+ * of the "Ada environment task". Otherwise, we would be
+ * stuck with the defaults set by RTEMS.
+ */
+
+void *start_gnat_main( void * argument )
+{
+ extern int gnat_main ( int argc, char **argv, char **envp );
+
+ (void) gnat_main ( 0, 0, 0 );
+
+ exit( 0 );
+
+ return 0;
+}
+
+void *POSIX_Init( void *argument )
+{
+ pthread_t thread_id;
+ pthread_attr_t attr;
+ int status;
+
+ status = pthread_attr_init( &attr );
+ assert( !status );
+
+#ifdef GNAT_MAIN_STACKSPACE
+ status = pthread_attr_setstacksize( &attr, GNAT_MAIN_STACKSPACE );
+ assert( !status );
+#endif
+
+ status = pthread_create( &thread_id, &attr, start_gnat_main, NULL );
+ assert( !status );
+
+ pthread_exit( 0 );
+
+ return 0;
+}
+
+/* configuration information */
+
+#define CONFIGURE_SPTEST
+#define CONFIGURE_GNAT_RTEMS
+
+#define CONFIGURE_TEST_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_TEST_NEEDS_CLOCK_DRIVER
+
+#define CONFIGURE_MICROSECONDS_PER_TICK RTEMS_MILLISECONDS_TO_MICROSECONDS(1)
+
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE
+
+#define CONFIGURE_MAXIMUM_POSIX_THREADS 20
+#define CONFIGURE_MAXIMUM_POSIX_KEYS 20
+#define CONFIGURE_MAXIMUM_POSIX_MUTEXES 30
+#define CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES 20
+
+#define CONFIGURE_INIT
+
+#include <confdefs.h>
+
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-button.adb b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-button.adb
new file mode 100644
index 0000000000..cc273b0b3f
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-button.adb
@@ -0,0 +1,22 @@
+package body TS1325.Button is
+
+ function Is_Button_Pressed return Boolean is
+ State: Byte;
+ begin
+ Inport (Button_Port, State);
+ return (State and Button_Mask) /= Button_Mask;
+ end Is_Button_Pressed;
+
+ procedure Wait_For_Button_Press is
+ begin
+ Poll_Loop:
+ loop
+ if Is_Button_Pressed then
+ delay Minimum_Press_Time;
+ exit Poll_Loop when Is_Button_Pressed;
+ end if;
+ delay Poll_Interval;
+ end loop Poll_Loop;
+ end Wait_For_Button_Press;
+
+end TS1325.Button;
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-button.ads b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-button.ads
new file mode 100644
index 0000000000..568710b32f
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-button.ads
@@ -0,0 +1,22 @@
+with I386_Ports;
+use I386_Ports;
+
+package TS1325.Button is
+
+ function Is_Button_Pressed return Boolean;
+
+ procedure Wait_For_Button_Press;
+
+private
+
+ pragma Inline (Is_Button_Pressed, Wait_For_Button_Press);
+
+ Poll_Interval: constant Duration := 0.3;
+
+ Minimum_Press_Time: constant Duration := 0.3;
+
+ Button_Mask: constant Byte := 2#0000_0001#;
+
+ Button_Port: Port_Address renames P1PIN;
+
+end TS1325.Button;
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-led.adb b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-led.adb
new file mode 100644
index 0000000000..1a213ac2ff
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-led.adb
@@ -0,0 +1,46 @@
+package body TS1325.LED is
+
+ protected body LED_State is
+
+ function Get return LED_Colour is
+ State: Byte;
+ Red_On, Green_On: Boolean;
+ begin
+ Inport (LED_Port, State);
+
+ Green_On := (State and Green_Bit) = Green_Bit;
+ Red_On := (State and Red_Bit) /= Red_Bit;
+
+ if not (Green_On or Red_On) then
+ return Off;
+ elsif Green_On and not Red_On then
+ return Green;
+ elsif Green_On and Red_On then
+ return Yellow;
+ else
+ return Red;
+ end if;
+ end Get;
+
+ procedure Set (Col: in LED_Colour) is
+ State: Byte;
+ begin
+ Inport (LED_Port, State);
+
+ case Col is
+ when Off =>
+ State := (State and not Green_Bit) or Red_Bit;
+ when Green =>
+ State := State or Green_Bit or Red_Bit;
+ when Yellow =>
+ State := (State or Green_Bit) and not Red_Bit;
+ when Red =>
+ State := State and not (Green_Bit or Red_Bit);
+ end case;
+
+ Outport (LED_Port, State);
+ end Set;
+
+ end LED_State;
+
+end TS1325.LED;
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-led.ads b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-led.ads
new file mode 100644
index 0000000000..6856bc4520
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-led.ads
@@ -0,0 +1,26 @@
+with I386_Ports;
+use I386_Ports;
+
+package TS1325.LED is
+
+ type LED_Colour is (Off, Green, Yellow, Red);
+
+ protected LED_State is
+
+ function Get return LED_Colour;
+
+ procedure Set (Col: in LED_Colour);
+
+ end LED_State;
+
+private
+
+ Green_Bit: constant Byte := 2#0010_0000#; -- bit set = LED on
+
+ Red_Bit: constant Byte := 2#0100_0000#; -- bit clear = LED on
+
+ LED_Mask: constant Byte := 2#0110_0000#;
+
+ LED_Port: Port_Address renames P1LTC;
+
+end TS1325.LED;
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-parallel.adb b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-parallel.adb
new file mode 100644
index 0000000000..c0a76bcadf
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-parallel.adb
@@ -0,0 +1,13 @@
+package body TS1325.Parallel is
+
+ procedure Read_Parallel_Port (Data: out Byte) is
+ begin
+ Inport (Parallel_Port_In, Data);
+ end Read_Parallel_Port;
+
+ procedure Write_Parallel_Port (Data: in Byte) is
+ begin
+ Outport (Parallel_Port_Out, Data);
+ end Write_Parallel_Port;
+
+end TS1325.Parallel;
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-parallel.ads b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-parallel.ads
new file mode 100644
index 0000000000..b6b18d6b55
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325-parallel.ads
@@ -0,0 +1,21 @@
+with I386_Ports;
+use I386_Ports;
+
+package TS1325.Parallel is
+
+ procedure Read_Parallel_Port (Data: out Byte);
+
+ procedure Write_Parallel_Port (Data: in Byte);
+
+private
+
+ pragma Inline (Read_Parallel_Port, Write_Parallel_Port);
+
+ -- These are non-standard IO locations, which is why they are here instead
+ -- of in the I386_Ports package.
+
+ Parallel_Port_In: constant Port_Address := 16#75#;
+
+ Parallel_Port_Out: constant Port_Address := 16#74#;
+
+end TS1325.Parallel;
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325.ads b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325.ads
new file mode 100644
index 0000000000..5ef01b7449
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325.ads
@@ -0,0 +1,2 @@
+package TS1325 is
+end TS1325;
diff --git a/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325_test.adb b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325_test.adb
new file mode 100644
index 0000000000..0cb621c880
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/tools/ts_1325_ada/ts1325_test.adb
@@ -0,0 +1,115 @@
+--
+-- A test program that uses the TS1325 Button and LED packages.
+--
+
+with Text_IO;
+
+with I386_Ports;
+use I386_Ports;
+
+with TS1325.LED;
+use TS1325.LED;
+
+with TS1325.Button;
+use TS1325.Button;
+
+with TS1325.Parallel;
+use TS1325.Parallel;
+
+procedure Ts1325_Test is
+
+ Test_Parallel_Interval: Duration := 1.0;
+ Read_Button_Interval: Duration := 1.0;
+ Read_LED_Interval: Duration := 1.0;
+ Set_LED_Interval: Duration := 0.2;
+
+ task Test_Parallel is
+ entry Start;
+ end Test_Parallel;
+
+ task body Test_Parallel is
+ W_Data, R_Data: I386_Ports.Byte := 0;
+ begin
+ accept Start;
+
+ loop
+ W_Data := W_Data + 1;
+ Write_Parallel_Port (W_Data);
+ Read_Parallel_Port (R_Data);
+ Text_IO.Put_Line ("Parallel Port Loopback: Data Write = " &
+ I386_Ports.Byte'Image (W_Data) &
+ ", Data Read = " &
+ I386_Ports.Byte'Image (R_Data));
+ delay Test_Parallel_Interval;
+ end loop;
+ end Test_Parallel;
+
+ task Read_Button is
+ entry Start;
+ end Read_Button;
+
+ task body Read_Button is
+ begin
+ accept Start;
+
+ loop
+ if Is_Button_Pressed then
+ Text_IO.Put_Line ("Button is pressed.");
+ else
+ Text_IO.Put_Line ("Button is not pressed.");
+ end if;
+ delay Read_Button_Interval;
+ end loop;
+ end Read_Button;
+
+ task Read_Colour is
+ entry Start;
+ end Read_Colour;
+
+ task body Read_Colour is
+ begin
+ accept Start;
+
+ loop
+ Text_IO.Put_Line ("Reading LED colour as " &
+ LED_Colour'Image (LED_State.Get));
+ delay Read_LED_Interval;
+ end loop;
+ end Read_Colour;
+
+ task Set_Colour is
+ entry Start;
+ end Set_Colour;
+
+ task body Set_Colour is
+ Colour: LED_Colour := Off;
+ begin
+ accept Start;
+
+ loop
+ LED_State.Set (Colour);
+
+ if Colour = LED_Colour'Last then
+ Colour := LED_Colour'First;
+ else
+ Colour := LED_Colour'Succ (Colour);
+ end if;
+
+ delay Set_LED_Interval;
+ end loop;
+ end Set_Colour;
+
+begin
+ Text_IO.Put_Line ("TS-1325 Utilities Test");
+ Text_IO.Put_Line ("======================");
+ Text_IO.New_Line;
+ Text_IO.Put_Line ("-=> Press the button to begin.");
+ Text_IO.New_Line;
+
+ Wait_For_Button_Press;
+
+ Set_Colour.Start;
+ Read_Colour.Start;
+ Read_Button.Start;
+ Test_Parallel.Start;
+end Ts1325_Test;
diff --git a/c/src/lib/libbsp/i386/ts_386ex/wrapup/Makefile.in b/c/src/lib/libbsp/i386/ts_386ex/wrapup/Makefile.in
new file mode 100644
index 0000000000..f824af4c6c
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/wrapup/Makefile.in
@@ -0,0 +1,70 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = ../../../../../../..
+subdir = c/src/lib/libbsp/i386/ts_386ex/wrapup
+
+INSTALL = @INSTALL@
+
+# We only build the Network library if HAS_NETWORKING was defined
+NETWORK_yes_V = network
+NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
+
+RTEMS_ROOT = $(top_srcdir)/@RTEMS_TOPdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+VPATH = @srcdir@
+
+BSP_PIECES=startup clock console timer $(NETWORK)
+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, $(GENERIC_PIECES), ../../../$(piece)/$(ARCH)/$(piece).rel)
+LIB=$(ARCH)/libbsp.a
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_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
+
+install: all
+
+$(PROJECT_ROOT)/${RTEMS_BSP}/lib/bsp_specs: ../bsp_specs
+ $(INSTALL_DATA) $< $@
+
+preinstall: $(PROJECT_ROOT)/${RTEMS_BSP}/lib/bsp_specs
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status