Subject: kern/1042: Some serial cards hang on first open if data is in FIFO
To: None <gnats-admin@sun-lamp.cs.berkeley.edu>
From: Scott Reynolds <scottr@Plexus.COM>
List: netbsd-bugs
Date: 05/11/1995 14:20:05
>Number: 1042
>Category: kern
>Synopsis: Some serial cards hang on first open if data is in FIFO
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu May 11 14:20:04 1995
>Originator: Scott Reynolds
>Organization:
>Release: NetBSD-current 08-May-95
>Environment:
Micronics JX30GC motherboard, on-board 16550-compatible UARTs
System: NetBSD aqua 1.0A NetBSD 1.0A (TGI) #46: Wed May 10 16:41:54 CDT 1995 scottr@aqua:/a/src/sys/arch/i386/compile/TGI i386
>Description:
If there is data in the FIFO when the port is first opened, such
as after a cold boot or after a warm boot from Win 3.x/NT 3.5, a
race condition will occur when calling splx() right before
returning from comopen(). This appears with at least some
SMC UARTs.
>How-To-Repeat:
Cold boot with some device that shoves characters into the serial
port after reset, such as a Logitech Mouseman CR-32. If you have
the affected serial chip, the machine will hang on the first open
of the port (e.g. in /etc/rc when 'ttyflags -a' is run).
>Fix:
This method was gleaned from the FreeBSD sio.c driver and mangled
appropriately. The comment comes primarily from sio.c.
*** com.c.orig Fri Apr 28 05:26:11 1995
--- com.c Thu May 11 09:41:01 1995
***************
*** 290,300 ****
ttsetwater(tp);
iobase = sc->sc_iobase;
! /* 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 |
! (tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
/* flush any pending I/O */
(void) inb(iobase + com_lsr);
(void) inb(iobase + com_data);
--- 290,319 ----
ttsetwater(tp);
iobase = sc->sc_iobase;
! if (sc->sc_hwflags & COM_HW_FIFO) {
! /*
! * (Re)enable and drain FIFOs.
! *
! * Certain SMC chips cause problems if the FIFOs are
! * enabled while input is ready. Turn off the FIFO
! * if necessary to clear the input. Test the input
! * ready bit after enabling the FIFOs to handle races
! * between enabling and fresh input.
! *
! * Set the FIFO threshold based on the receive speed.
! */
! for (;;) {
! outb(iobase + com_fifo,
! FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST |
! (tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
! delay(100);
! if ((inb(iobase + com_lsr) & LSR_RXRDY) == 0)
! break;
! outb(iobase + com_fifo, 0);
! delay(100);
! (void) inb(iobase + com_data);
! }
! }
/* flush any pending I/O */
(void) inb(iobase + com_lsr);
(void) inb(iobase + com_data);
>Audit-Trail:
>Unformatted: