Index: c/src/exec/libcsupport/include/rtems/libio.h
===================================================================
--- c/src/exec/libcsupport/include/rtems/libio.h	(revision a307f79f17b6f4a330728f01540c57115d4ec56a)
+++ c/src/exec/libcsupport/include/rtems/libio.h	(revision d24ceb38f71e2b8a0b0822815de35cc0658c2d4e)
@@ -140,5 +140,6 @@
   int                       (*deviceLastClose)(int major, int minor, void *arg),
   int                       (*deviceRead)(int minor),
-  int                       (*deviceWrite)(int minor, char *buf, int len)
+  int                       (*deviceWrite)(int minor, char *buf, int len),
+  int                         deviceOutputUsesInterrupts
   );
 
Index: c/src/exec/libcsupport/src/termios.c
===================================================================
--- c/src/exec/libcsupport/src/termios.c	(revision a307f79f17b6f4a330728f01540c57115d4ec56a)
+++ c/src/exec/libcsupport/src/termios.c	(revision d24ceb38f71e2b8a0b0822815de35cc0658c2d4e)
@@ -2,5 +2,5 @@
  * TERMIOS serial line support
  *
- *  Authors:
+ *  Author:
  *    W. Eric Norum
  *    Saskatchewan Accelerator Laboratory
@@ -8,11 +8,4 @@
  *    Saskatoon, Saskatchewan, CANADA
  *    eric@skatter.usask.ca
- *
- *    AND
- * 
- *    Katsutoshi Shibuya
- *    BU Denken Co.,Ltd.
- *    Sapporo, JAPAN
- *    shibuya@mxb.meshnet.or.jp
  *
  *  The license and distribution terms for this file may be
@@ -38,7 +31,10 @@
 
 /*
- * The size of the raw input message queue
- */
-#define RAW_BUFFER_SIZE	128
+ * The sizes of the raw message buffers.
+ * On most architectures it is quite a bit more
+ * efficient if these are powers of two.
+ */
+#define RAW_INPUT_BUFFER_SIZE	128
+#define RAW_OUTPUT_BUFFER_SIZE	64
 
 /*
@@ -90,14 +86,24 @@
 
 	/*
-	 * Raw character buffer
-	 */
-	volatile char		rawBuf[RAW_BUFFER_SIZE];
-	volatile unsigned int	rawBufHead;
-	volatile unsigned int	rawBufTail;
-	rtems_id		rawBufSemaphore;
-	rtems_unsigned32	rawBufSemaphoreOptions;
-	rtems_interval		rawBufSemaphoreTimeout;
-	rtems_interval		rawBufSemaphoreFirstTimeout;
-	unsigned int		rawBufDropped;	/* Statistics */
+	 * Raw input character buffer
+	 */
+	volatile char		rawInBuf[RAW_INPUT_BUFFER_SIZE];
+	volatile unsigned int	rawInBufHead;
+	volatile unsigned int	rawInBufTail;
+	rtems_id		rawInBufSemaphore;
+	rtems_unsigned32	rawInBufSemaphoreOptions;
+	rtems_interval		rawInBufSemaphoreTimeout;
+	rtems_interval		rawInBufSemaphoreFirstTimeout;
+	unsigned int		rawInBufDropped;	/* Statistics */
+
+	/*
+	 * Raw output character buffer
+	 */
+	char			outputUsesInterrupts;
+	volatile char		rawOutBuf[RAW_OUTPUT_BUFFER_SIZE];
+	volatile unsigned int	rawOutBufHead;
+	volatile unsigned int	rawOutBufTail;
+	rtems_id		rawOutBufSemaphore;
+	enum {rob_idle, rob_busy, rob_wait }	rawOutBufState;
 
 	/*
@@ -110,4 +116,27 @@
 static struct rtems_termios_tty *ttyHead, *ttyTail;
 static rtems_id ttyMutex;
+
+/*
+ *  Reserve enough resources to open every physical device once.
+ */
+void
+rtems_termios_reserve_resources (
+  rtems_configuration_table *configuration,
+  rtems_unsigned32           number_of_devices
+  )
+{
+	static int first_time = 1;
+	rtems_api_configuration_table *rtems_config;
+
+	if (!configuration)
+		rtems_fatal_error_occurred (0xFFF0F001);
+	rtems_config = configuration->RTEMS_api_configuration;
+	if (!rtems_config)
+		rtems_fatal_error_occurred (0xFFF0F002);
+	if (first_time)
+		rtems_config->maximum_semaphores += 1;
+	first_time = 0;
+	rtems_config->maximum_semaphores += (4 * number_of_devices);
+}
 
 void
@@ -142,5 +171,6 @@
   int                      (*deviceLastClose)(int major, int minor, void *arg),
   int                      (*deviceRead)(int minor),
-  int                      (*deviceWrite)(int minor, char *buf, int len)
+  int                      (*deviceWrite)(int minor, char *buf, int len),
+  int                        deviceOutputUsesInterrupts
   )
 {
@@ -195,4 +225,14 @@
 		if (sc != RTEMS_SUCCESSFUL)
 			rtems_fatal_error_occurred (sc);
+		sc = rtems_semaphore_create (
+			rtems_build_name ('T', 'R', 'x', c),
+			0,
+			RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
+			RTEMS_NO_PRIORITY,
+			&tty->rawOutBufSemaphore);
+		if (sc != RTEMS_SUCCESSFUL)
+			rtems_fatal_error_occurred (sc);
+		tty->rawOutBufHead = 0;
+		tty->rawOutBufTail = 0;
 
 		/*
@@ -207,9 +247,9 @@
 				RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
 				RTEMS_NO_PRIORITY,
-				&tty->rawBufSemaphore);
+				&tty->rawInBufSemaphore);
 			if (sc != RTEMS_SUCCESSFUL)
 				rtems_fatal_error_occurred (sc);
-			tty->rawBufHead = 0;
-			tty->rawBufTail = 0;
+			tty->rawInBufHead = 0;
+			tty->rawInBufTail = 0;
 		}
 
@@ -219,4 +259,5 @@
 		tty->column = 0;
 		tty->cindex = tty->ccount = 0;
+		tty->outputUsesInterrupts = deviceOutputUsesInterrupts;
 
 		/*
@@ -267,5 +308,4 @@
 	rtems_status_code sc;
 
-	args->ioctl_return = 0;
 	sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
 	if (sc != RTEMS_SUCCESSFUL)
@@ -284,6 +324,7 @@
 		rtems_semaphore_delete (tty->isem);
 		rtems_semaphore_delete (tty->osem);
+		rtems_semaphore_delete (tty->rawOutBufSemaphore);
 		if (tty->read == NULL)
-			rtems_semaphore_delete (tty->rawBufSemaphore);
+			rtems_semaphore_delete (tty->rawInBufSemaphore);
 		free (tty);
 	}
@@ -299,4 +340,5 @@
 	rtems_status_code sc;
 
+ 	args->ioctl_return = 0;
 	sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
 	if (sc != RTEMS_SUCCESSFUL)
@@ -314,7 +356,7 @@
 		tty->termios = *(struct termios *)args->buffer;
 		if (tty->termios.c_lflag & ICANON) {
-			tty->rawBufSemaphoreOptions = RTEMS_WAIT;
-			tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
-			tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
+			tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
+			tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
+			tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
 		}
 		else {
@@ -323,19 +365,19 @@
 			tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
 			if (tty->termios.c_cc[VTIME]) {
-				tty->rawBufSemaphoreOptions = RTEMS_WAIT;
-				tty->rawBufSemap`oreTimeout = tty->vtimeTicks;
+				tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
+				tty->rawInBufSemaphoreTimeout = tty->vtimeTicks;
 				if (tty->termios.c_cc[VMIN])
-					tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
+					tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
 				else
-					tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks;
+					tty->rawInBufSemaphoreFirstTimeout = tty->vtimeTicks;
 			}
 			else {
 				if (tty->termios.c_cc[VMIN]) {
-					tty->rawBufSemaphoreOptions = RTEMS_WAIT;
-					tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
-					tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
+					tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
+					tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
+					tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
 				}
 				else {
-					tty->rawBufSemaphoreOptions = RTEMS_NO_WAIT;
+					tty->rawInBufSemaphoreOptions = RTEMS_NO_WAIT;
 				}
 			}
@@ -345,4 +387,58 @@
 	rtems_semaphore_release (tty->osem);
 	return sc;
+}
+
+/*
+ * Send characters to device-specific code
+ */
+static void
+osend (const char *buf, int len, struct rtems_termios_tty *tty)
+{
+	unsigned int newHead;
+	rtems_interrupt_level level;
+	rtems_status_code sc;
+
+	if (!tty->outputUsesInterrupts) {
+		(*tty->write)(tty->minor, buf, len);
+		return;
+	}
+	newHead = tty->rawOutBufHead;
+	while (len) {
+		/*
+		 * Performance improvement could be made here.
+		 * Copy multiple bytes to raw buffer:
+		 * if (len > 1) && (space to buffer end, or tail > 1)
+		 *	ncopy = MIN (len, space to buffer end or tail)
+		 *	memcpy (raw buffer, buf, ncopy)
+		 *	buf += ncopy
+		 *	len -= ncopy
+		 *
+		 * To minimize latency, the memcpy should be done
+		 * with interrupts enabled.
+		 */
+		newHead = (newHead + 1) % RAW_OUTPUT_BUFFER_SIZE;
+		rtems_interrupt_disable (level);
+		while (newHead == tty->rawOutBufTail) {
+			tty->rawOutBufState = rob_wait;
+			rtems_interrupt_enable (level);
+			sc = rtems_semaphore_obtain (tty->rawOutBufSemaphore,
+							RTEMS_WAIT,
+							RTEMS_NO_TIMEOUT);
+			if (sc != RTEMS_SUCCESSFUL)
+				rtems_fatal_error_occurred (sc);
+			rtems_interrupt_disable (level);
+		}
+		tty->rawOutBuf[tty->rawOutBufHead] = *buf++;
+		tty->rawOutBufHead = newHead;
+		if (tty->rawOutBufState == rob_idle) {
+			rtems_interrupt_enable (level);
+			tty->rawOutBufState = rob_busy;
+			(*tty->write)(tty->minor, (char *)&tty->rawOutBuf[tty->rawOutBufTail], 1);
+		}
+		else {
+			rtems_interrupt_enable (level);
+		}
+		len--;
+	}
 }
 
@@ -361,5 +457,5 @@
 				tty->column = 0;
 			if (tty->termios.c_oflag & ONLCR) {
-				(*tty->write)(tty->minor, "\r", 1);
+				osend ("\r", 1, tty);
 				tty->column = 0;
 			}
@@ -382,5 +478,5 @@
 			if ((tty->termios.c_oflag & TABDLY) == XTABS) {
 				tty->column += i;
-				(*tty->write)(tty->minor,  "        ",  i);
+				osend ( "        ",  i, tty);
 				return;
 			}
@@ -401,5 +497,5 @@
 		}
 	}
-	(*tty->write)(tty->minor, &c, 1);
+	osend (&c, 1, tty);
 }
 
@@ -422,8 +518,6 @@
 	}
 	else {
-		if ((*tty->write)(tty->minor, args->buffer, args->count) < 0)
-			sc = RTEMS_UNSATISFIED;
-		else
-			args->bytes_moved = args->count;
+		osend (args->buffer, args->count, tty);
+		args->bytes_moved = args->count;
 	}
 	rtems_semaphore_release (tty->osem);
@@ -442,5 +536,5 @@
 		echobuf[0] = '^';
 		echobuf[1] = c ^ 0x40;
-		(*tty->write)(tty->minor, echobuf, 2);
+		osend (echobuf, 2, tty);
 		tty->column += 2;
 	}
@@ -505,5 +599,5 @@
 				 */
 				while (tty->column > col) {
-					(*tty->write)(tty->minor, "\b", 1);
+					osend ("\b", 1, tty);
 					tty->column--;
 				}
@@ -511,10 +605,10 @@
 			else {
 				if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) {
-					(*tty->write)(tty->minor, "\b \b", 3);
+					osend ("\b \b", 3, tty);
 					if (tty->column)
 						tty->column--;
 				}
 				if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) {
-					(*tty->write)(tty->minor, "\b \b", 3);
+					osend ("\b \b", 3, tty);
 					if (tty->column)
 						tty->column--;
@@ -669,5 +763,5 @@
 fillBufferQueue (struct rtems_termios_tty *tty)
 {
-	rtems_interval timeout = tty->rawBufSemaphoreFirstTimeout;
+	rtems_interval timeout = tty->rawInBufSemaphoreFirstTimeout;
 	rtems_status_code sc;
 
@@ -676,11 +770,11 @@
 		 * Process characters read from raw queue
 		 */
-		while (tty->rawBufHead != tty->rawBufTail) {
+		while (tty->rawInBufHead != tty->rawInBufTail) {
 			unsigned char c;
 			unsigned int newHead;
 
-			newHead = (tty->rawBufHead + 1) % RAW_BUFFER_SIZE;
-			c = tty->rawBuf[newHead];
-			tty->rawBufHead = newHead;
+			newHead = (tty->rawInBufHead + 1) % RAW_INPUT_BUFFER_SIZE;
+			c = tty->rawInBuf[newHead];
+			tty->rawInBufHead = newHead;
 			if (tty->termios.c_lflag & ICANON) {
 				if  (siproc (c, tty))
@@ -692,5 +786,5 @@
 					return RTEMS_SUCCESSFUL;
 			}
-			timeout = tty->rawBufSemaphoreTimeout;
+			timeout = tty->rawInBufSemaphoreTimeout;
 		}
 
@@ -698,6 +792,6 @@
 		 * Wait for characters
 		 */
-		sc = rtems_semaphore_obtain (tty->rawBufSemaphore,
-						tty->rawBufSemaphoreOptions,
+		sc = rtems_semaphore_obtain (tty->rawInBufSemaphore,
+						tty->rawInBufSemaphoreOptions,
 						timeout);
 		if (sc != RTEMS_SUCCESSFUL)
@@ -740,5 +834,6 @@
 /*
  * Place characters on raw queue.
- * NOTE: This routine runs in the context of the device interrupt handler.
+ * NOTE: This routine runs in the context of the
+ *       device receive interrupt handler.
  */
 void
@@ -749,39 +844,51 @@
 
 	while (len) {
-		newTail = (tty->rawBufTail + 1) % RAW_BUFFER_SIZE;
-		if (newTail == tty->rawBufHead) {
-			tty->rawBufDropped += len;
+		newTail = (tty->rawInBufTail + 1) % RAW_INPUT_BUFFER_SIZE;
+		if (newTail == tty->rawInBufHead) {
+			tty->rawInBufDropped += len;
 			break;
 		}
-		tty->rawBuf[newTail] = *buf++;
+		tty->rawInBuf[newTail] = *buf++;
 		len--;
-		tty->rawBufTail = newTail;
-	}
-	rtems_semaphore_release (tty->rawBufSemaphore);
-}
-
-/*
- *  Reserve enough resources to open every physical device once.
- */
-
-void rtems_termios_reserve_resources(
-  rtems_configuration_table *configuration,
-  rtems_unsigned32           number_of_devices
-)
-{
-  static int first_time = 1;
-  rtems_api_configuration_table *rtems_config;
-
-  if (!configuration)
-    rtems_fatal_error_occurred (0xFFF0F001);
-
-  rtems_config = configuration->RTEMS_api_configuration;
-  if (!rtems_config)
-    rtems_fatal_error_occurred (0xFFF0F002);
-
-  if (first_time)
-    rtems_config->maximum_semaphores += 1;
-
-  first_time = 0;
-  rtems_config->maximum_semaphores += (3 * number_of_devices);
-}
+		tty->rawInBufTail = newTail;
+	}
+	rtems_semaphore_release (tty->rawInBufSemaphore);
+}
+
+/*
+ * Characters have been transmitted
+ * NOTE: This routine runs in the context of the
+ *       device transmit interrupt handler.
+ * The second argument is the number of characters transmitted so far.
+ * This value will always be 1 for devices which generate an interrupt
+ * for each transmitted character.
+ */
+void
+rtems_termios_dequeue_characters (void *ttyp, int len)
+{
+	struct rtems_termios_tty *tty = ttyp;
+	unsigned int newTail;
+	int nToSend;
+
+	if (tty->rawOutBufState == rob_wait)
+		rtems_semaphore_release (tty->rawOutBufSemaphore);
+	newTail = (tty->rawOutBufTail + len) % RAW_OUTPUT_BUFFER_SIZE;
+	if (newTail == tty->rawOutBufHead) {
+		/*
+		 * Buffer empty
+		 */
+		tty->rawOutBufState = rob_idle;
+	}
+	else {
+		/*
+		 * Buffer not empty, start tranmitter
+		 */
+		tty->rawOutBufState = rob_busy;
+		if (newTail > tty->rawOutBufHead)
+			nToSend = RAW_OUTPUT_BUFFER_SIZE - newTail;
+		else
+			nToSend = tty->rawOutBufHead - newTail;
+		(*tty->write)(tty->minor, (char *)&tty->rawOutBuf[newTail], nToSend);
+	}
+	tty->rawOutBufTail = newTail;
+}
Index: c/src/lib/include/rtems/libio.h
===================================================================
--- c/src/lib/include/rtems/libio.h	(revision a307f79f17b6f4a330728f01540c57115d4ec56a)
+++ c/src/lib/include/rtems/libio.h	(revision d24ceb38f71e2b8a0b0822815de35cc0658c2d4e)
@@ -140,5 +140,6 @@
   int                       (*deviceLastClose)(int major, int minor, void *arg),
   int                       (*deviceRead)(int minor),
-  int                       (*deviceWrite)(int minor, char *buf, int len)
+  int                       (*deviceWrite)(int minor, char *buf, int len),
+  int                         deviceOutputUsesInterrupts
   );
 
Index: c/src/lib/libbsp/m68k/gen68360/console/console.c
===================================================================
--- c/src/lib/libbsp/m68k/gen68360/console/console.c	(revision a307f79f17b6f4a330728f01540c57115d4ec56a)
+++ c/src/lib/libbsp/m68k/gen68360/console/console.c	(revision d24ceb38f71e2b8a0b0822815de35cc0658c2d4e)
@@ -41,5 +41,5 @@
  * I/O buffers and pointers to buffer descriptors
  */
-static volatile char rxBuf[RXBUFSIZE], txBuf;
+static volatile char rxBuf[RXBUFSIZE];
 static volatile m360BufferDescriptor_t *smcRxBd, *smcTxBd;
 
@@ -63,4 +63,13 @@
 		}
 	}
+
+	/*
+	 * Buffer transmitted?
+	 */
+	if (m360.smc1.smce & 0x2) {
+		m360.smc1.smce = 0x2;
+		if ((smcTxBd->status & M360_BD_READY) == 0)
+			rtems_termios_dequeue_characters (smc1ttyp, smcTxBd->length);
+	}
 	m360.cisr = 1UL << 4;	/* Clear SMC1 interrupt-in-service bit */
 }
@@ -123,6 +132,4 @@
 	 */
 	smcTxBd->status = M360_BD_WRAP;
-	smcTxBd->length = 1;
-	smcTxBd->buffer = &txBuf;
 	 
 	/*
@@ -151,5 +158,5 @@
 						(m360.cicr & 0xE0) | 0x04,
 						&old_handler);
-	m360.smc1.smcm = 1;	/* Enable SMC1 receiver interrupt */
+	m360.smc1.smcm = 3;	/* Enable SMC1 TX and RX interrupts */
 	m360.cimr |= 1UL << 4;	/* Enable SMC1 interrupts */
 	}
@@ -169,17 +176,30 @@
 }
 
+/*
+ * Device-dependent write routine
+ * Interrupt-driven devices:
+ *	Begin transmission of as many characters as possible (minimum is 1).
+ * Polling devices:
+ *	Transmit all characters.
+ */
 static int
 smc1Write (int minor, char *buf, int len)
 {
-	int nwrite = 0;
-
-	while (nwrite < len) {
+#if (defined (M360_SMC1_INTERRUPT))
+	smcTxBd->buffer = buf;
+	smcTxBd->length = len;
+	smcTxBd->status = M360_BD_READY | M360_BD_WRAP | M360_BD_INTERRUPT;
+#else
+	while (len--) {
+		static char txBuf;
 		while (smcTxBd->status & M360_BD_READY)
 			continue;
 		txBuf = *buf++;
+		smcTxBd->buffer = &txBuf;
+		smcTxBd->length = 1;
 		smcTxBd->status = M360_BD_READY | M360_BD_WRAP;
-		nwrite++;
 	}
-	return nwrite;
+#endif
+	return 0;
 }
 
@@ -189,4 +209,14 @@
  ***************
  */
+
+/*
+ * Reserve resources consumed by this driver
+ */
+void console_reserve_resources(
+  rtems_configuration_table *configuration
+)
+{
+	rtems_termios_reserve_resources (configuration, 1);
+}
 
 /*
@@ -238,5 +268,6 @@
 			NULL,
 			NULL,
-			smc1Write);
+			smc1Write,
+			1);
 	smc1ttyp = args->iop->data1;
 #else
@@ -245,5 +276,6 @@
 			NULL,
 			smc1Read,
-			smc1Write);
+			smc1Write,
+			0);
 #endif
 	return sc;
Index: c/src/lib/libc/libio.h
===================================================================
--- c/src/lib/libc/libio.h	(revision a307f79f17b6f4a330728f01540c57115d4ec56a)
+++ c/src/lib/libc/libio.h	(revision d24ceb38f71e2b8a0b0822815de35cc0658c2d4e)
@@ -140,5 +140,6 @@
   int                       (*deviceLastClose)(int major, int minor, void *arg),
   int                       (*deviceRead)(int minor),
-  int                       (*deviceWrite)(int minor, char *buf, int len)
+  int                       (*deviceWrite)(int minor, char *buf, int len),
+  int                         deviceOutputUsesInterrupts
   );
 
Index: c/src/lib/libc/termios.c
===================================================================
--- c/src/lib/libc/termios.c	(revision a307f79f17b6f4a330728f01540c57115d4ec56a)
+++ c/src/lib/libc/termios.c	(revision d24ceb38f71e2b8a0b0822815de35cc0658c2d4e)
@@ -2,5 +2,5 @@
  * TERMIOS serial line support
  *
- *  Authors:
+ *  Author:
  *    W. Eric Norum
  *    Saskatchewan Accelerator Laboratory
@@ -8,11 +8,4 @@
  *    Saskatoon, Saskatchewan, CANADA
  *    eric@skatter.usask.ca
- *
- *    AND
- * 
- *    Katsutoshi Shibuya
- *    BU Denken Co.,Ltd.
- *    Sapporo, JAPAN
- *    shibuya@mxb.meshnet.or.jp
  *
  *  The license and distribution terms for this file may be
@@ -38,7 +31,10 @@
 
 /*
- * The size of the raw input message queue
- */
-#define RAW_BUFFER_SIZE	128
+ * The sizes of the raw message buffers.
+ * On most architectures it is quite a bit more
+ * efficient if these are powers of two.
+ */
+#define RAW_INPUT_BUFFER_SIZE	128
+#define RAW_OUTPUT_BUFFER_SIZE	64
 
 /*
@@ -90,14 +86,24 @@
 
 	/*
-	 * Raw character buffer
-	 */
-	volatile char		rawBuf[RAW_BUFFER_SIZE];
-	volatile unsigned int	rawBufHead;
-	volatile unsigned int	rawBufTail;
-	rtems_id		rawBufSemaphore;
-	rtems_unsigned32	rawBufSemaphoreOptions;
-	rtems_interval		rawBufSemaphoreTimeout;
-	rtems_interval		rawBufSemaphoreFirstTimeout;
-	unsigned int		rawBufDropped;	/* Statistics */
+	 * Raw input character buffer
+	 */
+	volatile char		rawInBuf[RAW_INPUT_BUFFER_SIZE];
+	volatile unsigned int	rawInBufHead;
+	volatile unsigned int	rawInBufTail;
+	rtems_id		rawInBufSemaphore;
+	rtems_unsigned32	rawInBufSemaphoreOptions;
+	rtems_interval		rawInBufSemaphoreTimeout;
+	rtems_interval		rawInBufSemaphoreFirstTimeout;
+	unsigned int		rawInBufDropped;	/* Statistics */
+
+	/*
+	 * Raw output character buffer
+	 */
+	char			outputUsesInterrupts;
+	volatile char		rawOutBuf[RAW_OUTPUT_BUFFER_SIZE];
+	volatile unsigned int	rawOutBufHead;
+	volatile unsigned int	rawOutBufTail;
+	rtems_id		rawOutBufSemaphore;
+	enum {rob_idle, rob_busy, rob_wait }	rawOutBufState;
 
 	/*
@@ -110,4 +116,27 @@
 static struct rtems_termios_tty *ttyHead, *ttyTail;
 static rtems_id ttyMutex;
+
+/*
+ *  Reserve enough resources to open every physical device once.
+ */
+void
+rtems_termios_reserve_resources (
+  rtems_configuration_table *configuration,
+  rtems_unsigned32           number_of_devices
+  )
+{
+	static int first_time = 1;
+	rtems_api_configuration_table *rtems_config;
+
+	if (!configuration)
+		rtems_fatal_error_occurred (0xFFF0F001);
+	rtems_config = configuration->RTEMS_api_configuration;
+	if (!rtems_config)
+		rtems_fatal_error_occurred (0xFFF0F002);
+	if (first_time)
+		rtems_config->maximum_semaphores += 1;
+	first_time = 0;
+	rtems_config->maximum_semaphores += (4 * number_of_devices);
+}
 
 void
@@ -142,5 +171,6 @@
   int                      (*deviceLastClose)(int major, int minor, void *arg),
   int                      (*deviceRead)(int minor),
-  int                      (*deviceWrite)(int minor, char *buf, int len)
+  int                      (*deviceWrite)(int minor, char *buf, int len),
+  int                        deviceOutputUsesInterrupts
   )
 {
@@ -195,4 +225,14 @@
 		if (sc != RTEMS_SUCCESSFUL)
 			rtems_fatal_error_occurred (sc);
+		sc = rtems_semaphore_create (
+			rtems_build_name ('T', 'R', 'x', c),
+			0,
+			RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
+			RTEMS_NO_PRIORITY,
+			&tty->rawOutBufSemaphore);
+		if (sc != RTEMS_SUCCESSFUL)
+			rtems_fatal_error_occurred (sc);
+		tty->rawOutBufHead = 0;
+		tty->rawOutBufTail = 0;
 
 		/*
@@ -207,9 +247,9 @@
 				RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
 				RTEMS_NO_PRIORITY,
-				&tty->rawBufSemaphore);
+				&tty->rawInBufSemaphore);
 			if (sc != RTEMS_SUCCESSFUL)
 				rtems_fatal_error_occurred (sc);
-			tty->rawBufHead = 0;
-			tty->rawBufTail = 0;
+			tty->rawInBufHead = 0;
+			tty->rawInBufTail = 0;
 		}
 
@@ -219,4 +259,5 @@
 		tty->column = 0;
 		tty->cindex = tty->ccount = 0;
+		tty->outputUsesInterrupts = deviceOutputUsesInterrupts;
 
 		/*
@@ -267,5 +308,4 @@
 	rtems_status_code sc;
 
-	args->ioctl_return = 0;
 	sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
 	if (sc != RTEMS_SUCCESSFUL)
@@ -284,6 +324,7 @@
 		rtems_semaphore_delete (tty->isem);
 		rtems_semaphore_delete (tty->osem);
+		rtems_semaphore_delete (tty->rawOutBufSemaphore);
 		if (tty->read == NULL)
-			rtems_semaphore_delete (tty->rawBufSemaphore);
+			rtems_semaphore_delete (tty->rawInBufSemaphore);
 		free (tty);
 	}
@@ -299,4 +340,5 @@
 	rtems_status_code sc;
 
+ 	args->ioctl_return = 0;
 	sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
 	if (sc != RTEMS_SUCCESSFUL)
@@ -314,7 +356,7 @@
 		tty->termios = *(struct termios *)args->buffer;
 		if (tty->termios.c_lflag & ICANON) {
-			tty->rawBufSemaphoreOptions = RTEMS_WAIT;
-			tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
-			tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
+			tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
+			tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
+			tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
 		}
 		else {
@@ -323,19 +365,19 @@
 			tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
 			if (tty->termios.c_cc[VTIME]) {
-				tty->rawBufSemaphoreOptions = RTEMS_WAIT;
-				tty->rawBufSemap`oreTimeout = tty->vtimeTicks;
+				tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
+				tty->rawInBufSemaphoreTimeout = tty->vtimeTicks;
 				if (tty->termios.c_cc[VMIN])
-					tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
+					tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
 				else
-					tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks;
+					tty->rawInBufSemaphoreFirstTimeout = tty->vtimeTicks;
 			}
 			else {
 				if (tty->termios.c_cc[VMIN]) {
-					tty->rawBufSemaphoreOptions = RTEMS_WAIT;
-					tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
-					tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
+					tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
+					tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
+					tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
 				}
 				else {
-					tty->rawBufSemaphoreOptions = RTEMS_NO_WAIT;
+					tty->rawInBufSemaphoreOptions = RTEMS_NO_WAIT;
 				}
 			}
@@ -345,4 +387,58 @@
 	rtems_semaphore_release (tty->osem);
 	return sc;
+}
+
+/*
+ * Send characters to device-specific code
+ */
+static void
+osend (const char *buf, int len, struct rtems_termios_tty *tty)
+{
+	unsigned int newHead;
+	rtems_interrupt_level level;
+	rtems_status_code sc;
+
+	if (!tty->outputUsesInterrupts) {
+		(*tty->write)(tty->minor, buf, len);
+		return;
+	}
+	newHead = tty->rawOutBufHead;
+	while (len) {
+		/*
+		 * Performance improvement could be made here.
+		 * Copy multiple bytes to raw buffer:
+		 * if (len > 1) && (space to buffer end, or tail > 1)
+		 *	ncopy = MIN (len, space to buffer end or tail)
+		 *	memcpy (raw buffer, buf, ncopy)
+		 *	buf += ncopy
+		 *	len -= ncopy
+		 *
+		 * To minimize latency, the memcpy should be done
+		 * with interrupts enabled.
+		 */
+		newHead = (newHead + 1) % RAW_OUTPUT_BUFFER_SIZE;
+		rtems_interrupt_disable (level);
+		while (newHead == tty->rawOutBufTail) {
+			tty->rawOutBufState = rob_wait;
+			rtems_interrupt_enable (level);
+			sc = rtems_semaphore_obtain (tty->rawOutBufSemaphore,
+							RTEMS_WAIT,
+							RTEMS_NO_TIMEOUT);
+			if (sc != RTEMS_SUCCESSFUL)
+				rtems_fatal_error_occurred (sc);
+			rtems_interrupt_disable (level);
+		}
+		tty->rawOutBuf[tty->rawOutBufHead] = *buf++;
+		tty->rawOutBufHead = newHead;
+		if (tty->rawOutBufState == rob_idle) {
+			rtems_interrupt_enable (level);
+			tty->rawOutBufState = rob_busy;
+			(*tty->write)(tty->minor, (char *)&tty->rawOutBuf[tty->rawOutBufTail], 1);
+		}
+		else {
+			rtems_interrupt_enable (level);
+		}
+		len--;
+	}
 }
 
@@ -361,5 +457,5 @@
 				tty->column = 0;
 			if (tty->termios.c_oflag & ONLCR) {
-				(*tty->write)(tty->minor, "\r", 1);
+				osend ("\r", 1, tty);
 				tty->column = 0;
 			}
@@ -382,5 +478,5 @@
 			if ((tty->termios.c_oflag & TABDLY) == XTABS) {
 				tty->column += i;
-				(*tty->write)(tty->minor,  "        ",  i);
+				osend ( "        ",  i, tty);
 				return;
 			}
@@ -401,5 +497,5 @@
 		}
 	}
-	(*tty->write)(tty->minor, &c, 1);
+	osend (&c, 1, tty);
 }
 
@@ -422,8 +518,6 @@
 	}
 	else {
-		if ((*tty->write)(tty->minor, args->buffer, args->count) < 0)
-			sc = RTEMS_UNSATISFIED;
-		else
-			args->bytes_moved = args->count;
+		osend (args->buffer, args->count, tty);
+		args->bytes_moved = args->count;
 	}
 	rtems_semaphore_release (tty->osem);
@@ -442,5 +536,5 @@
 		echobuf[0] = '^';
 		echobuf[1] = c ^ 0x40;
-		(*tty->write)(tty->minor, echobuf, 2);
+		osend (echobuf, 2, tty);
 		tty->column += 2;
 	}
@@ -505,5 +599,5 @@
 				 */
 				while (tty->column > col) {
-					(*tty->write)(tty->minor, "\b", 1);
+					osend ("\b", 1, tty);
 					tty->column--;
 				}
@@ -511,10 +605,10 @@
 			else {
 				if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) {
-					(*tty->write)(tty->minor, "\b \b", 3);
+					osend ("\b \b", 3, tty);
 					if (tty->column)
 						tty->column--;
 				}
 				if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) {
-					(*tty->write)(tty->minor, "\b \b", 3);
+					osend ("\b \b", 3, tty);
 					if (tty->column)
 						tty->column--;
@@ -669,5 +763,5 @@
 fillBufferQueue (struct rtems_termios_tty *tty)
 {
-	rtems_interval timeout = tty->rawBufSemaphoreFirstTimeout;
+	rtems_interval timeout = tty->rawInBufSemaphoreFirstTimeout;
 	rtems_status_code sc;
 
@@ -676,11 +770,11 @@
 		 * Process characters read from raw queue
 		 */
-		while (tty->rawBufHead != tty->rawBufTail) {
+		while (tty->rawInBufHead != tty->rawInBufTail) {
 			unsigned char c;
 			unsigned int newHead;
 
-			newHead = (tty->rawBufHead + 1) % RAW_BUFFER_SIZE;
-			c = tty->rawBuf[newHead];
-			tty->rawBufHead = newHead;
+			newHead = (tty->rawInBufHead + 1) % RAW_INPUT_BUFFER_SIZE;
+			c = tty->rawInBuf[newHead];
+			tty->rawInBufHead = newHead;
 			if (tty->termios.c_lflag & ICANON) {
 				if  (siproc (c, tty))
@@ -692,5 +786,5 @@
 					return RTEMS_SUCCESSFUL;
 			}
-			timeout = tty->rawBufSemaphoreTimeout;
+			timeout = tty->rawInBufSemaphoreTimeout;
 		}
 
@@ -698,6 +792,6 @@
 		 * Wait for characters
 		 */
-		sc = rtems_semaphore_obtain (tty->rawBufSemaphore,
-						tty->rawBufSemaphoreOptions,
+		sc = rtems_semaphore_obtain (tty->rawInBufSemaphore,
+						tty->rawInBufSemaphoreOptions,
 						timeout);
 		if (sc != RTEMS_SUCCESSFUL)
@@ -740,5 +834,6 @@
 /*
  * Place characters on raw queue.
- * NOTE: This routine runs in the context of the device interrupt handler.
+ * NOTE: This routine runs in the context of the
+ *       device receive interrupt handler.
  */
 void
@@ -749,39 +844,51 @@
 
 	while (len) {
-		newTail = (tty->rawBufTail + 1) % RAW_BUFFER_SIZE;
-		if (newTail == tty->rawBufHead) {
-			tty->rawBufDropped += len;
+		newTail = (tty->rawInBufTail + 1) % RAW_INPUT_BUFFER_SIZE;
+		if (newTail == tty->rawInBufHead) {
+			tty->rawInBufDropped += len;
 			break;
 		}
-		tty->rawBuf[newTail] = *buf++;
+		tty->rawInBuf[newTail] = *buf++;
 		len--;
-		tty->rawBufTail = newTail;
-	}
-	rtems_semaphore_release (tty->rawBufSemaphore);
-}
-
-/*
- *  Reserve enough resources to open every physical device once.
- */
-
-void rtems_termios_reserve_resources(
-  rtems_configuration_table *configuration,
-  rtems_unsigned32           number_of_devices
-)
-{
-  static int first_time = 1;
-  rtems_api_configuration_table *rtems_config;
-
-  if (!configuration)
-    rtems_fatal_error_occurred (0xFFF0F001);
-
-  rtems_config = configuration->RTEMS_api_configuration;
-  if (!rtems_config)
-    rtems_fatal_error_occurred (0xFFF0F002);
-
-  if (first_time)
-    rtems_config->maximum_semaphores += 1;
-
-  first_time = 0;
-  rtems_config->maximum_semaphores += (3 * number_of_devices);
-}
+		tty->rawInBufTail = newTail;
+	}
+	rtems_semaphore_release (tty->rawInBufSemaphore);
+}
+
+/*
+ * Characters have been transmitted
+ * NOTE: This routine runs in the context of the
+ *       device transmit interrupt handler.
+ * The second argument is the number of characters transmitted so far.
+ * This value will always be 1 for devices which generate an interrupt
+ * for each transmitted character.
+ */
+void
+rtems_termios_dequeue_characters (void *ttyp, int len)
+{
+	struct rtems_termios_tty *tty = ttyp;
+	unsigned int newTail;
+	int nToSend;
+
+	if (tty->rawOutBufState == rob_wait)
+		rtems_semaphore_release (tty->rawOutBufSemaphore);
+	newTail = (tty->rawOutBufTail + len) % RAW_OUTPUT_BUFFER_SIZE;
+	if (newTail == tty->rawOutBufHead) {
+		/*
+		 * Buffer empty
+		 */
+		tty->rawOutBufState = rob_idle;
+	}
+	else {
+		/*
+		 * Buffer not empty, start tranmitter
+		 */
+		tty->rawOutBufState = rob_busy;
+		if (newTail > tty->rawOutBufHead)
+			nToSend = RAW_OUTPUT_BUFFER_SIZE - newTail;
+		else
+			nToSend = tty->rawOutBufHead - newTail;
+		(*tty->write)(tty->minor, (char *)&tty->rawOutBuf[newTail], nToSend);
+	}
+	tty->rawOutBufTail = newTail;
+}
Index: cpukit/libcsupport/include/rtems/libio.h
===================================================================
--- cpukit/libcsupport/include/rtems/libio.h	(revision a307f79f17b6f4a330728f01540c57115d4ec56a)
+++ cpukit/libcsupport/include/rtems/libio.h	(revision d24ceb38f71e2b8a0b0822815de35cc0658c2d4e)
@@ -140,5 +140,6 @@
   int                       (*deviceLastClose)(int major, int minor, void *arg),
   int                       (*deviceRead)(int minor),
-  int                       (*deviceWrite)(int minor, char *buf, int len)
+  int                       (*deviceWrite)(int minor, char *buf, int len),
+  int                         deviceOutputUsesInterrupts
   );
 
Index: cpukit/libcsupport/src/termios.c
===================================================================
--- cpukit/libcsupport/src/termios.c	(revision a307f79f17b6f4a330728f01540c57115d4ec56a)
+++ cpukit/libcsupport/src/termios.c	(revision d24ceb38f71e2b8a0b0822815de35cc0658c2d4e)
@@ -2,5 +2,5 @@
  * TERMIOS serial line support
  *
- *  Authors:
+ *  Author:
  *    W. Eric Norum
  *    Saskatchewan Accelerator Laboratory
@@ -8,11 +8,4 @@
  *    Saskatoon, Saskatchewan, CANADA
  *    eric@skatter.usask.ca
- *
- *    AND
- * 
- *    Katsutoshi Shibuya
- *    BU Denken Co.,Ltd.
- *    Sapporo, JAPAN
- *    shibuya@mxb.meshnet.or.jp
  *
  *  The license and distribution terms for this file may be
@@ -38,7 +31,10 @@
 
 /*
- * The size of the raw input message queue
- */
-#define RAW_BUFFER_SIZE	128
+ * The sizes of the raw message buffers.
+ * On most architectures it is quite a bit more
+ * efficient if these are powers of two.
+ */
+#define RAW_INPUT_BUFFER_SIZE	128
+#define RAW_OUTPUT_BUFFER_SIZE	64
 
 /*
@@ -90,14 +86,24 @@
 
 	/*
-	 * Raw character buffer
-	 */
-	volatile char		rawBuf[RAW_BUFFER_SIZE];
-	volatile unsigned int	rawBufHead;
-	volatile unsigned int	rawBufTail;
-	rtems_id		rawBufSemaphore;
-	rtems_unsigned32	rawBufSemaphoreOptions;
-	rtems_interval		rawBufSemaphoreTimeout;
-	rtems_interval		rawBufSemaphoreFirstTimeout;
-	unsigned int		rawBufDropped;	/* Statistics */
+	 * Raw input character buffer
+	 */
+	volatile char		rawInBuf[RAW_INPUT_BUFFER_SIZE];
+	volatile unsigned int	rawInBufHead;
+	volatile unsigned int	rawInBufTail;
+	rtems_id		rawInBufSemaphore;
+	rtems_unsigned32	rawInBufSemaphoreOptions;
+	rtems_interval		rawInBufSemaphoreTimeout;
+	rtems_interval		rawInBufSemaphoreFirstTimeout;
+	unsigned int		rawInBufDropped;	/* Statistics */
+
+	/*
+	 * Raw output character buffer
+	 */
+	char			outputUsesInterrupts;
+	volatile char		rawOutBuf[RAW_OUTPUT_BUFFER_SIZE];
+	volatile unsigned int	rawOutBufHead;
+	volatile unsigned int	rawOutBufTail;
+	rtems_id		rawOutBufSemaphore;
+	enum {rob_idle, rob_busy, rob_wait }	rawOutBufState;
 
 	/*
@@ -110,4 +116,27 @@
 static struct rtems_termios_tty *ttyHead, *ttyTail;
 static rtems_id ttyMutex;
+
+/*
+ *  Reserve enough resources to open every physical device once.
+ */
+void
+rtems_termios_reserve_resources (
+  rtems_configuration_table *configuration,
+  rtems_unsigned32           number_of_devices
+  )
+{
+	static int first_time = 1;
+	rtems_api_configuration_table *rtems_config;
+
+	if (!configuration)
+		rtems_fatal_error_occurred (0xFFF0F001);
+	rtems_config = configuration->RTEMS_api_configuration;
+	if (!rtems_config)
+		rtems_fatal_error_occurred (0xFFF0F002);
+	if (first_time)
+		rtems_config->maximum_semaphores += 1;
+	first_time = 0;
+	rtems_config->maximum_semaphores += (4 * number_of_devices);
+}
 
 void
@@ -142,5 +171,6 @@
   int                      (*deviceLastClose)(int major, int minor, void *arg),
   int                      (*deviceRead)(int minor),
-  int                      (*deviceWrite)(int minor, char *buf, int len)
+  int                      (*deviceWrite)(int minor, char *buf, int len),
+  int                        deviceOutputUsesInterrupts
   )
 {
@@ -195,4 +225,14 @@
 		if (sc != RTEMS_SUCCESSFUL)
 			rtems_fatal_error_occurred (sc);
+		sc = rtems_semaphore_create (
+			rtems_build_name ('T', 'R', 'x', c),
+			0,
+			RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
+			RTEMS_NO_PRIORITY,
+			&tty->rawOutBufSemaphore);
+		if (sc != RTEMS_SUCCESSFUL)
+			rtems_fatal_error_occurred (sc);
+		tty->rawOutBufHead = 0;
+		tty->rawOutBufTail = 0;
 
 		/*
@@ -207,9 +247,9 @@
 				RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
 				RTEMS_NO_PRIORITY,
-				&tty->rawBufSemaphore);
+				&tty->rawInBufSemaphore);
 			if (sc != RTEMS_SUCCESSFUL)
 				rtems_fatal_error_occurred (sc);
-			tty->rawBufHead = 0;
-			tty->rawBufTail = 0;
+			tty->rawInBufHead = 0;
+			tty->rawInBufTail = 0;
 		}
 
@@ -219,4 +259,5 @@
 		tty->column = 0;
 		tty->cindex = tty->ccount = 0;
+		tty->outputUsesInterrupts = deviceOutputUsesInterrupts;
 
 		/*
@@ -267,5 +308,4 @@
 	rtems_status_code sc;
 
-	args->ioctl_return = 0;
 	sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
 	if (sc != RTEMS_SUCCESSFUL)
@@ -284,6 +324,7 @@
 		rtems_semaphore_delete (tty->isem);
 		rtems_semaphore_delete (tty->osem);
+		rtems_semaphore_delete (tty->rawOutBufSemaphore);
 		if (tty->read == NULL)
-			rtems_semaphore_delete (tty->rawBufSemaphore);
+			rtems_semaphore_delete (tty->rawInBufSemaphore);
 		free (tty);
 	}
@@ -299,4 +340,5 @@
 	rtems_status_code sc;
 
+ 	args->ioctl_return = 0;
 	sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
 	if (sc != RTEMS_SUCCESSFUL)
@@ -314,7 +356,7 @@
 		tty->termios = *(struct termios *)args->buffer;
 		if (tty->termios.c_lflag & ICANON) {
-			tty->rawBufSemaphoreOptions = RTEMS_WAIT;
-			tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
-			tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
+			tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
+			tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
+			tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
 		}
 		else {
@@ -323,19 +365,19 @@
 			tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
 			if (tty->termios.c_cc[VTIME]) {
-				tty->rawBufSemaphoreOptions = RTEMS_WAIT;
-				tty->rawBufSemap`oreTimeout = tty->vtimeTicks;
+				tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
+				tty->rawInBufSemaphoreTimeout = tty->vtimeTicks;
 				if (tty->termios.c_cc[VMIN])
-					tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
+					tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
 				else
-					tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks;
+					tty->rawInBufSemaphoreFirstTimeout = tty->vtimeTicks;
 			}
 			else {
 				if (tty->termios.c_cc[VMIN]) {
-					tty->rawBufSemaphoreOptions = RTEMS_WAIT;
-					tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
-					tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
+					tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
+					tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
+					tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
 				}
 				else {
-					tty->rawBufSemaphoreOptions = RTEMS_NO_WAIT;
+					tty->rawInBufSemaphoreOptions = RTEMS_NO_WAIT;
 				}
 			}
@@ -345,4 +387,58 @@
 	rtems_semaphore_release (tty->osem);
 	return sc;
+}
+
+/*
+ * Send characters to device-specific code
+ */
+static void
+osend (const char *buf, int len, struct rtems_termios_tty *tty)
+{
+	unsigned int newHead;
+	rtems_interrupt_level level;
+	rtems_status_code sc;
+
+	if (!tty->outputUsesInterrupts) {
+		(*tty->write)(tty->minor, buf, len);
+		return;
+	}
+	newHead = tty->rawOutBufHead;
+	while (len) {
+		/*
+		 * Performance improvement could be made here.
+		 * Copy multiple bytes to raw buffer:
+		 * if (len > 1) && (space to buffer end, or tail > 1)
+		 *	ncopy = MIN (len, space to buffer end or tail)
+		 *	memcpy (raw buffer, buf, ncopy)
+		 *	buf += ncopy
+		 *	len -= ncopy
+		 *
+		 * To minimize latency, the memcpy should be done
+		 * with interrupts enabled.
+		 */
+		newHead = (newHead + 1) % RAW_OUTPUT_BUFFER_SIZE;
+		rtems_interrupt_disable (level);
+		while (newHead == tty->rawOutBufTail) {
+			tty->rawOutBufState = rob_wait;
+			rtems_interrupt_enable (level);
+			sc = rtems_semaphore_obtain (tty->rawOutBufSemaphore,
+							RTEMS_WAIT,
+							RTEMS_NO_TIMEOUT);
+			if (sc != RTEMS_SUCCESSFUL)
+				rtems_fatal_error_occurred (sc);
+			rtems_interrupt_disable (level);
+		}
+		tty->rawOutBuf[tty->rawOutBufHead] = *buf++;
+		tty->rawOutBufHead = newHead;
+		if (tty->rawOutBufState == rob_idle) {
+			rtems_interrupt_enable (level);
+			tty->rawOutBufState = rob_busy;
+			(*tty->write)(tty->minor, (char *)&tty->rawOutBuf[tty->rawOutBufTail], 1);
+		}
+		else {
+			rtems_interrupt_enable (level);
+		}
+		len--;
+	}
 }
 
@@ -361,5 +457,5 @@
 				tty->column = 0;
 			if (tty->termios.c_oflag & ONLCR) {
-				(*tty->write)(tty->minor, "\r", 1);
+				osend ("\r", 1, tty);
 				tty->column = 0;
 			}
@@ -382,5 +478,5 @@
 			if ((tty->termios.c_oflag & TABDLY) == XTABS) {
 				tty->column += i;
-				(*tty->write)(tty->minor,  "        ",  i);
+				osend ( "        ",  i, tty);
 				return;
 			}
@@ -401,5 +497,5 @@
 		}
 	}
-	(*tty->write)(tty->minor, &c, 1);
+	osend (&c, 1, tty);
 }
 
@@ -422,8 +518,6 @@
 	}
 	else {
-		if ((*tty->write)(tty->minor, args->buffer, args->count) < 0)
-			sc = RTEMS_UNSATISFIED;
-		else
-			args->bytes_moved = args->count;
+		osend (args->buffer, args->count, tty);
+		args->bytes_moved = args->count;
 	}
 	rtems_semaphore_release (tty->osem);
@@ -442,5 +536,5 @@
 		echobuf[0] = '^';
 		echobuf[1] = c ^ 0x40;
-		(*tty->write)(tty->minor, echobuf, 2);
+		osend (echobuf, 2, tty);
 		tty->column += 2;
 	}
@@ -505,5 +599,5 @@
 				 */
 				while (tty->column > col) {
-					(*tty->write)(tty->minor, "\b", 1);
+					osend ("\b", 1, tty);
 					tty->column--;
 				}
@@ -511,10 +605,10 @@
 			else {
 				if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) {
-					(*tty->write)(tty->minor, "\b \b", 3);
+					osend ("\b \b", 3, tty);
 					if (tty->column)
 						tty->column--;
 				}
 				if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) {
-					(*tty->write)(tty->minor, "\b \b", 3);
+					osend ("\b \b", 3, tty);
 					if (tty->column)
 						tty->column--;
@@ -669,5 +763,5 @@
 fillBufferQueue (struct rtems_termios_tty *tty)
 {
-	rtems_interval timeout = tty->rawBufSemaphoreFirstTimeout;
+	rtems_interval timeout = tty->rawInBufSemaphoreFirstTimeout;
 	rtems_status_code sc;
 
@@ -676,11 +770,11 @@
 		 * Process characters read from raw queue
 		 */
-		while (tty->rawBufHead != tty->rawBufTail) {
+		while (tty->rawInBufHead != tty->rawInBufTail) {
 			unsigned char c;
 			unsigned int newHead;
 
-			newHead = (tty->rawBufHead + 1) % RAW_BUFFER_SIZE;
-			c = tty->rawBuf[newHead];
-			tty->rawBufHead = newHead;
+			newHead = (tty->rawInBufHead + 1) % RAW_INPUT_BUFFER_SIZE;
+			c = tty->rawInBuf[newHead];
+			tty->rawInBufHead = newHead;
 			if (tty->termios.c_lflag & ICANON) {
 				if  (siproc (c, tty))
@@ -692,5 +786,5 @@
 					return RTEMS_SUCCESSFUL;
 			}
-			timeout = tty->rawBufSemaphoreTimeout;
+			timeout = tty->rawInBufSemaphoreTimeout;
 		}
 
@@ -698,6 +792,6 @@
 		 * Wait for characters
 		 */
-		sc = rtems_semaphore_obtain (tty->rawBufSemaphore,
-						tty->rawBufSemaphoreOptions,
+		sc = rtems_semaphore_obtain (tty->rawInBufSemaphore,
+						tty->rawInBufSemaphoreOptions,
 						timeout);
 		if (sc != RTEMS_SUCCESSFUL)
@@ -740,5 +834,6 @@
 /*
  * Place characters on raw queue.
- * NOTE: This routine runs in the context of the device interrupt handler.
+ * NOTE: This routine runs in the context of the
+ *       device receive interrupt handler.
  */
 void
@@ -749,39 +844,51 @@
 
 	while (len) {
-		newTail = (tty->rawBufTail + 1) % RAW_BUFFER_SIZE;
-		if (newTail == tty->rawBufHead) {
-			tty->rawBufDropped += len;
+		newTail = (tty->rawInBufTail + 1) % RAW_INPUT_BUFFER_SIZE;
+		if (newTail == tty->rawInBufHead) {
+			tty->rawInBufDropped += len;
 			break;
 		}
-		tty->rawBuf[newTail] = *buf++;
+		tty->rawInBuf[newTail] = *buf++;
 		len--;
-		tty->rawBufTail = newTail;
-	}
-	rtems_semaphore_release (tty->rawBufSemaphore);
-}
-
-/*
- *  Reserve enough resources to open every physical device once.
- */
-
-void rtems_termios_reserve_resources(
-  rtems_configuration_table *configuration,
-  rtems_unsigned32           number_of_devices
-)
-{
-  static int first_time = 1;
-  rtems_api_configuration_table *rtems_config;
-
-  if (!configuration)
-    rtems_fatal_error_occurred (0xFFF0F001);
-
-  rtems_config = configuration->RTEMS_api_configuration;
-  if (!rtems_config)
-    rtems_fatal_error_occurred (0xFFF0F002);
-
-  if (first_time)
-    rtems_config->maximum_semaphores += 1;
-
-  first_time = 0;
-  rtems_config->maximum_semaphores += (3 * number_of_devices);
-}
+		tty->rawInBufTail = newTail;
+	}
+	rtems_semaphore_release (tty->rawInBufSemaphore);
+}
+
+/*
+ * Characters have been transmitted
+ * NOTE: This routine runs in the context of the
+ *       device transmit interrupt handler.
+ * The second argument is the number of characters transmitted so far.
+ * This value will always be 1 for devices which generate an interrupt
+ * for each transmitted character.
+ */
+void
+rtems_termios_dequeue_characters (void *ttyp, int len)
+{
+	struct rtems_termios_tty *tty = ttyp;
+	unsigned int newTail;
+	int nToSend;
+
+	if (tty->rawOutBufState == rob_wait)
+		rtems_semaphore_release (tty->rawOutBufSemaphore);
+	newTail = (tty->rawOutBufTail + len) % RAW_OUTPUT_BUFFER_SIZE;
+	if (newTail == tty->rawOutBufHead) {
+		/*
+		 * Buffer empty
+		 */
+		tty->rawOutBufState = rob_idle;
+	}
+	else {
+		/*
+		 * Buffer not empty, start tranmitter
+		 */
+		tty->rawOutBufState = rob_busy;
+		if (newTail > tty->rawOutBufHead)
+			nToSend = RAW_OUTPUT_BUFFER_SIZE - newTail;
+		else
+			nToSend = tty->rawOutBufHead - newTail;
+		(*tty->write)(tty->minor, (char *)&tty->rawOutBuf[newTail], nToSend);
+	}
+	tty->rawOutBufTail = newTail;
+}
