Index: c/ACKNOWLEDGEMENTS
===================================================================
--- c/ACKNOWLEDGEMENTS	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/ACKNOWLEDGEMENTS	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -93,4 +93,8 @@
   autoconf.  This effort is greatly appreciated.
 
++ Eric Norum (eric@skatter.usask.ca) of the Saskatchewan Accelerator
+  Laboratory submitted the port of the ka9q tcp/ip stack to rtems
+  and a network driver for the `gen68360' BSP.
+
 Finally, the RTEMS project would like to thank those who have contributed
 to the other free software efforts which RTEMS utilizes.  The primary RTEMS
Index: c/Makefile.in
===================================================================
--- c/Makefile.in	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/Makefile.in	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -28,8 +28,13 @@
 SUB_DIRS=build-tools src
 
+# We only make the ka9q install point if it is enabled.
+LIBKA9Q_yes_V = include/ka9q
+LIBKA9Q = $(LIBKA9Q_$(HAS_KA9Q)_V)
+
 # directories to be created in install point
 CREATE_DIRS = 	include include/sys \
     include/rtems include/rtems/score include/rtems/rtems include/rtems/posix \
-		include/libc include/libc/sys \
+                include/netinet include/libc include/libc/sys \
+                $(LIBKA9Q) \
 		lib \
 		bin \
Index: c/src/exec/libcsupport/include/rtems/libio.h
===================================================================
--- c/src/exec/libcsupport/include/rtems/libio.h	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/exec/libcsupport/include/rtems/libio.h	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -100,3 +100,25 @@
 int __rtems_isatty(int _fd);
 
+/*
+ * External I/O handlers
+ */
+typedef struct {
+    int (*open)(const char  *pathname, unsigned32 flag, unsigned32 mode);
+    int (*close)(int  fd);
+    int (*read)(int fd, void *buffer, unsigned32 count);
+    int (*write)(int fd, const void *buffer, unsigned32 count);
+    int (*ioctl)(int fd, unsigned32  command, void *buffer);
+    int (*lseek)(int fd, rtems_libio_offset_t offset, int whence);
+} rtems_libio_handler_t;
+
+void rtems_register_libio_handler(int handler_flag,
+                                 const rtems_libio_handler_t *handler);
+
+#define RTEMS_FILE_DESCRIPTOR_TYPE_FILE         0x0000
+#define RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET       0x1000
+#define rtems_make_file_descriptor(fd,flags)    ((fd)|(flags))
+#define rtems_file_descriptor_base(fd)          ((fd) & 0x0FFF)
+#define rtems_file_descriptor_type(fd)          ((fd) & 0xF000)
+#define rtems_file_descriptor_type_index(fd)    ((((fd) & 0xF000) >> 12) - 1)
+
 #endif /* _RTEMS_LIBIO_H */
Index: c/src/exec/libcsupport/src/libio.c
===================================================================
--- c/src/exec/libcsupport/src/libio.c	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/exec/libcsupport/src/libio.c	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -80,4 +80,26 @@
     } while (0)
 
+/*
+ * External I/O handlers
+ * 
+ * Space for all possible handlers is preallocated
+ * to speed up dispatch to external handlers.
+ */
+
+static rtems_libio_handler_t handlers[15];
+
+void
+rtems_register_libio_handler(
+    int                         handler_flag,
+    const rtems_libio_handler_t *handler
+)
+{
+  int handler_index = rtems_file_descriptor_type_index(handler_flag);
+
+  if ((handler_index < 0) || (handler_index >= 15))
+    rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER );
+  handlers[handler_index] = *handler;
+}
+
 
 void
@@ -85,5 +107,5 @@
     rtems_configuration_table *config,
     unsigned32                 max_fds
-  )
+)
 {
     rtems_libio_number_iops = max_fds;
@@ -254,13 +276,14 @@
     rtems_libio_open_close_args_t args;
 
-    if ((rc = rtems_io_lookup_name(pathname, &np)) != RTEMS_SUCCESSFUL) {
-/*
-      if ( rc == RTEMS_UNSATISFIED ) {
-        puts( "open -- ENOSYS case" );
-        assert( 0 );
-      }
-*/
+    /*
+     * Additional external I/O handlers would be supported by
+     * adding code to pick apart the pathname appropriately.
+     * The networking code does not require changes here since
+     * network file descriptors are obtained using socket(), not
+     * open().
+     */
+
+    if ((rc = rtems_io_lookup_name(pathname, &np)) != RTEMS_SUCCESSFUL)
         goto done;
-    }
 
     iop = rtems_libio_allocate();
@@ -300,7 +323,18 @@
     rtems_status_code rc;
     rtems_driver_name_t *np;
-    rtems_libio_t *iop = rtems_libio_iop(fd);
+    rtems_libio_t *iop;
     rtems_libio_open_close_args_t args;
 
+    if (rtems_file_descriptor_type(fd)) {
+        int (*fp)(int fd);
+
+        fp = handlers[rtems_file_descriptor_type_index(fd)].close;
+        if (fp == NULL) {
+            errno = EBADF;
+            return -1;
+        }
+        return (*fp)(fd);
+    }
+    iop = rtems_libio_iop(fd);
     rtems_libio_check_fd(fd);
 
@@ -327,7 +361,18 @@
     rtems_status_code rc;
     rtems_driver_name_t *np;
-    rtems_libio_t *iop = rtems_libio_iop(fd);
+    rtems_libio_t *iop;
     rtems_libio_rw_args_t args;
 
+    if (rtems_file_descriptor_type(fd)) {
+        int (*fp)(int fd, void *buffer, unsigned32 count);
+
+        fp = handlers[rtems_file_descriptor_type_index(fd)].read;
+        if (fp == NULL) {
+            errno = EBADF;
+            return -1;
+        }
+        return (*fp)(fd, buffer, count);
+    }
+    iop = rtems_libio_iop(fd);
     rtems_libio_check_fd(fd);
     rtems_libio_check_buffer(buffer);
@@ -363,7 +408,18 @@
     rtems_status_code rc;
     rtems_driver_name_t *np;
-    rtems_libio_t *iop = rtems_libio_iop(fd);
+    rtems_libio_t *iop;
     rtems_libio_rw_args_t args;
 
+    if (rtems_file_descriptor_type(fd)) {
+        int (*fp)(int fd, const void *buffer, unsigned32 count);
+
+        fp = handlers[rtems_file_descriptor_type_index(fd)].write;
+        if (fp == NULL) {
+            errno = EBADF;
+            return -1;
+        }
+        return (*fp)(fd, buffer, count);
+    }
+    iop = rtems_libio_iop(fd);
     rtems_libio_check_fd(fd);
     rtems_libio_check_buffer(buffer);
@@ -398,7 +454,18 @@
     rtems_status_code rc;
     rtems_driver_name_t *np;
-    rtems_libio_t *iop = rtems_libio_iop(fd);
+    rtems_libio_t *iop;
     rtems_libio_ioctl_args_t args;
 
+    if (rtems_file_descriptor_type(fd)) {
+        int (*fp)(int fd, unsigned32 command, void *buffer);
+
+        fp = handlers[rtems_file_descriptor_type_index(fd)].ioctl;
+        if (fp == NULL) {
+            errno = EBADF;
+            return -1;
+        }
+        return (*fp)(fd, command, buffer);
+    }
+    iop = rtems_libio_iop(fd);
     rtems_libio_check_fd(fd);
 
@@ -429,6 +496,17 @@
   )    
 {
-    rtems_libio_t *iop = rtems_libio_iop(fd);
-
+    rtems_libio_t *iop;
+
+    if (rtems_file_descriptor_type(fd)) {
+        int (*fp)(int fd, rtems_libio_offset_t offset, int whence);
+
+        fp = handlers[rtems_file_descriptor_type_index(fd)].lseek;
+        if (fp == NULL) {
+            errno = EBADF;
+            return -1;
+        }
+        return (*fp)(fd, offset, whence);
+    }
+    iop = rtems_libio_iop(fd);
     rtems_libio_check_fd(fd);
 
Index: c/src/exec/score/cpu/a29k/cpu.h
===================================================================
--- c/src/exec/score/cpu/a29k/cpu.h	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/exec/score/cpu/a29k/cpu.h	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -296,4 +296,16 @@
 
 #define CPU_STRUCTURE_ALIGNMENT
+
+/*
+ *  Define what is required to specify how the network to host conversion
+ *  routines are handled.
+ *
+ */
+
+#error "Check these definitions!!!"
+
+#define CPU_CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN                           TRUE
+#define CPU_LITTLE_ENDIAN                        FALSE
 
 /*
Index: c/src/exec/score/cpu/hppa1.1/cpu.h
===================================================================
--- c/src/exec/score/cpu/hppa1.1/cpu.h	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/exec/score/cpu/hppa1.1/cpu.h	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -64,4 +64,13 @@
 #define CPU_STACK_GROWS_UP               TRUE
 #define CPU_STRUCTURE_ALIGNMENT          __attribute__ ((__aligned__ (32)))
+
+/*
+ *  Define what is required to specify how the network to host conversion
+ *  routines are handled.
+ */
+
+#define CPU_CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN                           TRUE
+#define CPU_LITTLE_ENDIAN                        FALSE
 
 /* constants */
Index: c/src/exec/score/cpu/i386/cpu.h
===================================================================
--- c/src/exec/score/cpu/i386/cpu.h	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/exec/score/cpu/i386/cpu.h	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -58,4 +58,13 @@
 #define CPU_STACK_GROWS_UP               FALSE
 #define CPU_STRUCTURE_ALIGNMENT
+
+/*
+ *  Define what is required to specify how the network to host conversion
+ *  routines are handled.
+ */
+
+#define CPU_CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN                           FALSE
+#define CPU_LITTLE_ENDIAN                        TRUE
 
 /* structures */
Index: c/src/exec/score/cpu/i960/cpu.h
===================================================================
--- c/src/exec/score/cpu/i960/cpu.h	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/exec/score/cpu/i960/cpu.h	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -61,4 +61,14 @@
 #define CPU_STACK_GROWS_UP               TRUE
 #define CPU_STRUCTURE_ALIGNMENT          __attribute__ ((aligned (16)))
+
+/*
+ *  Define what is required to specify how the network to host conversion
+ *  routines are handled.
+ */
+
+#define CPU_CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN                           TRUE
+#define CPU_LITTLE_ENDIAN                        FALSE
+
 
 /* structures */
Index: c/src/exec/score/cpu/m68k/cpu.h
===================================================================
--- c/src/exec/score/cpu/m68k/cpu.h	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/exec/score/cpu/m68k/cpu.h	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -75,4 +75,13 @@
 #define CPU_STACK_GROWS_UP               FALSE
 #define CPU_STRUCTURE_ALIGNMENT
+
+/*
+ *  Define what is required to specify how the network to host conversion
+ *  routines are handled.
+ */
+
+#define CPU_CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN                           TRUE
+#define CPU_LITTLE_ENDIAN                        FALSE
 
 #ifndef ASM
Index: c/src/exec/score/cpu/mips64orion/cpu.h
===================================================================
--- c/src/exec/score/cpu/mips64orion/cpu.h	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/exec/score/cpu/mips64orion/cpu.h	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -290,4 +290,13 @@
 #define CPU_STRUCTURE_ALIGNMENT 
 #endif
+
+/*
+ *  Define what is required to specify how the network to host conversion
+ *  routines are handled.
+ */
+
+#define CPU_CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN                           TRUE
+#define CPU_LITTLE_ENDIAN                        FALSE
 
 /*
Index: c/src/exec/score/cpu/no_cpu/cpu.h
===================================================================
--- c/src/exec/score/cpu/no_cpu/cpu.h	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/exec/score/cpu/no_cpu/cpu.h	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -259,4 +259,13 @@
 
 #define CPU_STRUCTURE_ALIGNMENT
+
+/*
+ *  Define what is required to specify how the network to host conversion
+ *  routines are handled.
+ */
+
+#define CPU_CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN                           TRUE
+#define CPU_LITTLE_ENDIAN                        FALSE
 
 /*
Index: c/src/exec/score/cpu/powerpc/cpu.h
===================================================================
--- c/src/exec/score/cpu/powerpc/cpu.h	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/exec/score/cpu/powerpc/cpu.h	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -285,5 +285,15 @@
  */
 
-#define CPU_STRUCTURE_ALIGNMENT    __attribute__ ((aligned (PPC_CACHE_ALIGNMENT)))
+#define CPU_STRUCTURE_ALIGNMENT \
+   __attribute__ ((aligned (PPC_CACHE_ALIGNMENT)))
+
+/*
+ *  Define what is required to specify how the network to host conversion
+ *  routines are handled.
+ */
+
+#define CPU_CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN                           TRUE
+#define CPU_LITTLE_ENDIAN                        FALSE
 
 /*
Index: c/src/exec/score/cpu/sparc/cpu.h
===================================================================
--- c/src/exec/score/cpu/sparc/cpu.h	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/exec/score/cpu/sparc/cpu.h	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -184,4 +184,13 @@
 
 #define CPU_STRUCTURE_ALIGNMENT          __attribute__ ((aligned (16)))
+
+/*
+ *  Define what is required to specify how the network to host conversion
+ *  routines are handled.
+ */
+
+#define CPU_CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN                           TRUE
+#define CPU_LITTLE_ENDIAN                        FALSE
 
 /*
Index: c/src/exec/score/cpu/unix/cpu.h
===================================================================
--- c/src/exec/score/cpu/unix/cpu.h	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/exec/score/cpu/unix/cpu.h	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -283,4 +283,21 @@
 #else
 #define CPU_STRUCTURE_ALIGNMENT
+#endif
+
+/*
+ *  Define what is required to specify how the network to host conversion
+ *  routines are handled.
+ */
+
+#if defined(hppa1_1) || defined(sparc)
+#define CPU_CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN                           TRUE
+#define CPU_LITTLE_ENDIAN                        FALSE
+#elif defined(i386) || defined(__i386__)
+#define CPU_CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN                           FALSE
+#define CPU_LITTLE_ENDIAN                        TRUE
+#else
+#error "Unknown CPU!!!"
 #endif
 
Index: c/src/exec/score/headers/Makefile.in
===================================================================
--- c/src/exec/score/headers/Makefile.in	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/exec/score/headers/Makefile.in	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -11,5 +11,5 @@
 H_PIECES= address apiext bitfield chain context copyrt coremsg coremutex \
     coresem heap interr isr mpci mppkt object objectmp \
-    priority stack states sysstate system thread threadmp threadq \
+    priority stack states sysstate thread threadmp threadq \
     tod tqdata userext watchdog wkspace
 H_FILES=$(H_PIECES:%=$(srcdir)/%.h)
@@ -20,7 +20,9 @@
 
 # H_FILES that get installed at the top level
-# system.h is handled specially
 EXTERNAL_H_PIECES = 
 EXTERNAL_H_FILES=$(EXTERNAL_H_PIECES:%=$(srcdir)/%.h)
+
+NET_H_PIECES = in
+NET_H_FILES=$(NET_H_PIECES:%=$(srcdir)/%.h)
 
 SRCS=$(H_FILES) $(SAPI_H_FILES) $(EXTERNAL_H_FILES)
@@ -42,3 +44,4 @@
 	$(INSTALL) -m 444 ${H_FILES} ${PROJECT_RELEASE}/include/rtems/score
 	$(INSTALL) -m 444 ${SAPI_H_FILES} ${PROJECT_RELEASE}/include/rtems/
+	$(INSTALL) -m 444 ${NET_H_FILES} ${PROJECT_RELEASE}/include/netinet
 #	$(INSTALL) -m 444 ${EXTERNAL_H_FILES} ${PROJECT_RELEASE}/include
Index: c/src/exec/score/include/rtems/score/Makefile.in
===================================================================
--- c/src/exec/score/include/rtems/score/Makefile.in	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/exec/score/include/rtems/score/Makefile.in	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -11,5 +11,5 @@
 H_PIECES= address apiext bitfield chain context copyrt coremsg coremutex \
     coresem heap interr isr mpci mppkt object objectmp \
-    priority stack states sysstate system thread threadmp threadq \
+    priority stack states sysstate thread threadmp threadq \
     tod tqdata userext watchdog wkspace
 H_FILES=$(H_PIECES:%=$(srcdir)/%.h)
@@ -20,7 +20,9 @@
 
 # H_FILES that get installed at the top level
-# system.h is handled specially
 EXTERNAL_H_PIECES = 
 EXTERNAL_H_FILES=$(EXTERNAL_H_PIECES:%=$(srcdir)/%.h)
+
+NET_H_PIECES = in
+NET_H_FILES=$(NET_H_PIECES:%=$(srcdir)/%.h)
 
 SRCS=$(H_FILES) $(SAPI_H_FILES) $(EXTERNAL_H_FILES)
@@ -42,3 +44,4 @@
 	$(INSTALL) -m 444 ${H_FILES} ${PROJECT_RELEASE}/include/rtems/score
 	$(INSTALL) -m 444 ${SAPI_H_FILES} ${PROJECT_RELEASE}/include/rtems/
+	$(INSTALL) -m 444 ${NET_H_FILES} ${PROJECT_RELEASE}/include/netinet
 #	$(INSTALL) -m 444 ${EXTERNAL_H_FILES} ${PROJECT_RELEASE}/include
Index: c/src/lib/Makefile.in
===================================================================
--- c/src/lib/Makefile.in	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/lib/Makefile.in	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -11,3 +11,7 @@
 include $(PROJECT_ROOT)/make/directory.cfg
 
-SUB_DIRS=start include libmisc libc libcpu libbsp wrapup
+# We only build the ka9q library if HAS_KA9Q was defined
+LIBKA9Q_yes_V = libka9q
+LIBKA9Q = $(LIBKA9Q_$(HAS_KA9Q)_V)
+
+SUB_DIRS=start include libmisc libc libcpu libbsp $(LIBKA9Q) wrapup
Index: c/src/lib/include/Makefile.in
===================================================================
--- c/src/lib/include/Makefile.in	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/lib/include/Makefile.in	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -8,12 +8,18 @@
 VPATH=@srcdir@
 
-H_FILES=console.h clockdrv.h iosupp.h ringbuf.h \
-   spurious.h timerdrv.h vmeintr.h z8036.h z8530.h z8536.h
+H_PIECES=console clockdrv iosupp ringbuf \
+   spurious timerdrv vmeintr z8036 z8530 z8536
+H_FILES=$(H_PIECES:%=$(srcdir)/%.h)
 
-HH_FILES=$(H_FILES:%=$(srcdir)/%)
+KA9Q_H_PIECES= arp asy ax25 ax25mail bootp cmdparse commands config \
+  daemon dialer domain enet ftp ftpcli global hardware icmp iface \
+  internet ip kiss lapb lzw mailbox mbuf netuser nospc nr4 nr4mail \
+  nrs ping pktdrvr ppp proc rip rtems_ka9q sb session slhc slip smtp \
+  sockaddr socket tcp telnet tftp timer tipmail trace udp usock
+KA9Q_H_FILES=$(KA9Q_H_PIECES:%=$(srcdir)/ka9q/%.h)
 
 SYS_H_FILES=
 
-SRCS=$(HH_FILES) $(SYS_H_FILES)
+SRCS=$(H_FILES) $(SYS_H_FILES)
 
 include $(RTEMS_CUSTOM)
@@ -24,5 +30,7 @@
 
 all:	$(SRCS)
-	$(INSTALL) -m 444 $(HH_FILES) ${PROJECT_RELEASE}/include
+	$(INSTALL) -m 444 $(H_FILES) ${PROJECT_RELEASE}/include
 	$(INSTALL) -m 444 $(SYS_H_FILES) ${PROJECT_RELEASE}/include/sys
-
+ifeq ($(HAS_KA9Q),yes)
+	$(INSTALL) -m 444 $(KA9Q_H_FILES) ${PROJECT_RELEASE}/include/ka9q
+endif
Index: c/src/lib/include/rtems/libio.h
===================================================================
--- c/src/lib/include/rtems/libio.h	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/lib/include/rtems/libio.h	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -100,3 +100,25 @@
 int __rtems_isatty(int _fd);
 
+/*
+ * External I/O handlers
+ */
+typedef struct {
+    int (*open)(const char  *pathname, unsigned32 flag, unsigned32 mode);
+    int (*close)(int  fd);
+    int (*read)(int fd, void *buffer, unsigned32 count);
+    int (*write)(int fd, const void *buffer, unsigned32 count);
+    int (*ioctl)(int fd, unsigned32  command, void *buffer);
+    int (*lseek)(int fd, rtems_libio_offset_t offset, int whence);
+} rtems_libio_handler_t;
+
+void rtems_register_libio_handler(int handler_flag,
+                                 const rtems_libio_handler_t *handler);
+
+#define RTEMS_FILE_DESCRIPTOR_TYPE_FILE         0x0000
+#define RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET       0x1000
+#define rtems_make_file_descriptor(fd,flags)    ((fd)|(flags))
+#define rtems_file_descriptor_base(fd)          ((fd) & 0x0FFF)
+#define rtems_file_descriptor_type(fd)          ((fd) & 0xF000)
+#define rtems_file_descriptor_type_index(fd)    ((((fd) & 0xF000) >> 12) - 1)
+
 #endif /* _RTEMS_LIBIO_H */
Index: c/src/lib/libbsp/m68k/gen68360/Makefile.in
===================================================================
--- c/src/lib/libbsp/m68k/gen68360/Makefile.in	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/lib/libbsp/m68k/gen68360/Makefile.in	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -13,7 +13,11 @@
 SRCS=README
 
+# We only build the ka9q device driver if HAS_KA9Q was defined
+LIBKA9Q_yes_V = network
+LIBKA9Q = $(LIBKA9Q_$(HAS_KA9Q)_V)
+
 all: $(SRCS)
 
 # wrapup is the one that actually builds and installs the library
 #  from the individual .rel files built in other directories
-SUB_DIRS=include start360 startup clock console timer wrapup
+SUB_DIRS=include start360 startup clock console timer $(LIBKA9Q) wrapup
Index: c/src/lib/libbsp/m68k/gen68360/README
===================================================================
--- c/src/lib/libbsp/m68k/gen68360/README	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/lib/libbsp/m68k/gen68360/README	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -4,5 +4,5 @@
 
 #
-# This package requires a version of GCC that has been modified
+# This package works best with a version of GCC that has been modified
 # to support the `-mcpu32' argument.  I have submitted the required
 # changes to the GCC maintainers.
@@ -20,6 +20,35 @@
 #
 
+#
+# This board support package works with several different versions of
+# MC68360 systems.  The choice of hardware is made at the final link-edit
+# phase by setting the Makefile LDFLAGS definition appropriately.
+#
+# Decisions to be made a link-edit time include:
+#	- The version of hardware on which the application is to run.
+#	  This is selected by defining the MC68360HardwareType variable.
+#	  Supported values are:
+#			MC68360HardwareTypeMotorolaGeneric (default)
+#			MC68360HardwareTypeAtlasHSB
+#	  To select the Atlas Computer Equipment HSB,
+#		--defsym MC68360HardwareType=MC68360HardwareTypeAtlasHSB
+#
+#	- The amount of dynamic RAM in the system.  This value applies
+#	  only to hardware versions which support different sizes of RAM.
+#	  The default value is 4 Mbytes.  To specify 16 Mbytes of memory,
+#		--defsym RamSize=0x1000000
+#
+#	- The size of the memory allocator heap.  The default value is
+#	  64 kbytes.  If the KA9Q network package is used the heap
+#	  should be at least 256 kbytes.  If your network is large, or
+#	  busy, the heap should be even larger.
+#	  To choose a heap size of 256 kbytes,
+#		--defsym HeapSize=0x40000
+#	  
+
 BSP NAME:	    gen68360
-BOARD:              home-built
+BOARD:              Generic 68360 as described in Motorola MC68360 User's Manual
+BOARD:              Atlas Computer Equipment Inc. High Speed Bridge (HSB)
+BOARD:              Atlas Computer Equipment Inc. Advanced Communication Engine (ACE)
 BUS:                none
 CPU FAMILY:         Motorola CPU32+
@@ -64,5 +93,5 @@
 bus width:	8-bit PROM, 32-bit DRAM
 ROM:		To 1 MByte, 180 nsec (3 wait states), chip select 0
-RAM:		4 MByte DRAM SIMM, 60 nsec (0 wait states), parity
+RAM:		1 to 64 MByte DRAM SIMM, 60 nsec (0 wait states), parity or nonparity
 
 Host System
@@ -253,5 +282,5 @@
 This board support package is written for a 68360 system similar to that
 described in chapter 9 of the Motorola MC68360 Quad Integrated Communication
-Processor Users' Manual.  The salient details of this hardware are:
+Processor Users' Manual.  The salient features of this hardware are:
 
 	25 MHz external clock
@@ -260,4 +289,5 @@
 	4 MBytes of 60 nsec parity DRAM (1Mx36) to RAS1*/CAS1*
 	Console serial port on SMC1
+	Ethernet interface on SCC1
 
 The board support package has been tested with a home-built board and with an
Index: c/src/lib/libbsp/m68k/gen68360/console/console.c
===================================================================
--- c/src/lib/libbsp/m68k/gen68360/console/console.c	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/lib/libbsp/m68k/gen68360/console/console.c	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -43,15 +43,8 @@
 
 /*
- * Place buffer descriptors at end of User Data/BD space in dual-port RAM
- */
-#define consoleRxBd ((volatile m360BufferDescriptor_t *)((char *)m360.dpram1 + \
-		(sizeof(m360.dpram2) - 2*sizeof(m360BufferDescriptor_t))))
-#define consoleTxBd ((volatile m360BufferDescriptor_t *)((char *)m360.dpram1 + \
-		(sizeof(m360.dpram2) - sizeof(m360BufferDescriptor_t))))
-
-/*
  * I/O buffers can be in ordindary RAM
  */
 static volatile char rxBuf, txBuf;
+static volatile m360BufferDescriptor_t *consoleRxBd, *consoleTxBd;
 
 rtems_device_driver console_initialize(
@@ -62,4 +55,10 @@
 {
 	rtems_status_code status;
+
+	/*
+	 * Allocate buffer descriptors
+	 */
+	consoleRxBd = M360AllocateBufferDescriptors (1);
+	consoleTxBd = M360AllocateBufferDescriptors (1);
 
 	/*
@@ -122,7 +121,5 @@
 	 * Send "Init parameters" command
 	 */
-	m360.cr = M360_CR_OP_INIT_RX_TX | M360_CR_CHAN_SMC1 | M360_CR_FLG;
-	while (m360.cr & M360_CR_FLG)
-		continue;
+	M360ExecuteRISC (M360_CR_OP_INIT_RX_TX | M360_CR_CHAN_SMC1);
 
 	/*
Index: c/src/lib/libbsp/m68k/gen68360/include/bsp.h
===================================================================
--- c/src/lib/libbsp/m68k/gen68360/include/bsp.h	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/lib/libbsp/m68k/gen68360/include/bsp.h	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -120,4 +120,6 @@
 
 void M360ExecuteRISC( rtems_unsigned16 command );
+void *M360AllocateBufferDescriptors( int count );
+void *M360AllocateRiscTimers( int count );
 
 m68k_isr_entry set_vector(
@@ -127,4 +129,21 @@
 );
 
+/*
+ * Values assigned by link editor
+ */
+extern void *_RomBase, *_RamBase, *_RamSize;
+extern void *_MC68360HardwareType;
+extern void *_MC68360HardwareTypeMotorolaGeneric;
+extern void *_MC68360HardwareTypeAtlasHSB;
+
+/*
+ * Definitions for Atlas Computer Equipment Inc. High Speed Bridge (HSB)
+ */
+#define ATLASHSB_ESR    0x20010000L
+#define ATLASHSB_USICR  0x20010001L
+#define ATLASHSB_DSRR   0x20010002L
+#define ATLASHSB_LED4   0x20010004L
+#define ATLASHSB_ROM_U6 0xFF080000L	/* U6 flash ROM socket */
+
 #ifdef __cplusplus
 }
Index: c/src/lib/libbsp/m68k/gen68360/include/sio.h
===================================================================
--- c/src/lib/libbsp/m68k/gen68360/include/sio.h	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
+++ c/src/lib/libbsp/m68k/gen68360/include/sio.h	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -0,0 +1,62 @@
+/*  sio.h
+ *
+ *  sio device driver for UART SCC and SMC
+ *
+ *  COPYRIGHT (c) 1997 Pacific Computing
+ * 
+ *  $Id$
+ */
+
+#ifndef _SIO_DRIVER_h
+#define _SIO_DRIVER_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SIO_DRIVER_TABLE_ENTRY \
+  { sio_initialize, sio_open, sio_close, \
+    sio_read, sio_write, sio_control }
+
+rtems_device_driver sio_initialize(
+  rtems_device_major_number,
+  rtems_device_minor_number,
+  void *
+);
+
+rtems_device_driver sio_open(
+  rtems_device_major_number,
+  rtems_device_minor_number,
+  void *
+);
+
+rtems_device_driver sio_close(
+  rtems_device_major_number,
+  rtems_device_minor_number,
+  void *
+);
+
+rtems_device_driver sio_read(
+  rtems_device_major_number,
+  rtems_device_minor_number,
+  void *
+);
+
+rtems_device_driver sio_write(
+  rtems_device_major_number,
+  rtems_device_minor_number,
+  void *
+);
+
+rtems_device_driver sio_control(
+  rtems_device_major_number,
+  rtems_device_minor_number,
+  void *
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
Index: c/src/lib/libbsp/m68k/gen68360/start/start360.s
===================================================================
--- c/src/lib/libbsp/m68k/gen68360/start/start360.s	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/lib/libbsp/m68k/gen68360/start/start360.s	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -57,5 +57,5 @@
 	.long	uhoh			|  22:
 	.long	uhoh			|  23:
-	.long	uhoh			|  24: Spurious interrupt
+	.long	spurious_interrupt	|  24: Spurious interrupt
 	.long	uhoh			|  25: Level 1 interrupt autovector
 	.long	uhoh			|  26: Level 2 interrupt autovector
@@ -299,4 +299,11 @@
 
 /*
+ * Log, but otherwise ignore, spurious interrupts
+ */
+spurious_interrupt:
+	addql	#1,SYM(_M68kSpuriousInterruptCount)
+	rte
+
+/*
  * Place the low-order 3 octets of the board's ethernet address at
  * a `well-known' fixed location relative to the beginning of ROM.
@@ -308,5 +315,5 @@
  * Initial PC
  */
-        .global start
+         .global start
 start:	
 	/*
@@ -387,4 +394,6 @@
 					| Should this just force a reset?
 mainDone:	nop			| Leave spot for breakpoint
+	movew	#1,a7			| Force a double bus error
+	movel	d0,a7@-			| This should cause a RESET
 	stop	#0x2700			| Stop with interrupts disabled
 	bra.s	mainDone		| Stuck forever
@@ -399,8 +408,13 @@
 END_CODE
 
-BEGIN_BSS
+BEGIN_DATA_DCL
         .align 2
 	PUBLIC (environ)
 SYM (environ):
 	.long	0
+	PUBLIC (_M68kSpuriousInterruptCount)
+SYM (_M68kSpuriousInterruptCount):
+	.long	0
+END_DATA_DCL
+
 END
Index: c/src/lib/libbsp/m68k/gen68360/start360/start360.s
===================================================================
--- c/src/lib/libbsp/m68k/gen68360/start360/start360.s	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/lib/libbsp/m68k/gen68360/start360/start360.s	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -57,5 +57,5 @@
 	.long	uhoh			|  22:
 	.long	uhoh			|  23:
-	.long	uhoh			|  24: Spurious interrupt
+	.long	spurious_interrupt	|  24: Spurious interrupt
 	.long	uhoh			|  25: Level 1 interrupt autovector
 	.long	uhoh			|  26: Level 2 interrupt autovector
@@ -299,4 +299,11 @@
 
 /*
+ * Log, but otherwise ignore, spurious interrupts
+ */
+spurious_interrupt:
+	addql	#1,SYM(_M68kSpuriousInterruptCount)
+	rte
+
+/*
  * Place the low-order 3 octets of the board's ethernet address at
  * a `well-known' fixed location relative to the beginning of ROM.
@@ -308,5 +315,5 @@
  * Initial PC
  */
-        .global start
+         .global start
 start:	
 	/*
@@ -387,4 +394,6 @@
 					| Should this just force a reset?
 mainDone:	nop			| Leave spot for breakpoint
+	movew	#1,a7			| Force a double bus error
+	movel	d0,a7@-			| This should cause a RESET
 	stop	#0x2700			| Stop with interrupts disabled
 	bra.s	mainDone		| Stuck forever
@@ -399,8 +408,13 @@
 END_CODE
 
-BEGIN_BSS
+BEGIN_DATA_DCL
         .align 2
 	PUBLIC (environ)
 SYM (environ):
 	.long	0
+	PUBLIC (_M68kSpuriousInterruptCount)
+SYM (_M68kSpuriousInterruptCount):
+	.long	0
+END_DATA_DCL
+
 END
Index: c/src/lib/libbsp/m68k/gen68360/startup/Makefile.in
===================================================================
--- c/src/lib/libbsp/m68k/gen68360/startup/Makefile.in	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/lib/libbsp/m68k/gen68360/startup/Makefile.in	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -11,5 +11,5 @@
 
 # C source names, if any, go here -- minus the .c
-C_PIECES=bspstart bspclean init68360 sbrk setvec
+C_PIECES=alloc360 bspstart bspclean init68360 sbrk setvec
 C_FILES=$(C_PIECES:%=%.c)
 C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
@@ -17,5 +17,6 @@
 H_FILES=
 
-SRCS=$(srcdir)/linkcmds $(srcdir)/linkcmds.prom $(C_FILES) $(H_FILES)
+SRCS=$(srcdir)/linkcmds $(srcdir)/linkcmds.prom $(srcdir)/linkcmds.bootp \
+     $(C_FILES) $(H_FILES)
 OBJS=$(C_O_FILES) $(CC_O_FILES)
 
Index: c/src/lib/libbsp/m68k/gen68360/startup/alloc360.c
===================================================================
--- c/src/lib/libbsp/m68k/gen68360/startup/alloc360.c	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
+++ c/src/lib/libbsp/m68k/gen68360/startup/alloc360.c	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -0,0 +1,96 @@
+/*
+ * MC68360 buffer descriptor allocation routines
+ *
+ * W. Eric Norum
+ * Saskatchewan Accelerator Laboratory
+ * University of Saskatchewan
+ * Saskatoon, Saskatchewan, CANADA
+ * eric@skatter.usask.ca
+ *
+ *  $Id$
+ */
+
+#include <rtems.h>
+#include <bsp.h>
+#include <m68360.h>
+#include <rtems/error.h>
+
+/*
+ * Allocation order:
+ *	- Dual-Port RAM section 1
+ *	- Dual-Port RAM section 3
+ *	- Dual-Port RAM section 0
+ *	- Dual-Port RAM section 2
+ */
+static struct {
+	char		*base;
+	unsigned int	size;
+	unsigned int	used;
+} bdregions[] = {
+	{ (char *)&m360.dpram1[0],	sizeof m360.dpram1,	0 },
+	{ (char *)&m360.dpram3[0],	sizeof m360.dpram3,	0 },
+	{ (char *)&m360.dpram0[0],	sizeof m360.dpram0,	0 },
+	{ (char *)&m360.dpram2[0],	sizeof m360.dpram2,	0 },
+};
+
+/*
+ * Send a command to the CPM RISC processer
+ */
+void *
+M360AllocateBufferDescriptors (int count)
+{
+	unsigned int i;
+	ISR_Level level;
+	void *bdp = NULL;
+	unsigned int want = count * sizeof(m360BufferDescriptor_t);
+
+	/*
+	 * Running with interrupts disabled is usually considered bad
+	 * form, but this routine is probably being run as part of an
+	 * initialization sequence so the effect shouldn't be too severe.
+	 */
+	_ISR_Disable (level);
+	for (i = 0 ; i < sizeof(bdregions) / sizeof(bdregions[0]) ; i++) {
+		/*
+		 * Verify that the region exists.
+		 * This test is necessary since some chips have
+		 * less dual-port RAM.
+		 */
+		if (bdregions[i].used == 0) {
+			volatile unsigned char *cp = bdregions[i].base;
+			*cp = 0xAA;
+			if (*cp != 0xAA) {
+				bdregions[i].used = bdregions[i].size;
+				continue;
+			}
+			*cp = 0x55;
+			if (*cp != 0x55) {
+				bdregions[i].used = bdregions[i].size;
+				continue;
+			}
+			*cp = 0x0;
+		}
+		if (bdregions[i].size - bdregions[i].used >= want) {
+			bdp = bdregions[i].base + bdregions[i].used;
+			bdregions[i].used += want;
+			break;
+		}
+	}
+	_ISR_Enable (level);
+	if (bdp == NULL)
+		rtems_panic ("Can't allocate %d buffer descriptor(s).\n", count);
+	return bdp;
+}
+
+void *
+M360AllocateRiscTimers (int count)
+{
+	/*
+	 * Convert the count to the number of buffer descriptors
+	 * of equal or larger size.  This ensures that all buffer
+	 * descriptors are allocated with appropriate alignment.
+	 */
+	return M360AllocateBufferDescriptors (((count * 4) +
+					sizeof(m360BufferDescriptor_t) - 1) / 
+					sizeof(m360BufferDescriptor_t));
+}
Index: c/src/lib/libbsp/m68k/gen68360/startup/init68360.c
===================================================================
--- c/src/lib/libbsp/m68k/gen68360/startup/init68360.c	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/lib/libbsp/m68k/gen68360/startup/init68360.c	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -37,5 +37,5 @@
 {
 	int i;
-	extern void *_RomBase, *_RamBase;
+	unsigned long l;
 	m68k_isr_entry *vbr;
 	extern void _CopyDataClearBSSAndStart (void);
@@ -59,6 +59,6 @@
 	 */
 	m360.clkocr = 0x8F;	/* No more writes, no clock outputs */
-	m360.pllcr = 0xD000;	/* PLL, no writes, no prescale,  */
-					/* no LPSTOP slowdown, PLL X1 */
+	m360.pllcr = 0xD000;	/* PLL, no writes, no prescale,
+				   no LPSTOP slowdown, PLL X1 */
 	m360.cdvcr = 0x8000;	/* No more writes, no clock division */
 
@@ -67,10 +67,10 @@
 	 *	Disable watchdog FIXME: Should use watchdog!!!!
 	 *	Watchdog causes system reset
-	 *	Fastest watchdog timeout
+	 *	Slowest watchdog timeout
 	 *	Enable double bus fault monitor
 	 *	Enable bus monitor external
 	 *	128 clocks for external timeout
 	 */
-	m360.sypcr = 0x4F;
+	m360.sypcr = 0x7F;
 
 	/*
@@ -90,8 +90,8 @@
 	 *	CF1MODE=00 (CONFIG1 input)
 	 *	RAS1* double drive
-	 *	A31-A28
+	 *	WE0* - WE3*
 	 *	OE* output
-	 *	CAS2* / CAS3*
-	 *	CAS0* / CAS1*
+	 *	CAS2* - CAS3*
+	 *	CAS0* - CAS1*
 	 *	CS7*
 	 *	AVEC*
@@ -100,48 +100,127 @@
 	 *	(static RAM, external address multiplexing, etc).
 	 */
-	m360.pepar = 0x0100;
+	m360.pepar = 0x0180;
 
 	/*
 	 * Step 11: Remap Chip Select 0 (CS0*), set up GMR
-	 *	1024 addresses per DRAM page (1M DRAM chips)
-	 *	60 nsec DRAM
-	 *	180 nsec ROM (3 wait states)
-	 * HARDWARE:
-	 *	Change if you are using a different memory configuration
-	 */
-	m360.gmr = M360_GMR_RCNT(24) | M360_GMR_RFEN | M360_GMR_RCYC(0) |
-			M360_GMR_PGS(3) | M360_GMR_DPS_32BIT | M360_GMR_NCS |
-			M360_GMR_GAMX;
-	m360.memc[0].br = (unsigned long)&_RomBase | M360_MEMC_BR_WP |
-							M360_MEMC_BR_V;
-	m360.memc[0].or = M360_MEMC_OR_WAITS(3) | M360_MEMC_OR_512KB |
+	 */
+	if (&_MC68360HardwareType == &_MC68360HardwareTypeAtlasHSB) {
+		m360.gmr = M360_GMR_RCNT(12) | M360_GMR_RFEN | 
+				M360_GMR_RCYC(0) | M360_GMR_PGS(1) | 
+				M360_GMR_DPS_32BIT | M360_GMR_DWQ |
+				M360_GMR_GAMX;
+		m360.memc[0].br = (unsigned long)&_RomBase | M360_MEMC_BR_WP |
+								M360_MEMC_BR_V;
+		m360.memc[0].or = M360_MEMC_OR_WAITS(3) | M360_MEMC_OR_1MB |
 							M360_MEMC_OR_8BIT;
+	}
+	else {
+		/*
+		 * 1024/2048/4096 addresses per DRAM page (1M/4M/16M DRAM chips)
+		 * 60 nsec DRAM
+		 * 180 nsec ROM (3 wait states)
+		 */
+		switch ((unsigned long)&_RamSize) {
+		default:
+		case 4*1024*1024:
+			m360.gmr = M360_GMR_RCNT(24) | M360_GMR_RFEN | 
+					M360_GMR_RCYC(0) | M360_GMR_PGS(3) |
+					M360_GMR_DPS_32BIT | M360_GMR_NCS | 
+					M360_GMR_GAMX;
+			break;
+
+		case 16*1024*1024:
+			m360.gmr = M360_GMR_RCNT(24) | M360_GMR_RFEN | 
+					M360_GMR_RCYC(0) | M360_GMR_PGS(5) |
+					M360_GMR_DPS_32BIT | M360_GMR_NCS | 
+					M360_GMR_GAMX;
+			break;
+
+		case 64*1024*1024:
+			m360.gmr = M360_GMR_RCNT(24) | M360_GMR_RFEN | 
+					M360_GMR_RCYC(0) | M360_GMR_PGS(7) |
+					M360_GMR_DPS_32BIT | M360_GMR_NCS | 
+					M360_GMR_GAMX;
+			break;
+		}
+		m360.memc[0].br = (unsigned long)&_RomBase | M360_MEMC_BR_WP |
+								M360_MEMC_BR_V;
+		m360.memc[0].or = M360_MEMC_OR_WAITS(3) | M360_MEMC_OR_1MB |
+							M360_MEMC_OR_8BIT;
+	}
 
 	/*
 	 * Step 12: Initialize the system RAM
-	 *	Set up option/base registers
-	 *		4 MB DRAM
-	 *		60 nsec DRAM
-	 *	Wait for chips to power up
-	 *	Perform 8 read cycles
-	 *	Set all parity bits to correct state
-	 *	Enable parity checking
-	 * HARDWARE:
-	 *	Change if you are using a different memory configuration
-	 */
-	m360.memc[1].or = M360_MEMC_OR_TCYC(0) | M360_MEMC_OR_4MB |
-				M360_MEMC_OR_DRAM;
-	m360.memc[1].br = (unsigned long)&_RamBase | M360_MEMC_BR_V;
-	for (i = 0; i < 50000; i++)
-		continue;
-	for (i = 0; i < 8; ++i)
-		*((volatile unsigned long *)(unsigned long)&_RamBase);
-	for (i = 0 ; i < 4*1024*1024 ; i += sizeof (unsigned long)) {
-		volatile unsigned long *lp;
-		lp = (unsigned long *)((unsigned char *)&_RamBase + i);
-		*lp = *lp;
-	}
-	m360.memc[1].br = (unsigned long)&_RamBase | M360_MEMC_BR_PAREN |
+	 */
+	if (&_MC68360HardwareType == &_MC68360HardwareTypeAtlasHSB) {
+		/* first bank 1MByte DRAM */
+		m360.memc[1].or = M360_MEMC_OR_TCYC(2) | M360_MEMC_OR_1MB |
+					M360_MEMC_OR_PGME | M360_MEMC_OR_DRAM;
+		m360.memc[1].br = (unsigned long)&_RamBase | M360_MEMC_BR_V;
+
+		/* second bank 1MByte DRAM */
+		m360.memc[2].or = M360_MEMC_OR_TCYC(2) | M360_MEMC_OR_1MB |
+					M360_MEMC_OR_PGME | M360_MEMC_OR_DRAM;
+		m360.memc[2].br = ((unsigned long)&_RamBase + 0x100000) |
+					M360_MEMC_BR_V;
+
+		/* flash rom socket U6 on CS5 */
+		m360.memc[5].br = (unsigned long)ATLASHSB_ROM_U6 | M360_MEMC_BR_WP |
 								M360_MEMC_BR_V;
+		m360.memc[5].or = M360_MEMC_OR_WAITS(2) | M360_MEMC_OR_512KB |
+								M360_MEMC_OR_8BIT;
+
+		/* CSRs on CS7 */
+		m360.memc[7].or = M360_MEMC_OR_TCYC(4) | M360_MEMC_OR_64KB |
+					M360_MEMC_OR_8BIT;
+		m360.memc[7].br = ATLASHSB_ESR | 0x01;
+		for (i = 0; i < 50000; i++)
+			continue;
+		for (i = 0; i < 8; ++i)
+			*((volatile unsigned long *)(unsigned long)&_RamBase);
+	}
+	else {
+		/*
+		 *	Set up option/base registers
+		 *		4M/16M/64M DRAM
+		 *		60 nsec DRAM
+		 *	Wait for chips to power up
+		 *	Perform 8 read cycles
+		 *	Set all parity bits to correct state
+		 *	Enable parity checking
+		 */
+		switch ((unsigned long)&_RamSize) {
+		default:
+		case 4*1024*1024:
+			m360.memc[1].or = M360_MEMC_OR_TCYC(0) |
+						M360_MEMC_OR_4MB |
+						M360_MEMC_OR_DRAM;
+			break;
+
+		case 16*1024*1024:
+			m360.memc[1].or = M360_MEMC_OR_TCYC(0) |
+						M360_MEMC_OR_16MB |
+						M360_MEMC_OR_DRAM;
+			break;
+
+		case 64*1024*1024:
+			m360.memc[1].or = M360_MEMC_OR_TCYC(0) |
+						M360_MEMC_OR_64MB |
+						M360_MEMC_OR_DRAM;
+			break;
+		}
+		m360.memc[1].br = (unsigned long)&_RamBase | M360_MEMC_BR_V;
+		for (i = 0; i < 50000; i++)
+			continue;
+		for (i = 0; i < 8; ++i)
+			*((volatile unsigned long *)(unsigned long)&_RamBase);
+		for (l = 0 ; l < (unsigned long)&_RamSize ; l += sizeof (unsigned long)) {
+			volatile unsigned long *lp;
+			lp = (unsigned long *)((unsigned char *)&_RamBase + i);
+			*lp = *lp;
+		}
+		m360.memc[1].br = (unsigned long)&_RamBase |
+					M360_MEMC_BR_PAREN | M360_MEMC_BR_V;
+	}
 
 	/*
@@ -156,4 +235,5 @@
 	 * Step 14: More system initialization
 	 * SDCR (Serial DMA configuration register)
+	 *	Disable SDMA during FREEZE
 	 *	Give SDMA priority over all interrupt handlers
 	 *	Set DMA arbiration level to 4
@@ -168,5 +248,5 @@
 	 *	SCCs priority grouped at top of table
 	 */
-	m360.sdcr = M360_SDMA_SISM_7 | M360_SDMA_SAID_4;
+	m360.sdcr = M360_SDMA_FREEZE | M360_SDMA_SISM_7 | M360_SDMA_SAID_4;
 	m360.cicr = (3 << 22) | (2 << 20) | (1 << 18) | (0 << 16) |
 						(4 << 13) | (0x1F << 8) | (128);
@@ -179,5 +259,5 @@
 	 *	No show cycles
 	 *	User/supervisor access
-	 *	Bus clear interupt service level 7
+	 *	Bus clear interrupt service level 7
 	 *	SIM60 interrupt sources higher priority than CPM
 	 */
Index: c/src/lib/libbsp/m68k/gen68360/startup/linkcmds
===================================================================
--- c/src/lib/libbsp/m68k/gen68360/startup/linkcmds	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/lib/libbsp/m68k/gen68360/startup/linkcmds	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -1,4 +1,6 @@
 /*
- *  This file contains GNU linker directives for a generic MC68360 board.
+ * This file contains GNU linker directives for a generic MC68360 board.
+ * Variations in hardware type and dynamic memory size can be made
+ * by overriding some values with linker command-line arguments.
  *
  * Saskatchewan Accelerator Laboratory
@@ -11,8 +13,28 @@
 
 /*
- * Declare on-board memory
+ * Declare some sizes.
+ * XXX: The assignment of ". += XyzSize;" fails in older gld's if the
+ *      number used there is not constant.  If this happens to you, edit
+ *      the lines marked XXX below to use a constant value.
+ */
+RamSize = DEFINED(RamSize) ? RamSize : 4M;
+HeapSize = DEFINED(HeapSize) ? HeapSize : 0x10000;
+StackSize = DEFINED(StackSize) ? StackSize : 0x1000;
+
+/*
+ * Declare hardware type
+ */
+MC68360HardwareTypeMotorolaGeneric = 0; 
+MC68360HardwareTypeAtlasHSB = 1; 
+MC68360HardwareType = DEFINED(MC68360HardwareType) ? MC68360HardwareType : 0;
+
+/*
+ * Declare on-board memory.
+ * It would be nice if the ram length could be given as
+ * LENGTH=RamSize, but gld doesn't allow non-constant
+ * values in the LENGTH expression.  
  */
 MEMORY {
-          ram : ORIGIN = 0x00000000, LENGTH = 4M
+          ram : ORIGIN = 0x00000000, LENGTH = 64M
           rom : ORIGIN = 0xFF000000, LENGTH = 1M
         dpram : ORIGIN = 0xFE000000, LENGTH = 8k
@@ -20,16 +42,16 @@
 
 /*
- * Declare some sizes
- * XXX: The assignment of ". += XyzSize;" fails in older gld's if the
- *      number used there is not constant.  If this happens to you, edit
- *      the lines marked below to use a constant value.
+ * Declare low-order three octets of Ethernet address.
  */
-HeapSize = DEFINED(HeapSize) ? HeapSize : 0x10000;
-StackSize = DEFINED(StackSize) ? StackSize : 0x1000;
+ETHERNET_ADDRESS = DEFINED(ETHERNET_ADDRESS) ? ETHERNET_ADDRESS : 0xDEAD12;
 
 /*
- * Declare low-order three octets of Ethernet address
+ * Declare hardware type.
+ * Acceptable values are:
+ *	0 - Generic system as described in the MC68360 User's Manual
+ *	    (MC68360UM/AD Rev. 1).
+ *	1 - ATLAS Computer Equipment Incorporated ACE360/HSB.
  */
-ETHERNET_ADDRESS = DEFINED(ETHERNET_ADDRESS) ? ETHERNET_ADDRESS : 0xDEAD12;
+MC68360HardwareType = DEFINED(MC68360HardwareType) ? MC68360HardwareType : 0;
 
 /*
@@ -37,4 +59,16 @@
  */
 SECTIONS {
+	/*
+	 * Hardware variations
+	 */
+	_RamSize = RamSize;
+	__RamSize = RamSize;
+	_MC68360HardwareType = MC68360HardwareType;
+	__MC68360HardwareType = MC68360HardwareType;
+	_MC68360HardwareTypeMotorolaGeneric = MC68360HardwareTypeMotorolaGeneric; 
+	__MC68360HardwareTypeMotorolaGeneric = MC68360HardwareTypeMotorolaGeneric; 
+	_MC68360HardwareTypeAtlasHSB = MC68360HardwareTypeAtlasHSB; 
+	__MC68360HardwareTypeAtlasHSB = MC68360HardwareTypeAtlasHSB; 
+
         /*
          * Boot PROM
Index: c/src/lib/libbsp/m68k/gen68360/startup/linkcmds.bootp
===================================================================
--- c/src/lib/libbsp/m68k/gen68360/startup/linkcmds.bootp	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
+++ c/src/lib/libbsp/m68k/gen68360/startup/linkcmds.bootp	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -0,0 +1,146 @@
+/*
+ * This file contains GNU linker directives for a generic MC68360 board.
+ * Variations in hardware type and dynamic memory size can be made
+ * by overriding some values with linker command-line arguments.
+ *
+ * These linker directives are for producing a PROM version.
+ * To create the PROM image from the linker output you must use objcopy
+ * (--adjust-section-vma) to place the data segment at the end of the text
+ * segment in the PROM.  The start-up code takes care of copying this region
+ * to RAM.
+ *
+ * Saskatchewan Accelerator Laboratory
+ * University of Saskatchewan
+ * Saskatoon, Saskatchewan, CANADA
+ * eric@skatter.usask.ca
+ * 
+ *  $Id$
+ */
+
+/*
+ * Declare some sizes.
+ * XXX: The assignment of ". += XyzSize;" fails in older gld's if the
+ *      number used there is not constant.  If this happens to you, edit
+ *      the lines marked XXX below to use a constant value.
+ */
+RamSize = DEFINED(RamSize) ? RamSize : 4M;
+HeapSize = DEFINED(HeapSize) ? HeapSize : 0x10000;
+StackSize = DEFINED(StackSize) ? StackSize : 0x1000;
+
+/*
+ * Declare hardware type
+ */
+MC68360HardwareTypeMotorolaGeneric = 0; 
+MC68360HardwareTypeAtlasHSB = 1; 
+MC68360HardwareType = DEFINED(MC68360HardwareType) ? MC68360HardwareType : 0;
+
+/*
+ * Declare on-board memory.
+ * It would be nice if the ram length could be given as
+ * LENGTH=RamSize, but gld doesn't allow non-constant
+ * values in the LENGTH expression.  
+ */
+MEMORY {
+          ram : ORIGIN = 0x00000000, LENGTH = 64M
+        myram : ORIGIN = 4M-512k,    LENGTH = 512k
+          rom : ORIGIN = 0xFF000000, LENGTH = 1M
+        dpram : ORIGIN = 0xFE000000, LENGTH = 8k
+}
+
+/*
+ * Declare low-order three octets of Ethernet address.
+ */
+ETHERNET_ADDRESS = DEFINED(ETHERNET_ADDRESS) ? ETHERNET_ADDRESS : 0xDEAD12;
+
+/*
+ * Declare hardware type.
+ * Acceptable values are:
+ *	0 - Generic system as described in the MC68360 User's Manual
+ *	    (MC68360UM/AD Rev. 1).
+ *	1 - ATLAS Computer Equipment Incorporated ACE360/HSB.
+ */
+MC68360HardwareType = DEFINED(MC68360HardwareType) ? MC68360HardwareType : 0;
+
+/*
+ * Load objects
+ */
+SECTIONS {
+	/*
+	 * Hardware variations
+	 */
+	_RamSize = RamSize;
+	__RamSize = RamSize;
+	_MC68360HardwareType = MC68360HardwareType;
+	__MC68360HardwareType = MC68360HardwareType;
+	_MC68360HardwareTypeMotorolaGeneric = MC68360HardwareTypeMotorolaGeneric; 
+	__MC68360HardwareTypeMotorolaGeneric = MC68360HardwareTypeMotorolaGeneric; 
+	_MC68360HardwareTypeAtlasHSB = MC68360HardwareTypeAtlasHSB; 
+	__MC68360HardwareTypeAtlasHSB = MC68360HardwareTypeAtlasHSB; 
+
+        /*
+         * Boot PROM
+         */
+        rom : {
+                _RomBase = .;
+                __RomBase = .;
+        } >rom
+
+        /*
+         * Dynamic RAM
+         */
+        ram : {
+                _RamBase = .;
+                __RamBase = .;
+        } >ram
+
+        /*
+         * Text, data and bss segments
+         */
+        .text : AT (0x00000000) {
+                CREATE_OBJECT_SYMBOLS
+                *(.text)
+                . = ALIGN (16);
+                etext = .;
+                _etext = .;
+        } >rom 
+        .data : AT(SIZEOF(.text)) {
+                copy_start = .;
+                *(.data)
+                . = ALIGN (16);
+                _edata = .;
+                copy_end = .;
+        } >myram
+        .bss : {
+                M68Kvec = .;
+                _M68Kvec = .;
+                . += (256 * 4);
+                clear_start = .;
+                *(.bss)
+                *(COMMON)
+                . = ALIGN (16);
+                _end = .;
+
+                _HeapStart = .;
+                __HeapStart = .;
+                . += HeapSize;  /* XXX -- Old gld can't handle this */
+                . += StackSize; /* XXX -- Old gld can't handle this */
+                /* . += 0x10000; */ /* HeapSize for old gld */
+                /* . += 0x1000;  */ /* StackSize for old gld */
+                . = ALIGN (16);
+                stack_init = .;
+                clear_end = .;
+
+                _WorkspaceBase = .;
+                __WorkspaceBase = .;
+        } >myram
+
+        /*
+         * On-chip memory/peripherals
+         */
+        dpram : {
+                m360 = .;
+                _m360 = .;
+                . += (8 * 1024);
+
+        } >dpram
+}
Index: c/src/lib/libbsp/m68k/gen68360/startup/linkcmds.prom
===================================================================
--- c/src/lib/libbsp/m68k/gen68360/startup/linkcmds.prom	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/lib/libbsp/m68k/gen68360/startup/linkcmds.prom	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -1,6 +1,9 @@
 /*
  * This file contains GNU linker directives for a generic MC68360 board.
- * These linker directives are for producing a PROM version..
- * To create the PROM image from the linkter output you must use objcopy
+ * Variations in hardware type and dynamic memory size can be made
+ * by overriding some values with linker command-line arguments.
+ *
+ * These linker directives are for producing a BOOTP PROM.
+ * To create the PROM image from the linker output you must use objcopy
  * (--adjust-section-vma) to place the data segment at the end of the text
  * segment in the PROM.  The start-up code takes care of copying this region
@@ -21,8 +24,28 @@
 
 /*
- * Declare on-board memory
+ * Declare some sizes.
+ * XXX: The assignment of ". += XyzSize;" fails in older gld's if the
+ *      number used there is not constant.  If this happens to you, edit
+ *      the lines marked XXX below to use a constant value.
+ */
+RamSize = DEFINED(RamSize) ? RamSize : 4M;
+HeapSize = DEFINED(HeapSize) ? HeapSize : 0x10000;
+StackSize = DEFINED(StackSize) ? StackSize : 0x1000;
+
+/*
+ * Declare hardware type
+ */
+MC68360HardwareTypeMotorolaGeneric = 0; 
+MC68360HardwareTypeAtlasHSB = 1; 
+MC68360HardwareType = DEFINED(MC68360HardwareType) ? MC68360HardwareType : 0;
+
+/*
+ * Declare on-board memory.
+ * It would be nice if the ram length could be given as
+ * LENGTH=RamSize, but gld doesn't allow non-constant
+ * values in the LENGTH expression.  
  */
 MEMORY {
-          ram : ORIGIN = 0x00000000, LENGTH = 4M
+          ram : ORIGIN = 0x00000000, LENGTH = 64M
           rom : ORIGIN = 0xFF000000, LENGTH = 1M
         dpram : ORIGIN = 0xFE000000, LENGTH = 8k
@@ -30,13 +53,16 @@
 
 /*
- * Declare some sizes
+ * Declare low-order three octets of Ethernet address.
  */
-HeapSize = DEFINED(HeapSize) ? HeapSize : 0x10000;
-StackSize = DEFINED(StackSize) ? StackSize : 0x1000;
+ETHERNET_ADDRESS = DEFINED(ETHERNET_ADDRESS) ? ETHERNET_ADDRESS : 0xDEAD12;
 
 /*
- * Declare low-order three octets of Ethernet address
+ * Declare hardware type.
+ * Acceptable values are:
+ *	0 - Generic system as described in the MC68360 User's Manual
+ *	    (MC68360UM/AD Rev. 1).
+ *	1 - ATLAS Computer Equipment Incorporated ACE360/HSB.
  */
-ETHERNET_ADDRESS = DEFINED(ETHERNET_ADDRESS) ? ETHERNET_ADDRESS : 0xDEAD12;
+MC68360HardwareType = DEFINED(MC68360HardwareType) ? MC68360HardwareType : 0;
 
 /*
@@ -44,4 +70,16 @@
  */
 SECTIONS {
+	/*
+	 * Hardware variations
+	 */
+	_RamSize = RamSize;
+	__RamSize = RamSize;
+	_MC68360HardwareType = MC68360HardwareType;
+	__MC68360HardwareType = MC68360HardwareType;
+	_MC68360HardwareTypeMotorolaGeneric = MC68360HardwareTypeMotorolaGeneric; 
+	__MC68360HardwareTypeMotorolaGeneric = MC68360HardwareTypeMotorolaGeneric; 
+	_MC68360HardwareTypeAtlasHSB = MC68360HardwareTypeAtlasHSB; 
+	__MC68360HardwareTypeAtlasHSB = MC68360HardwareTypeAtlasHSB; 
+
         /*
          * Boot PROM
@@ -89,6 +127,8 @@
                 _HeapStart = .;
                 __HeapStart = .;
-                . += HeapSize;
-                . += StackSize;
+                . += HeapSize;  /* XXX -- Old gld can't handle this */
+                . += StackSize; /* XXX -- Old gld can't handle this */
+                /* . += 0x10000; */ /* HeapSize for old gld */
+                /* . += 0x1000;  */ /* StackSize for old gld */
                 . = ALIGN (16);
                 stack_init = .;
@@ -108,4 +148,3 @@
 
         } >dpram
-
 }
Index: c/src/lib/libbsp/m68k/gen68360/wrapup/Makefile.in
===================================================================
--- c/src/lib/libbsp/m68k/gen68360/wrapup/Makefile.in	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/lib/libbsp/m68k/gen68360/wrapup/Makefile.in	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -8,9 +8,16 @@
 VPATH=@srcdir@
 
-BSP_PIECES=startup clock console timer
+# We only build the ka9q device driver if HAS_KA9Q was defined
+LIBKA9Q_yes_V = network
+LIBKA9Q = $(LIBKA9Q_$(HAS_KA9Q)_V)
+
+BSP_PIECES=startup clock console $(LIBKA9Q) timer
+CPU_PIECES=
 GENERIC_PIECES=
 
 # bummer; have to use $foreach since % pattern subst rules only replace 1x
 OBJS=$(foreach piece, $(BSP_PIECES), ../$(piece)/$(ARCH)/$(piece).rel) \
+     $(foreach piece, $(CPU_PIECES), \
+         ../../../../libcpu/$(RTEMS_CPU)/$(piece)/$(ARCH)/$(piece).rel) \
      $(foreach piece, $(GENERIC_PIECES), ../../../$(piece)/$(ARCH)/$(piece).rel)
 LIB=$(ARCH)/libbsp.a
Index: c/src/lib/libc/libio.c
===================================================================
--- c/src/lib/libc/libio.c	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/lib/libc/libio.c	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -80,4 +80,26 @@
     } while (0)
 
+/*
+ * External I/O handlers
+ * 
+ * Space for all possible handlers is preallocated
+ * to speed up dispatch to external handlers.
+ */
+
+static rtems_libio_handler_t handlers[15];
+
+void
+rtems_register_libio_handler(
+    int                         handler_flag,
+    const rtems_libio_handler_t *handler
+)
+{
+  int handler_index = rtems_file_descriptor_type_index(handler_flag);
+
+  if ((handler_index < 0) || (handler_index >= 15))
+    rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER );
+  handlers[handler_index] = *handler;
+}
+
 
 void
@@ -85,5 +107,5 @@
     rtems_configuration_table *config,
     unsigned32                 max_fds
-  )
+)
 {
     rtems_libio_number_iops = max_fds;
@@ -254,13 +276,14 @@
     rtems_libio_open_close_args_t args;
 
-    if ((rc = rtems_io_lookup_name(pathname, &np)) != RTEMS_SUCCESSFUL) {
-/*
-      if ( rc == RTEMS_UNSATISFIED ) {
-        puts( "open -- ENOSYS case" );
-        assert( 0 );
-      }
-*/
+    /*
+     * Additional external I/O handlers would be supported by
+     * adding code to pick apart the pathname appropriately.
+     * The networking code does not require changes here since
+     * network file descriptors are obtained using socket(), not
+     * open().
+     */
+
+    if ((rc = rtems_io_lookup_name(pathname, &np)) != RTEMS_SUCCESSFUL)
         goto done;
-    }
 
     iop = rtems_libio_allocate();
@@ -300,7 +323,18 @@
     rtems_status_code rc;
     rtems_driver_name_t *np;
-    rtems_libio_t *iop = rtems_libio_iop(fd);
+    rtems_libio_t *iop;
     rtems_libio_open_close_args_t args;
 
+    if (rtems_file_descriptor_type(fd)) {
+        int (*fp)(int fd);
+
+        fp = handlers[rtems_file_descriptor_type_index(fd)].close;
+        if (fp == NULL) {
+            errno = EBADF;
+            return -1;
+        }
+        return (*fp)(fd);
+    }
+    iop = rtems_libio_iop(fd);
     rtems_libio_check_fd(fd);
 
@@ -327,7 +361,18 @@
     rtems_status_code rc;
     rtems_driver_name_t *np;
-    rtems_libio_t *iop = rtems_libio_iop(fd);
+    rtems_libio_t *iop;
     rtems_libio_rw_args_t args;
 
+    if (rtems_file_descriptor_type(fd)) {
+        int (*fp)(int fd, void *buffer, unsigned32 count);
+
+        fp = handlers[rtems_file_descriptor_type_index(fd)].read;
+        if (fp == NULL) {
+            errno = EBADF;
+            return -1;
+        }
+        return (*fp)(fd, buffer, count);
+    }
+    iop = rtems_libio_iop(fd);
     rtems_libio_check_fd(fd);
     rtems_libio_check_buffer(buffer);
@@ -363,7 +408,18 @@
     rtems_status_code rc;
     rtems_driver_name_t *np;
-    rtems_libio_t *iop = rtems_libio_iop(fd);
+    rtems_libio_t *iop;
     rtems_libio_rw_args_t args;
 
+    if (rtems_file_descriptor_type(fd)) {
+        int (*fp)(int fd, const void *buffer, unsigned32 count);
+
+        fp = handlers[rtems_file_descriptor_type_index(fd)].write;
+        if (fp == NULL) {
+            errno = EBADF;
+            return -1;
+        }
+        return (*fp)(fd, buffer, count);
+    }
+    iop = rtems_libio_iop(fd);
     rtems_libio_check_fd(fd);
     rtems_libio_check_buffer(buffer);
@@ -398,7 +454,18 @@
     rtems_status_code rc;
     rtems_driver_name_t *np;
-    rtems_libio_t *iop = rtems_libio_iop(fd);
+    rtems_libio_t *iop;
     rtems_libio_ioctl_args_t args;
 
+    if (rtems_file_descriptor_type(fd)) {
+        int (*fp)(int fd, unsigned32 command, void *buffer);
+
+        fp = handlers[rtems_file_descriptor_type_index(fd)].ioctl;
+        if (fp == NULL) {
+            errno = EBADF;
+            return -1;
+        }
+        return (*fp)(fd, command, buffer);
+    }
+    iop = rtems_libio_iop(fd);
     rtems_libio_check_fd(fd);
 
@@ -429,6 +496,17 @@
   )    
 {
-    rtems_libio_t *iop = rtems_libio_iop(fd);
-
+    rtems_libio_t *iop;
+
+    if (rtems_file_descriptor_type(fd)) {
+        int (*fp)(int fd, rtems_libio_offset_t offset, int whence);
+
+        fp = handlers[rtems_file_descriptor_type_index(fd)].lseek;
+        if (fp == NULL) {
+            errno = EBADF;
+            return -1;
+        }
+        return (*fp)(fd, offset, whence);
+    }
+    iop = rtems_libio_iop(fd);
     rtems_libio_check_fd(fd);
 
Index: c/src/lib/libc/libio.h
===================================================================
--- c/src/lib/libc/libio.h	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/lib/libc/libio.h	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -100,3 +100,25 @@
 int __rtems_isatty(int _fd);
 
+/*
+ * External I/O handlers
+ */
+typedef struct {
+    int (*open)(const char  *pathname, unsigned32 flag, unsigned32 mode);
+    int (*close)(int  fd);
+    int (*read)(int fd, void *buffer, unsigned32 count);
+    int (*write)(int fd, const void *buffer, unsigned32 count);
+    int (*ioctl)(int fd, unsigned32  command, void *buffer);
+    int (*lseek)(int fd, rtems_libio_offset_t offset, int whence);
+} rtems_libio_handler_t;
+
+void rtems_register_libio_handler(int handler_flag,
+                                 const rtems_libio_handler_t *handler);
+
+#define RTEMS_FILE_DESCRIPTOR_TYPE_FILE         0x0000
+#define RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET       0x1000
+#define rtems_make_file_descriptor(fd,flags)    ((fd)|(flags))
+#define rtems_file_descriptor_base(fd)          ((fd) & 0x0FFF)
+#define rtems_file_descriptor_type(fd)          ((fd) & 0xF000)
+#define rtems_file_descriptor_type_index(fd)    ((((fd) & 0xF000) >> 12) - 1)
+
 #endif /* _RTEMS_LIBIO_H */
Index: c/src/lib/wrapup/Makefile.in
===================================================================
--- c/src/lib/wrapup/Makefile.in	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/lib/wrapup/Makefile.in	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -18,4 +18,5 @@
      $(PROJECT_HOME)/lib/librtems$(LIB_VARIANT).a \
      $(wildcard $(PROJECT_HOME)/lib/libposix$(LIB_VARIANT).a) \
+     $(wildcard $(PROJECT_HOME)/lib/libka9q$(LIB_VARIANT).a) \
      $(PROJECT_HOME)/lib/libcsupport$(LIB_VARIANT).a \
      $(wildcard $(PROJECT_HOME)/lib/rtems-ctor$(LIB_VARIANT).o) \
Index: c/src/wrapup/Makefile.in
===================================================================
--- c/src/wrapup/Makefile.in	(revision bed475e288765cbfafffe79a3cb69ea7f3027c86)
+++ c/src/wrapup/Makefile.in	(revision e2d795597310f976af211f9bac2466dbf89b50c8)
@@ -18,4 +18,5 @@
      $(PROJECT_HOME)/lib/librtems$(LIB_VARIANT).a \
      $(wildcard $(PROJECT_HOME)/lib/libposix$(LIB_VARIANT).a) \
+     $(wildcard $(PROJECT_HOME)/lib/libka9q$(LIB_VARIANT).a) \
      $(PROJECT_HOME)/lib/libcsupport$(LIB_VARIANT).a \
      $(wildcard $(PROJECT_HOME)/lib/rtems-ctor$(LIB_VARIANT).o) \
