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 /sys/dev/ic/com.c | |
parent | d8e6db8ceb3f3f5d88ce1c325f2413a387310813 (diff) |
New probe routine and support for ST16650.
Compiles, but completely untested.
Diffstat (limited to 'sys/dev/ic/com.c')
-rw-r--r-- | sys/dev/ic/com.c | 229 |
1 files changed, 192 insertions, 37 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; |