summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Downs <downsj@cvs.openbsd.org>1998-02-23 11:40:34 +0000
committerJason Downs <downsj@cvs.openbsd.org>1998-02-23 11:40:34 +0000
commitd8e6db8ceb3f3f5d88ce1c325f2413a387310813 (patch)
treeccdb969c5fa3fb8d678be5643faf497832769b83
parent5cb487dc627c4b7c83691dc3776933222dcfff65 (diff)
New probe routine, add support for ST16650 (works).
Tested with some 16450 and 16550 UARTs.
-rw-r--r--sys/arch/i386/isa/pccom.c216
-rw-r--r--sys/arch/i386/isa/pccomvar.h12
2 files changed, 197 insertions, 31 deletions
diff --git a/sys/arch/i386/isa/pccom.c b/sys/arch/i386/isa/pccom.c
index 16ca8bd7b61..29e93ad3976 100644
--- a/sys/arch/i386/isa/pccom.c
+++ b/sys/arch/i386/isa/pccom.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pccom.c,v 1.21 1998/02/22 21:35:31 niklas Exp $ */
+/* $OpenBSD: pccom.c,v 1.22 1998/02/23 11:40:32 downsj Exp $ */
/* $NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $ */
/*-
@@ -554,6 +554,7 @@ comattach(parent, self, aux)
int hayesp_ports[] = { 0x140, 0x180, 0x280, 0x300, 0 };
int *hayespp;
#endif
+ u_int8_t lcr;
/*
* XXX should be broken out into functions for isa attach and
@@ -645,22 +646,115 @@ comattach(parent, self, aux)
if (*hayespp == 0) {
#endif
- sc->sc_fifolen = 1;
- /* look for a NS 16550AF UART with FIFOs */
- bus_space_write_1(iot, ioh, com_fifo,
- FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14);
+ /*
+ * Probe for all known forms of UART.
+ */
+ lcr = bus_space_read_1(iot, ioh, com_lcr);
+
+ bus_space_write_1(iot, ioh, com_lcr, 0xbf);
+ bus_space_write_1(iot, ioh, com_efr, 0);
+ bus_space_write_1(iot, ioh, com_lcr, 0);
+
+ bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE);
delay(100);
- if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_FIFO_MASK) ==
- IIR_FIFO_MASK) {
- if (ISSET(bus_space_read_1(iot, ioh, com_fifo),
- FIFO_TRIGGER_14) == FIFO_TRIGGER_14) {
- SET(sc->sc_hwflags, COM_HW_FIFO);
- printf(": ns16550a, working fifo\n");
- sc->sc_fifolen = 16;
- } else
- printf(": ns16550, broken fifo\n");
- } else
- printf(": ns8250 or ns16450, no fifo\n");
+
+ switch(bus_space_read_1(iot, ioh, com_iir) >> 6) {
+ case 0:
+ sc->sc_uarttype = COM_UART_16450;
+ break;
+ case 2:
+ sc->sc_uarttype = COM_UART_16550;
+ break;
+ case 3:
+ sc->sc_uarttype = COM_UART_16550A;
+ break;
+ default:
+ sc->sc_uarttype = COM_UART_UNKNOWN;
+ break;
+ }
+
+ if (sc->sc_uarttype == COM_UART_16550A) { /* Probe for ST16650s */
+ bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB);
+ if (bus_space_read_1(iot, ioh, com_efr) == 0) {
+ sc->sc_uarttype = COM_UART_ST16650;
+ } else {
+ bus_space_write_1(iot, ioh, com_lcr, 0xbf);
+ if (bus_space_read_1(iot, ioh, com_efr) == 0)
+ sc->sc_uarttype = COM_UART_ST16650V2;
+ }
+ }
+
+#ifdef notyet
+ if (sc->sc_uarttype == COM_UART_16550A) { /* Probe for TI16750s */
+ bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB);
+ bus_space_write_1(iot, ioh, com_fifo,
+ FIFO_ENABLE | FIFO_ENABLE_64BYTE);
+ if ((bus_space_read_1(iot, ioh, com_iir) >> 5) == 7) {
+ bus_space_write_1(iot, ioh, com_lcr, 0);
+ if ((bus_space_read_1(iot, ioh, com_iir) >> 5) == 6)
+ sc->sc_uarttype = COM_UART_TI16750;
+ }
+ bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE);
+ }
+#endif
+
+ bus_space_write_1(iot, ioh, com_lcr, lcr);
+ if (sc->sc_uarttype == COM_UART_16450) { /* Probe for 8250 */
+ u_int8_t scr0, scr1, scr2;
+
+ scr0 = bus_space_read_1(iot, ioh, com_scratch);
+ bus_space_write_1(iot, ioh, com_scratch, 0xa5);
+ scr1 = bus_space_read_1(iot, ioh, com_scratch);
+ bus_space_write_1(iot, ioh, com_scratch, 0x5a);
+ scr2 = bus_space_read_1(iot, ioh, com_scratch);
+ bus_space_write_1(iot, ioh, com_scratch, scr0);
+
+ if ((scr1 != 0xa5) || (scr2 != 0x5a))
+ sc->sc_uarttype = COM_UART_8250;
+ }
+
+ /*
+ * Print UART type and initialize ourself.
+ */
+ sc->sc_fifolen = 1; /* default */
+ switch (sc->sc_uarttype) {
+ case COM_UART_UNKNOWN:
+ printf(": unknown uart\n");
+ break;
+ case COM_UART_8250:
+ printf(": ns8250, no fifo\n");
+ break;
+ case COM_UART_16450:
+ printf(": ns16450, no fifo\n");
+ break;
+ case COM_UART_16550:
+ printf(": ns16550, no working fifo\n");
+ break;
+ case COM_UART_16550A:
+ printf(": ns16550a, 16 byte fifo\n");
+ SET(sc->sc_hwflags, COM_HW_FIFO);
+ sc->sc_fifolen = 16;
+ break;
+ case COM_UART_ST16650:
+ printf(": st16650, no working fifo\n");
+ break;
+ case COM_UART_ST16650V2:
+ printf(": st16650, 32 byte fifo\n");
+ SET(sc->sc_hwflags, COM_HW_FIFO);
+ sc->sc_fifolen = 32;
+ break;
+ case COM_UART_TI16750:
+ printf(": ti16750, 64 byte fifo\n");
+ SET(sc->sc_hwflags, COM_HW_FIFO);
+ sc->sc_fifolen = 64;
+ break;
+ default:
+ panic("comattach: bad fifo type\n");
+ }
+
+ /* 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);
bus_space_write_1(iot, ioh, com_fifo, 0);
#ifdef COM_HAYESP
}
@@ -768,6 +862,24 @@ comopen(dev, flag, mode, p)
iot = sc->sc_iot;
ioh = sc->sc_ioh;
+
+ /*
+ * Wake up the sleepy heads.
+ */
+ switch (sc->sc_uarttype) {
+ case COM_UART_ST16650:
+ case COM_UART_ST16650V2:
+ bus_space_write_1(iot, ioh, com_lcr, 0xbf);
+ bus_space_write_1(iot, ioh, com_efr, EFR_ECB);
+ bus_space_write_1(iot, ioh, com_ier, 0);
+ bus_space_write_1(iot, ioh, com_efr, 0);
+ bus_space_write_1(iot, ioh, com_lcr, 0);
+ break;
+ case COM_UART_TI16750:
+ bus_space_write_1(iot, ioh, com_ier, 0);
+ break;
+ }
+
#ifdef COM_HAYESP
/* Setup the ESP board */
if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
@@ -801,6 +913,20 @@ comopen(dev, flag, mode, p)
} else
#endif
if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
+ u_int8_t fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST;
+ u_int8_t lcr;
+
+ if (tp->t_ispeed <= 1200)
+ fifo |= FIFO_TRIGGER_1;
+ else
+ fifo |= FIFO_TRIGGER_8;
+ if (sc->sc_uarttype == COM_UART_TI16750) {
+ fifo |= FIFO_ENABLE_64BYTE;
+ lcr = bus_space_read_1(iot, ioh, com_lcr);
+ bus_space_write_1(iot, ioh, com_lcr,
+ lcr | LCR_DLAB);
+ }
+
/*
* (Re)enable and drain FIFOs.
*
@@ -816,15 +942,15 @@ comopen(dev, flag, mode, p)
bus_space_write_1(iot, ioh, com_fifo, 0);
delay(100);
(void) bus_space_read_1(iot, ioh, com_data);
- bus_space_write_1(iot, ioh, com_fifo,
- FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST |
- (tp->t_ispeed <= 1200 ?
- FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
+ bus_space_write_1(iot, ioh, com_fifo, fifo |
+ FIFO_RCV_RST | FIFO_XMT_RST);
delay(100);
if(!ISSET(bus_space_read_1(iot, ioh,
com_lsr), LSR_RXRDY))
break;
}
+ if (sc->sc_uarttype == COM_UART_TI16750)
+ bus_space_write_1(iot, ioh, com_lcr, lcr);
}
/* flush any pending I/O */
@@ -921,12 +1047,31 @@ comclose(dev, flag, mode, p)
/* XXX perhaps only clear DTR */
bus_space_write_1(iot, ioh, com_mcr, 0);
}
+
+ /*
+ * Turn FIFO off; enter sleep mode if possible.
+ */
+ bus_space_write_1(iot, ioh, com_fifo, 0);
+ delay(100);
+ (void) bus_space_read_1(iot, ioh, com_data);
+ delay(100);
+ bus_space_write_1(iot, ioh, com_fifo,
+ FIFO_RCV_RST | FIFO_XMT_RST);
+
+ switch (sc->sc_uarttype) {
+ case COM_UART_ST16650:
+ case COM_UART_ST16650V2:
+ bus_space_write_1(iot, ioh, com_lcr, 0xbf);
+ bus_space_write_1(iot, ioh, com_efr, EFR_ECB);
+ bus_space_write_1(iot, ioh, com_ier, IER_SLEEP);
+ bus_space_write_1(iot, ioh, com_lcr, 0);
+ break;
+ case COM_UART_TI16750:
+ bus_space_write_1(iot, ioh, com_ier, IER_SLEEP);
+ break;
+ }
}
CLR(tp->t_state, TS_BUSY | TS_FLUSH);
-/*
- * FIFO off
- */
- bus_space_write_1(iot, ioh, com_fifo, 0);
sc->sc_cua = 0;
splx(s);
ttyclose(tp);
@@ -1200,7 +1345,7 @@ comparam(tp, t)
* Make sure the transmit FIFO is empty before
* proceeding. If we don't do this, some revisions
* of the UART will hang. Interestingly enough,
- * even if we do this will the last character is
+ * even if we do this while the last character is
* still being pushed out, they don't hang. This
* seems good enough.
*/
@@ -1228,10 +1373,19 @@ comparam(tp, t)
bus_space_write_1(iot, ioh, com_lcr, lcr);
if (!ISSET(sc->sc_hwflags, COM_HW_HAYESP) &&
- ISSET(sc->sc_hwflags, COM_HW_FIFO))
- bus_space_write_1(iot, ioh, com_fifo,
- FIFO_ENABLE |
- (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
+ ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
+ if (sc->sc_uarttype == COM_UART_TI16750) {
+ bus_space_write_1(iot, ioh, com_lcr,
+ lcr | LCR_DLAB);
+ bus_space_write_1(iot, ioh, com_fifo,
+ FIFO_ENABLE | FIFO_ENABLE_64BYTE |
+ (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
+ bus_space_write_1(iot, ioh, com_lcr, lcr);
+ } else
+ bus_space_write_1(iot, ioh, com_fifo,
+ FIFO_ENABLE |
+ (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
+ }
} else
bus_space_write_1(iot, ioh, com_lcr, lcr);
@@ -1332,7 +1486,6 @@ comhwiflow(tp, block)
return 1;
}
-
void
comstart(tp)
struct tty *tp;
@@ -1552,6 +1705,9 @@ comintr(arg)
u_char lsr;
u_int rxput;
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT) || !sc->sc_tty)
+ return (0); /* can't do squat. */
+
if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND))
return (0);
diff --git a/sys/arch/i386/isa/pccomvar.h b/sys/arch/i386/isa/pccomvar.h
index 1be68aa70ac..62770b329cc 100644
--- a/sys/arch/i386/isa/pccomvar.h
+++ b/sys/arch/i386/isa/pccomvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pccomvar.h,v 1.4 1997/07/07 17:08:05 niklas Exp $ */
+/* $OpenBSD: pccomvar.h,v 1.5 1998/02/23 11:40:33 downsj Exp $ */
/* $NetBSD: comvar.h,v 1.5 1996/05/05 19:50:47 christos Exp $ */
/*
@@ -62,6 +62,16 @@ struct com_softc {
bus_space_handle_t sc_hayespioh;
isa_chipset_tag_t sc_ic;
+ u_char sc_uarttype;
+#define COM_UART_UNKNOWN 0x00 /* unknown */
+#define COM_UART_8250 0x01 /* no fifo */
+#define COM_UART_16450 0x02 /* no fifo */
+#define COM_UART_16550 0x03 /* no working fifo */
+#define COM_UART_16550A 0x04 /* 16 byte fifo */
+#define COM_UART_ST16650 0x05 /* no working fifo */
+#define COM_UART_ST16650V2 0x06 /* 32 byte fifo */
+#define COM_UART_TI16750 0x07 /* 64 byte fifo */
+
u_char sc_hwflags;
#define COM_HW_NOIEN 0x01
#define COM_HW_FIFO 0x02