Subject: bug in /sys/arch/i386/isa/com.c:1.31.2.4: discards output bytes
To: None <gnats-bugs@netbsd.org>
From: John Kohl <jtk@kolvir.blrc.ma.us>
List: current-users
Date: 09/05/1994 13:33:36
>Submitter-Id: net
>Originator: John Kohl
>Organization:
"MIT SIPB"
>Confidential: no
>Synopsis: com.c will discard in-transit FIFO data if tcsetattr() invoked
>Severity: serious
>Priority: high
>Category: port-i386
>Class: sw-bug
>Release: 1.0_BETA
>Environment:
NetBSD 1.0_BETA i386 (-current)
System: NetBSD kolvir 1.0_BETA NetBSD 1.0_BETA (KOLVIR) #42: Mon Sep 5 13:18:51 EDT 1994 jtk@kolvir:/local/usr/src/local/NetBSD/src/sys/arch/i386/compile/KOLVIR i386
>Description:
The serial line COM code can destroy in-transit FIFO data if
comparam() is invoked to set some parameters. This can cause UUCP to fail
in mysterious ways, and probably causes other programs some problems.
>How-To-Repeat:
Open a com port with a FIFO, shove data down it, then do
something to affect the hardware (e.g. toggle CRTSCTS). Note that the
receiver doesn't get all the in-transit bytes.
>Fix:
The problem lies in the FIFO reset code inside comparam().
There's no need to adjust the FIFO trigger level unless the baud rate is
being changed.
The patch below includes a reinstatement of the FIFO trigger
initialization in comopen(); otherwise the trigger level would not be
set until the baud rate is changed from the default baud rate. [This
code was removed when the trigger level stuff was moved to comparam()]
The patch is relative to:
! * $Id: com.c,v 1.31.2.4 1994/08/24 07:29:42 mycroft Exp $
*** 1.1 1994/09/05 15:15:28
--- com.c 1994/09/05 17:24:23
***************
*** 297,302 ****
--- 297,308 ----
iobase = sc->sc_iobase;
/* flush any pending I/O */
+ if (sc->sc_hwflags & COM_HW_FIFO)
+ outb(iobase + com_fifo,
+ FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST |
+ FIFO_TRIGGER_8);
+ /* The FIFO trigger level is adjusted when speed
+ changes, see below */
(void) inb(iobase + com_lsr);
(void) inb(iobase + com_data);
/* you turn me on, baby */
***************
*** 555,562 ****
s = spltty();
! /* Set the FIFO threshold based on the receive speed. */
! if (sc->sc_hwflags & COM_HW_FIFO)
outb(iobase + com_fifo,
FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST |
(t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
--- 561,570 ----
s = spltty();
! /* Set the FIFO threshold based on the receive speed, but only
! if we're changing speed (otherwise we may destroy
! in-transit characters). */
! if (tp->t_ospeed != t->c_ospeed && (sc->sc_hwflags & COM_HW_FIFO))
outb(iobase + com_fifo,
FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST |
(t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
------------------------------------------------------------------------------