diff --git a/sys/arch/arm32/dev/com.c b/sys/arch/arm32/dev/com.c index 5a57703007a3..165d4956246e 100644 --- a/sys/arch/arm32/dev/com.c +++ b/sys/arch/arm32/dev/com.c @@ -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)) diff --git a/sys/arch/arm32/mainbus/com.c b/sys/arch/arm32/mainbus/com.c index 5a57703007a3..165d4956246e 100644 --- a/sys/arch/arm32/mainbus/com.c +++ b/sys/arch/arm32/mainbus/com.c @@ -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))