Lowered the FIFO trigger threshold to 4 for rather than 8.

Impelemented a fix for kernel locks when opening the serial post :
Revisions A->D of the SMC FDC37GT665 Peripherial controller have
a bug in the serial port that is triggered if the FIFO is enabled
while there is a byte in the rx data register resulting in the
rx ready bit being permenantly set.
This commit is contained in:
mark 1997-01-05 19:19:57 +00:00
parent 17d2a69941
commit c65504baea
2 changed files with 84 additions and 14 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: com.c,v 1.12 1996/10/16 19:32:56 ws Exp $ */
/* $NetBSD: com.c,v 1.13 1997/01/05 19:19:57 mark Exp $ */
/*-
* Copyright (c) 1993, 1994, 1995, 1996
@ -412,7 +412,8 @@ comopen(dev, flag, mode, p)
struct tty *tp;
int s;
int error = 0;
int count;
if (unit >= com_cd.cd_ndevs)
return ENXIO;
sc = com_cd.cd_devs[unit];
@ -467,7 +468,7 @@ comopen(dev, flag, mode, p)
bus_io_write_1(bc, ioh, com_fifo,
FIFO_DMA_MODE|FIFO_ENABLE|
FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_8);
FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_4);
/* Set 16550 compatibility mode */
bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETMODE);
@ -492,14 +493,48 @@ comopen(dev, flag, mode, p)
HAYESP_LOBYTE(HAYESP_RXLOWMARK));
} else
#endif
if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
/*
* This is a patch for bugged revision 1-4 SMC FDC37C665
* I/O controllers.
* If there is RX data pending when the FIFO in turned on
* the RX register cannot be emptied.
*
* Solution:
* Make sure FIFO is off.
* Read pending data / int status etc.
* Enable FIFO.
*/
bus_io_write_1(bc, ioh, com_fifo, 0);
for (count = 0; count < 8; ++count)
(void)bus_io_read_1(bc, ioh, count);
if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
/* Set the FIFO threshold based on the receive speed. */
bus_io_write_1(bc, ioh, 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 (ISSET(bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY))
(tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_4));
/* flush any pending I/O, just incase the fix above fails limit the looping */
count = 1024;
while (ISSET(bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY) && count > 0) {
(void) bus_io_read_1(bc, ioh, com_data);
--count;
}
if (count == 0) {
/*
* Read 1024 bytes from the serial chip and still data !
* This means something is broken ...
*/
printf("com init error: lsr=%02x data=%02x\n",
bus_io_read_1(bc, ioh, com_lsr),
bus_io_read_1(bc, ioh, com_data));
printf("Cannot clear serial input register\n");
CLR(tp->t_state, TS_BUSY | TS_FLUSH);
CLR(tp->t_state, TS_WOPEN);
if (--comsopen == 0)
untimeout(comsoft, NULL);
splx(s);
return(ENXIO);
}
/* you turn me on, baby */
sc->sc_mcr = MCR_DTR | MCR_RTS;
if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))

View File

@ -1,4 +1,4 @@
/* $NetBSD: com.c,v 1.12 1996/10/16 19:32:56 ws Exp $ */
/* $NetBSD: com.c,v 1.13 1997/01/05 19:19:57 mark Exp $ */
/*-
* Copyright (c) 1993, 1994, 1995, 1996
@ -412,7 +412,8 @@ comopen(dev, flag, mode, p)
struct tty *tp;
int s;
int error = 0;
int count;
if (unit >= com_cd.cd_ndevs)
return ENXIO;
sc = com_cd.cd_devs[unit];
@ -467,7 +468,7 @@ comopen(dev, flag, mode, p)
bus_io_write_1(bc, ioh, com_fifo,
FIFO_DMA_MODE|FIFO_ENABLE|
FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_8);
FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_4);
/* Set 16550 compatibility mode */
bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETMODE);
@ -492,14 +493,48 @@ comopen(dev, flag, mode, p)
HAYESP_LOBYTE(HAYESP_RXLOWMARK));
} else
#endif
if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
/*
* This is a patch for bugged revision 1-4 SMC FDC37C665
* I/O controllers.
* If there is RX data pending when the FIFO in turned on
* the RX register cannot be emptied.
*
* Solution:
* Make sure FIFO is off.
* Read pending data / int status etc.
* Enable FIFO.
*/
bus_io_write_1(bc, ioh, com_fifo, 0);
for (count = 0; count < 8; ++count)
(void)bus_io_read_1(bc, ioh, count);
if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
/* Set the FIFO threshold based on the receive speed. */
bus_io_write_1(bc, ioh, 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 (ISSET(bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY))
(tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_4));
/* flush any pending I/O, just incase the fix above fails limit the looping */
count = 1024;
while (ISSET(bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY) && count > 0) {
(void) bus_io_read_1(bc, ioh, com_data);
--count;
}
if (count == 0) {
/*
* Read 1024 bytes from the serial chip and still data !
* This means something is broken ...
*/
printf("com init error: lsr=%02x data=%02x\n",
bus_io_read_1(bc, ioh, com_lsr),
bus_io_read_1(bc, ioh, com_data));
printf("Cannot clear serial input register\n");
CLR(tp->t_state, TS_BUSY | TS_FLUSH);
CLR(tp->t_state, TS_WOPEN);
if (--comsopen == 0)
untimeout(comsoft, NULL);
splx(s);
return(ENXIO);
}
/* you turn me on, baby */
sc->sc_mcr = MCR_DTR | MCR_RTS;
if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))