summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Downs <downsj@cvs.openbsd.org>1998-02-23 11:41:27 +0000
committerJason Downs <downsj@cvs.openbsd.org>1998-02-23 11:41:27 +0000
commit8f22f18b619e47b00192eaa7ddd8903b146f13a0 (patch)
treee6416ac2c64294be74f8e357092bd0abeceeaf9d
parentd8e6db8ceb3f3f5d88ce1c325f2413a387310813 (diff)
New probe routine and support for ST16650.
Compiles, but completely untested.
-rw-r--r--sys/dev/ic/com.c229
-rw-r--r--sys/dev/ic/comreg.h20
-rw-r--r--sys/dev/ic/comvar.h13
-rw-r--r--sys/dev/ic/ns16550reg.h3
4 files changed, 225 insertions, 40 deletions
diff --git a/sys/dev/ic/com.c b/sys/dev/ic/com.c
index 65846062d83..5b614174dad 100644
--- a/sys/dev/ic/com.c
+++ b/sys/dev/ic/com.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: com.c,v 1.37 1998/02/05 16:49:24 deraadt Exp $ */
+/* $OpenBSD: com.c,v 1.38 1998/02/23 11:41:24 downsj Exp $ */
/* $NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $ */
/*-
@@ -349,6 +349,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
@@ -426,6 +427,7 @@ comattach(parent, self, aux)
if (comprobeHAYESP(hayespioh, sc)) {
sc->sc_hayespbase = *hayespp;
sc->sc_hayespioh = hayespioh;
+ sc->sc_fifolen = 1024;
break;
}
bus_space_unmap(iot, hayespioh, HAYESP_NPORTS);
@@ -434,20 +436,115 @@ comattach(parent, self, aux)
if (*hayespp == 0) {
#endif
- /* 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");
- } 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
}
@@ -559,6 +656,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)) {
@@ -592,6 +707,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.
*
@@ -607,15 +736,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 */
@@ -712,6 +841,29 @@ 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);
if (--comsopen == 0)
@@ -993,7 +1145,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.
*/
@@ -1021,10 +1173,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);
@@ -1103,8 +1264,7 @@ comstart(tp)
}
if (ISSET(tp->t_state, TS_BUSY))
goto out;
- if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) ||
- sc->sc_halt > 0)
+ if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) || sc->sc_halt > 0)
goto stopped;
if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS))
goto stopped;
@@ -1123,19 +1283,14 @@ comstart(tp)
SET(sc->sc_ier, IER_ETXRDY);
bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
}
+ if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
#ifdef COM_HAYESP
- if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
- u_char buffer[1024], *cp = buffer;
- int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
- do
- bus_space_write_1(iot, ioh, com_data, *cp++);
- while (--n);
- }
- else
+ u_char buffer[1024]; /* XXX: largest fifo */
+#else
+ u_char buffer[64]; /* XXX: largest fifo */
#endif
- if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
- u_char buffer[16], *cp = buffer;
- int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
+ u_char *cp = buffer;
+ int n = q_to_b(&tp->t_outq, cp, sc->sc_fifolen);
do {
bus_space_write_1(iot, ioh, com_data, *cp++);
} while (--n);
@@ -1293,7 +1448,7 @@ comintr(arg)
#endif
if (ISSET(sc->sc_hwflags, COM_HW_ABSENT) || !sc->sc_tty)
- return 0; /* can't do squat. */
+ return (0); /* can't do squat. */
#ifdef COM_DEBUG
n = 0;
diff --git a/sys/dev/ic/comreg.h b/sys/dev/ic/comreg.h
index fdbd1db4fc5..8fe9408d350 100644
--- a/sys/dev/ic/comreg.h
+++ b/sys/dev/ic/comreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: comreg.h,v 1.7 1997/10/15 14:04:18 pefo Exp $ */
+/* $OpenBSD: comreg.h,v 1.8 1998/02/23 11:41:25 downsj Exp $ */
/* $NetBSD: comreg.h,v 1.8 1996/02/05 23:01:50 scottr Exp $ */
/*-
@@ -48,6 +48,7 @@
#define IER_ETXRDY 0x2 /* Enable transmitter empty interrupt */
#define IER_ERLS 0x4 /* Enable line status interrupt */
#define IER_EMSC 0x8 /* Enable modem status interrupt */
+#define IER_SLEEP 0x10 /* Enable sleep mode */
/* interrupt identification register */
#define IIR_IMASK 0xf
@@ -68,6 +69,17 @@
#define FIFO_TRIGGER_4 0x40 /* ibid 4 */
#define FIFO_TRIGGER_8 0x80 /* ibid 8 */
#define FIFO_TRIGGER_14 0xc0 /* ibid 14 */
+/* ST16650 fifo control register */
+#define FIFO_RCV_TRIGGER_8 0x00
+#define FIFO_RCV_TRIGGER_16 0x40
+#define FIFO_RCV_TRIGGER_24 0x80
+#define FIFO_RCV_TRIGGER_28 0xc0
+#define FIFO_XMT_TRIGGER_16 0x00
+#define FIFO_XMT_TRIGGER_8 0x10
+#define FIFO_XMT_TRIGGER_24 0x20
+#define FIFO_XMT_TRIGGER_30 0x30
+/* TI16750 fifo control register */
+#define FIFO_ENABLE_64BYTE 0x20
/* line control register */
#define LCR_DLAB 0x80 /* Divisor latch access enable */
@@ -113,6 +125,12 @@
#define MSR_DDSR 0x02 /* DSR has changed state */
#define MSR_DCTS 0x01 /* CTS has changed state */
+/* enhanced features register */
+#define EFR_ECB 0x10 /* enhanced control bit */
+#define EFR_SCD 0x20 /* special character detect */
+#define EFR_RTS 0x40 /* RTS flow control */
+#define EFR_CTS 0x80 /* CTS flow control */
+
#define COM_NPORTS 8
/*
diff --git a/sys/dev/ic/comvar.h b/sys/dev/ic/comvar.h
index 153a70a8b53..3ea011a6541 100644
--- a/sys/dev/ic/comvar.h
+++ b/sys/dev/ic/comvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: comvar.h,v 1.9 1997/07/07 16:37:12 niklas Exp $ */
+/* $OpenBSD: comvar.h,v 1.10 1998/02/23 11:41:26 downsj Exp $ */
/* $NetBSD: comvar.h,v 1.5 1996/05/05 19:50:47 christos Exp $ */
/*
@@ -64,6 +64,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
@@ -78,6 +88,7 @@ struct com_softc {
#define COM_SW_CRTSCTS 0x04
#define COM_SW_MDMBUF 0x08
#define COM_SW_PPS 0x10
+ int sc_fifolen;
u_char sc_msr, sc_mcr, sc_lcr, sc_ier;
u_char sc_dtr;
diff --git a/sys/dev/ic/ns16550reg.h b/sys/dev/ic/ns16550reg.h
index f0e4831e1c1..82e46094f01 100644
--- a/sys/dev/ic/ns16550reg.h
+++ b/sys/dev/ic/ns16550reg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ns16550reg.h,v 1.2 1996/10/31 01:01:36 niklas Exp $ */
+/* $OpenBSD: ns16550reg.h,v 1.3 1998/02/23 11:41:26 downsj Exp $ */
/* $NetBSD: ns16550reg.h,v 1.4 1994/10/27 04:18:43 cgd Exp $ */
/*-
@@ -46,6 +46,7 @@
#define com_ier 1 /* interrupt enable (W) */
#define com_iir 2 /* interrupt identification (R) */
#define com_fifo 2 /* FIFO control (W) */
+#define com_efr 2 /* extended features register (W) */
#define com_lctl 3 /* line control register (R/W) */
#define com_cfcr 3 /* line control register (R/W) */
#define com_mcr 4 /* modem control register (R/W) */