Subject: Re: kern/1042: Some serial cards hang on first open if data is in FIFO
To: None <gnats-admin@sun-lamp.cs.berkeley.edu, netbsd-bugs@NetBSD.ORG>
From: Scott Reynolds <scottr@Plexus.COM>
List: netbsd-bugs
Date: 07/06/1995 15:16:57
Here's an updated version of my patch to deal with some SMC brain
damage. The SMC 37C665 is included on at least a few Micronics boards.
This patch doesn't break on a real 16550, and leaves the default behavior
for UARTs that don't have multiple-byte FIFOs.
--scott
*** com.c 1995/07/06 16:23:49 1.4
--- com.c 1995/07/06 20:13:41
***************
*** 310,324 ****
sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
- 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 */
! while (inb(iobase + com_lsr) & LSR_RXRDY)
! (void) inb(iobase + com_data);
/* you turn me on, baby */
sc->sc_mcr = MCR_DTR | MCR_RTS;
if ((sc->sc_hwflags & COM_HW_NOIEN) == 0)
--- 310,338 ----
sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
/* flush any pending I/O */
! iobase = sc->sc_iobase;
! if (sc->sc_hwflags & COM_HW_FIFO) {
! /*
! * Drain FIFOs this way to deal with certain SMC
! * chips, otherwise we'll hang hard on the splx()
! * just before returning. Works with real 16550s
! * as well.
! */
! 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);
! }
! } else
! while (inb(iobase + com_lsr) & LSR_RXRDY)
! (void) inb(iobase + com_data);
/* you turn me on, baby */
sc->sc_mcr = MCR_DTR | MCR_RTS;
if ((sc->sc_hwflags & COM_HW_NOIEN) == 0)