Index: com.c =================================================================== RCS file: /cvs/src/sys/dev/ic/com.c,v retrieving revision 1.158 diff -u -p -r1.158 com.c --- com.c 14 Sep 2014 14:17:24 -0000 1.158 +++ com.c 6 Jan 2016 01:43:22 -0000 @@ -79,6 +79,7 @@ #endif #include +#include #if !defined(__sparc__) || defined(__sparc64__) #include #endif @@ -146,6 +147,67 @@ void com_kgdb_putc(void *, int); #define DEVUNIT(x) (minor(x) & 0x7f) #define DEVCUA(x) (minor(x) & 0x80) +void +comsetlcr(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t lcr) +{ + bus_space_write_1(iot, ioh, com_lcr, lcr); + + { + int i; + for (i = 0; i < 100000; i++) { + if (lcr == bus_space_read_1(iot, ioh, com_lcr)) break; + } + if (i) printf("comsetlcr: failed to set lcr %d\n", i); + } +} + +void +comsetdlb(bus_space_tag_t iot, bus_space_handle_t ioh, int speed) +{ + u_int8_t dlbl = speed; + u_int8_t dlbh = speed >> 8; + + bus_space_write_1(iot, ioh, com_dlbl, dlbl); + bus_space_write_1(iot, ioh, com_dlbh, dlbh); +#if 0 // this code works as a slightly delay? if enabled, the problem goes away. + { + int i; + for (i = 0; i < 100000; i++) { + if (dlbl == bus_space_read_1(iot, ioh, com_dlbl) && + dlbh == bus_space_read_1(iot, ioh, com_dlbh)) break; + } + if (i) printf("comsetdlb: failed to set dlb %d\n", i); + + } +#endif +} + +void +disp_reg(char *identifier, bus_space_tag_t iot, bus_space_handle_t ioh) +{ + int i; + unsigned char reg[16]; + unsigned char lcr; + + disable_intr(); + + lcr = bus_space_read_1(iot, ioh, com_lcr); + + comsetlcr(iot, ioh, lcr | LCR_DLAB); + for (i = 0; i < 8; i++) reg[i + 8] = bus_space_read_1(iot, ioh, i); + + comsetlcr(iot, ioh, lcr); + for (i = 1; i < 8; i++) reg[i] = bus_space_read_1(iot, ioh, i); + + reg[0] = 0xff; + + enable_intr(); + + printf("%s: ", identifier); + for (i = 0; i < 16; i++) printf("%02x ", reg[i]); + printf("\n"); +} + int comspeed(long freq, long speed) { @@ -177,7 +239,7 @@ comprobe1(bus_space_tag_t iot, bus_space int i, k; /* force access to id reg */ - bus_space_write_1(iot, ioh, com_lcr, 0); + comsetlcr(iot, ioh, 0); bus_space_write_1(iot, ioh, com_iir, 0); for (i = 0; i < 32; i++) { k = bus_space_read_1(iot, ioh, com_iir); @@ -342,11 +404,11 @@ comopen(dev_t dev, int flag, int mode, s switch (sc->sc_uarttype) { case COM_UART_ST16650: case COM_UART_ST16650V2: - bus_space_write_1(iot, ioh, com_lcr, LCR_EFR); + comsetlcr(iot, ioh, LCR_EFR); 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); + comsetlcr(iot, ioh, 0); break; case COM_UART_TI16750: bus_space_write_1(iot, ioh, com_ier, 0); @@ -370,8 +432,7 @@ comopen(dev_t dev, int flag, int mode, s 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); + comsetlcr(iot, ioh, lcr | LCR_DLAB); } /* @@ -397,7 +458,7 @@ comopen(dev_t dev, int flag, int mode, s break; } if (sc->sc_uarttype == COM_UART_TI16750) - bus_space_write_1(iot, ioh, com_lcr, lcr); + comsetlcr(iot, ioh, lcr); } /* Flush any pending I/O. */ @@ -431,6 +492,7 @@ comopen(dev_t dev, int flag, int mode, s #endif } #endif +disp_reg("comopen", iot, ioh); } else if (ISSET(tp->t_state, TS_XCLUDE) && suser(p, 0) != 0) return EBUSY; else @@ -531,7 +593,7 @@ compwroff(struct com_softc *sc) struct tty *tp = sc->sc_tty; CLR(sc->sc_lcr, LCR_SBREAK); - bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr); + comsetlcr(iot, ioh, sc->sc_lcr); bus_space_write_1(iot, ioh, com_ier, 0); if (ISSET(tp->t_cflag, HUPCL) && !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) { @@ -555,10 +617,10 @@ compwroff(struct com_softc *sc) switch (sc->sc_uarttype) { case COM_UART_ST16650: case COM_UART_ST16650V2: - bus_space_write_1(iot, ioh, com_lcr, LCR_EFR); + comsetlcr(iot, ioh, LCR_EFR); 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); + comsetlcr(iot, ioh, 0); break; case COM_UART_TI16750: bus_space_write_1(iot, ioh, com_ier, IER_SLEEP); @@ -599,11 +661,11 @@ com_resume(struct com_softc *sc) switch (sc->sc_uarttype) { case COM_UART_ST16650: case COM_UART_ST16650V2: - bus_space_write_1(iot, ioh, com_lcr, LCR_EFR); + comsetlcr(iot, ioh, LCR_EFR); 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); + comsetlcr(iot, ioh, 0); break; case COM_UART_TI16750: bus_space_write_1(iot, ioh, com_ier, 0); @@ -617,12 +679,11 @@ com_resume(struct com_softc *sc) ospeed = comspeed(sc->sc_frequency, tp->t_ospeed); if (ospeed != 0) { - bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr | LCR_DLAB); - bus_space_write_1(iot, ioh, com_dlbl, ospeed); - bus_space_write_1(iot, ioh, com_dlbh, ospeed >> 8); - bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr); + comsetlcr(iot, ioh, sc->sc_lcr | LCR_DLAB); + comsetdlb(iot, ioh, ospeed); + comsetlcr(iot, ioh, sc->sc_lcr); } else { - bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr); + comsetlcr(iot, ioh, sc->sc_lcr); } if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { @@ -638,8 +699,7 @@ com_resume(struct com_softc *sc) 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); + comsetlcr(iot, ioh, lcr | LCR_DLAB); } /* @@ -665,7 +725,7 @@ com_resume(struct com_softc *sc) break; } if (sc->sc_uarttype == COM_UART_TI16750) - bus_space_write_1(iot, ioh, com_lcr, lcr); + comsetlcr(iot, ioh, lcr); } /* You turn me on, baby! */ @@ -681,6 +741,7 @@ com_resume(struct com_softc *sc) #endif } #endif +disp_reg("com_resume", iot, ioh); } void @@ -751,11 +812,11 @@ comioctl(dev_t dev, u_long cmd, caddr_t switch (cmd) { case TIOCSBRK: SET(sc->sc_lcr, LCR_SBREAK); - bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr); + comsetlcr(iot, ioh, sc->sc_lcr); break; case TIOCCBRK: CLR(sc->sc_lcr, LCR_SBREAK); - bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr); + comsetlcr(iot, ioh, sc->sc_lcr); break; case TIOCSDTR: SET(sc->sc_mcr, sc->sc_dtr); @@ -921,30 +982,28 @@ comparam(struct tty *tp, struct termios } } - bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB); - bus_space_write_1(iot, ioh, com_dlbl, ospeed); - bus_space_write_1(iot, ioh, com_dlbh, ospeed >> 8); - bus_space_write_1(iot, ioh, com_lcr, lcr); + comsetlcr(iot, ioh, lcr | LCR_DLAB); + comsetdlb(iot, ioh, ospeed); + comsetlcr(iot, ioh, lcr); SET(sc->sc_mcr, MCR_DTR); bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); } else - bus_space_write_1(iot, ioh, com_lcr, lcr); + comsetlcr(iot, ioh, lcr); if (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); + comsetlcr(iot, ioh, 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); + comsetlcr(iot, ioh, 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); + comsetlcr(iot, ioh, lcr); /* When not using CRTSCTS, RTS follows DTR. */ if (!ISSET(t->c_cflag, CRTSCTS)) { @@ -981,6 +1040,7 @@ comparam(struct tty *tp, struct termios bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); } +disp_reg("comparam", iot, ioh); /* Just to be sure... */ comstart(tp); return 0; @@ -1387,11 +1447,10 @@ cominit(bus_space_tag_t iot, bus_space_h int s = splhigh(); u_char stat; - bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB); + comsetlcr(iot, ioh, LCR_DLAB); rate = comspeed(frequency, rate); /* XXX not comdefaultrate? */ - bus_space_write_1(iot, ioh, com_dlbl, rate); - bus_space_write_1(iot, ioh, com_dlbh, rate >> 8); - bus_space_write_1(iot, ioh, com_lcr, LCR_8BITS); + comsetdlb(iot, ioh, rate); + comsetlcr(iot, ioh, LCR_8BITS); bus_space_write_1(iot, ioh, com_mcr, MCR_DTR | MCR_RTS); #ifdef COM_PXA2X0 /* XXX */ @@ -1403,6 +1462,7 @@ cominit(bus_space_tag_t iot, bus_space_h FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1); stat = bus_space_read_1(iot, ioh, com_iir); splx(s); +disp_reg("cominit", iot, ioh); } #ifdef COM_CONSOLE @@ -1606,9 +1666,9 @@ com_attach_subr(struct com_softc *sc) * Probe for all known forms of UART. */ lcr = bus_space_read_1(iot, ioh, com_lcr); - bus_space_write_1(iot, ioh, com_lcr, LCR_EFR); + comsetlcr(iot, ioh, LCR_EFR); bus_space_write_1(iot, ioh, com_efr, 0); - bus_space_write_1(iot, ioh, com_lcr, 0); + comsetlcr(iot, ioh, 0); bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE); delay(100); @@ -1633,14 +1693,14 @@ com_attach_subr(struct com_softc *sc) } if (sc->sc_uarttype == COM_UART_16550A) { /* Probe for ST16650s */ - bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB); + comsetlcr(iot, ioh, lcr | LCR_DLAB); if (bus_space_read_1(iot, ioh, com_efr) == 0) { bus_space_write_1(iot, ioh, com_efr, EFR_CTS); if (bus_space_read_1(iot, ioh, com_efr) != 0) sc->sc_uarttype = COM_UART_ST16650; bus_space_write_1(iot, ioh, com_efr, 0); } else { - bus_space_write_1(iot, ioh, com_lcr, LCR_EFR); + comsetlcr(iot, ioh, LCR_EFR); if (bus_space_read_1(iot, ioh, com_efr) == 0) sc->sc_uarttype = COM_UART_ST16650V2; } @@ -1651,13 +1711,12 @@ com_attach_subr(struct com_softc *sc) u_int8_t dlbl, dlbh; /* Enable latch access and get the current values. */ - bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB); + comsetlcr(iot, ioh, lcr | LCR_DLAB); dlbl = bus_space_read_1(iot, ioh, com_dlbl); dlbh = bus_space_read_1(iot, ioh, com_dlbh); /* Zero out the latch divisors */ - bus_space_write_1(iot, ioh, com_dlbl, 0); - bus_space_write_1(iot, ioh, com_dlbh, 0); + comsetdlb(iot, ioh, 0); if (bus_space_read_1(iot, ioh, com_dlbh) == 0x10) { sc->sc_uarttype = COM_UART_XR16850; @@ -1665,18 +1724,17 @@ com_attach_subr(struct com_softc *sc) } /* Reset to original. */ - bus_space_write_1(iot, ioh, com_dlbl, dlbl); - bus_space_write_1(iot, ioh, com_dlbh, dlbh); + comsetdlb(iot, ioh, (dlbh << 8) | dlbl); } #endif if (sc->sc_uarttype == COM_UART_16550A) { /* Probe for TI16750s */ - bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB); + comsetlcr(iot, ioh, 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) { #if 0 - bus_space_write_1(iot, ioh, com_lcr, 0); + comsetlcr(iot, ioh, 0); if ((bus_space_read_1(iot, ioh, com_iir) >> 5) == 6) #endif sc->sc_uarttype = COM_UART_TI16750; @@ -1685,7 +1743,7 @@ com_attach_subr(struct com_softc *sc) } /* Reset the LCR (latch access is probably enabled). */ - bus_space_write_1(iot, ioh, com_lcr, lcr); + comsetlcr(iot, ioh, lcr); if (sc->sc_uarttype == COM_UART_16450) { /* Probe for 8250 */ u_int8_t scr0, scr1, scr2; @@ -1856,10 +1914,9 @@ com_fifo_probe(struct com_softc *sc) 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); + comsetlcr(iot, ioh, LCR_DLAB); + comsetdlb(iot, ioh, 3); + comsetlcr(iot, ioh, LCR_PNONE | LCR_8BITS); bus_space_write_1(iot, ioh, com_mcr, MCR_LOOPBACK); fifo = FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST;