summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorFederico G. Schwindt <fgsch@cvs.openbsd.org>2005-10-13 14:58:57 +0000
committerFederico G. Schwindt <fgsch@cvs.openbsd.org>2005-10-13 14:58:57 +0000
commit35182740a9b22fcb144291823d0d222d79d36116 (patch)
tree73f59c3cbcc1b44f5610b098e95d9e94259de682 /sys
parentf057276ebbf760c0f72a5b8d911a73c13b2f2fe3 (diff)
Over the years, different UARTs have appeared in the market.
Unfortunately most vendors implement hidden bits/features and ships with buggy buffers. This is our first attempt to fix this. Test the fifo size by putting the fifo into loopback mode and reading back what we wrote. It seems to be very much accurate and has correctly identified several buggy UARTs. Commented out for now. Tested by several people with different hardware, many thanks. Idea from Theo, code by myself.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ic/com_subr.c65
1 files changed, 64 insertions, 1 deletions
diff --git a/sys/dev/ic/com_subr.c b/sys/dev/ic/com_subr.c
index a00a5e99780..40025dabfd8 100644
--- a/sys/dev/ic/com_subr.c
+++ b/sys/dev/ic/com_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: com_subr.c,v 1.2 2005/10/13 01:59:42 fgsch Exp $ */
+/* $OpenBSD: com_subr.c,v 1.3 2005/10/13 14:58:56 fgsch Exp $ */
/*
* Copyright (c) 1997 - 1999, Jason Downs. All rights reserved.
@@ -108,6 +108,7 @@ cdev_decl(com);
#endif
void com_enable_debugport(struct com_softc *);
+void com_fifo_probe(struct com_softc *);
#if defined(COM_CONSOLE) || defined(KGDB)
void
@@ -314,6 +315,10 @@ com_attach_subr(sc)
if (sc->sc_fifolen == 0)
sc->sc_fifolen = 1; /* default */
+#ifdef notyet
+ com_fifo_probe(sc);
+#endif
+
/* clear and disable fifo */
bus_space_write_1(iot, ioh, com_fifo, FIFO_RCV_RST | FIFO_XMT_RST);
(void)bus_space_read_1(iot, ioh, com_data);
@@ -376,3 +381,61 @@ com_attach_subr(sc)
com_enable_debugport(sc);
#endif
}
+
+void
+com_fifo_probe(struct com_softc *sc)
+{
+ bus_space_handle_t ioh = sc->sc_ioh;
+ bus_space_tag_t iot = sc->sc_iot;
+ u_int8_t fifo, ier;
+ int timo, len;
+
+ if (!ISSET(sc->sc_hwflags, COM_HW_FIFO))
+ return;
+
+ ier = 0;
+#ifdef COM_PXA2X0
+ if (sc->sc_uarttype == COM_UART_PXA2X0)
+ ier |= IER_EUART;
+#endif
+ bus_space_write_1(iot, ioh, com_ier, ier);
+ bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB);
+ bus_space_write_1(iot, ioh, com_dlbl, 3);
+ bus_space_write_1(iot, ioh, com_dlbh, 0);
+ bus_space_write_1(iot, ioh, com_lcr, LCR_PNONE | LCR_8BITS);
+ bus_space_write_1(iot, ioh, com_mcr, MCR_LOOPBACK);
+
+ fifo = FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST;
+ if (sc->sc_uarttype == COM_UART_TI16750)
+ fifo |= FIFO_ENABLE_64BYTE;
+
+ bus_space_write_1(iot, ioh, com_fifo, fifo);
+
+ for (len = 0; len < 256; len++) {
+ bus_space_write_1(iot, ioh, com_data, (len + 1));
+ timo = 2000;
+ while (!ISSET(bus_space_read_1(iot, ioh, com_lsr),
+ LSR_TXRDY) && --timo)
+ delay(1);
+ if (!timo)
+ break;
+ }
+
+ delay(100);
+
+ for (len = 0; len < 256; len++) {
+ timo = 2000;
+ while (!ISSET(bus_space_read_1(iot, ioh, com_lsr),
+ LSR_RXRDY) && --timo)
+ delay(1);
+ if (!timo || bus_space_read_1(iot, ioh, com_data) != (len + 1))
+ break;
+ }
+
+ /* For safety, always use the smaller value. */
+ if (sc->sc_fifolen > len) {
+ printf("%s: probed fifo depth: %d bytes\n",
+ sc->sc_dev.dv_xname, len);
+ sc->sc_fifolen = len;
+ }
+}