diff options
author | Jason Downs <downsj@cvs.openbsd.org> | 1998-02-23 11:41:27 +0000 |
---|---|---|
committer | Jason Downs <downsj@cvs.openbsd.org> | 1998-02-23 11:41:27 +0000 |
commit | 8f22f18b619e47b00192eaa7ddd8903b146f13a0 (patch) | |
tree | e6416ac2c64294be74f8e357092bd0abeceeaf9d | |
parent | d8e6db8ceb3f3f5d88ce1c325f2413a387310813 (diff) |
New probe routine and support for ST16650.
Compiles, but completely untested.
-rw-r--r-- | sys/dev/ic/com.c | 229 | ||||
-rw-r--r-- | sys/dev/ic/comreg.h | 20 | ||||
-rw-r--r-- | sys/dev/ic/comvar.h | 13 | ||||
-rw-r--r-- | sys/dev/ic/ns16550reg.h | 3 |
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) */ |