Subject: Re: Is it normal for serial ports to drop characters at the end?

From: Marcus Sundberg <[email-masked]>
Date: 03 May 2000 21:27:56 +0200

"Brown, David (dbrown03)" <[email-masked]> writes:

> I see characters dropped at the end of a write to a serial port.  Surely
> that isn't normal.
> I'm using the current MontaVista 2.2.13 kernel patched for my custom
> 860-based board.  The serial ports are running at 9600.
>
> When I do this:
> init-2.00# help while >/dev/ttyS1

[snip]

> well.  Could it be that when a serial port is closed, the uart is disabled
> immediately instead of waiting for output to finish?

Right on target.
rs_8xx_wait_until_sent() will wait for the *first* buffer descriptor
to be finished, instead of waiting for the last one as it should.
This patch fixes that problem:

diff -bu uart.orig uart.c
--- uart.c.orig	Wed May  3 20:25:09 2000
+++ uart.c	Fri Apr 28 20:08:15 2000
@@ -1710,6 +1718,13 @@
 	 * be at least two characters waiting to be sent after the buffers
 	 * are empty.
 	 */
+	bdp = info->tx_cur;
+	/* We want to wait for the last buffer, not the first. */
+	if (bdp == info->tx_bd_base) {
+		bdp += (TX_NUM_FIFO-1);
+	} else {
+		bdp--;
+	}
 	do {
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
 		printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
@@ -1721,7 +1736,6 @@
 			break;
 		if (timeout && ((orig_jiffies + timeout) < jiffies))
 			break;
-		bdp = info->tx_cur;
 	} while (bdp->cbd_sc & BD_SC_READY);
 	current->state = TASK_RUNNING;
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT

There is also a problem with kernel messages being truncated when
an application open the serial console. This patch should fix that:

diff -bu uart.orig uart.c
--- uart.c.orig	Wed May  3 20:25:09 2000
+++ uart.c	Fri Apr 28 20:08:15 2000
@@ -915,8 +909,20 @@
 		info->read_status_mask &= ~BD_SC_EMPTY;
 	save_flags(flags); cli();

+	/* Make sure last buffer has been sent. */
+	{
+		volatile cbd_t	*bdp;
+		bdp = info->tx_cur;
+		if (bdp == info->tx_bd_base) {
+			bdp += (TX_NUM_FIFO-1);
+		} else {
+			bdp--;
+		}
+		while (bdp->cbd_sc & BD_SC_READY);
+	}
+
 	/* Start bit has not been added (so don't, because we would just
 	 * subtract it later), and we need to add one for the number of
 	 * stops bits (there is always at least one).
 	 */
 	bits++;

//Marcus
--
-------------------------------+-----------------------------------
        Marcus Sundberg        |       Phone: +46 707 452062
  Embedded Systems Consultant  |      Email: [email-masked]
       Cendio Systems AB       |       http://www.cendio.se/

** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/