diff options
author | Jim Rees <rees@cvs.openbsd.org> | 1999-02-09 02:39:44 +0000 |
---|---|---|
committer | Jim Rees <rees@cvs.openbsd.org> | 1999-02-09 02:39:44 +0000 |
commit | fc07b0ec5a553f737121f7c95e73690b42cd19e3 (patch) | |
tree | cae5179b7f37422cfda186e3c422144e56c02d26 | |
parent | b45206b9b5c7445dab9dba61b43ec0177c17c2e7 (diff) |
Fix cua device to not block on open.
Turn off chip (and dtr) on interrupted open.
-rw-r--r-- | sys/dev/ic/com.c | 130 |
1 files changed, 66 insertions, 64 deletions
diff --git a/sys/dev/ic/com.c b/sys/dev/ic/com.c index fd785250950..e939597711f 100644 --- a/sys/dev/ic/com.c +++ b/sys/dev/ic/com.c @@ -1,4 +1,4 @@ -/* $OpenBSD: com.c,v 1.42 1999/01/11 05:12:16 millert Exp $ */ +/* $OpenBSD: com.c,v 1.43 1999/02/09 02:39:43 rees Exp $ */ /* $NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $ */ /*- @@ -88,6 +88,7 @@ static u_char tiocm_xxx2mcr __P((int)); int comprobe __P((struct device *, void *, void *)); void comattach __P((struct device *, struct device *, void *)); void comstart_pending __P((void *)); +void compwroff __P((struct com_softc *)); #if NCOM_ISA struct cfattach com_isa_ca = { @@ -776,35 +777,29 @@ comopen(dev, flag, mode, p) return EBUSY; } sc->sc_cua = 1; /* We go into CUA mode */ - } - - /* wait for carrier if necessary */ - if (ISSET(flag, O_NONBLOCK)) { - if (!DEVCUA(dev) && sc->sc_cua) { - /* Opening TTY non-blocking... but the CUA is busy */ - splx(s); - return EBUSY; - } } else { - while (sc->sc_cua || - (!ISSET(tp->t_cflag, CLOCAL) && - !ISSET(tp->t_state, TS_CARR_ON))) { - SET(tp->t_state, TS_WOPEN); - error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, - ttopen, 0); - if (!DEVCUA(dev) && sc->sc_cua && error == EINTR) - continue; - if (error) { - /* XXX should turn off chip if we're the - only waiter */ - if (DEVCUA(dev)) - sc->sc_cua = 0; - CLR(tp->t_state, TS_WOPEN); + /* tty (not cua) device; wait for carrier if necessary */ + if (ISSET(flag, O_NONBLOCK)) { + if (sc->sc_cua) { + /* Opening TTY non-blocking... but the CUA is busy */ splx(s); - return error; + return EBUSY; + } + } else { + while (sc->sc_cua || + (!ISSET(tp->t_cflag, CLOCAL) && + !ISSET(tp->t_state, TS_CARR_ON))) { + SET(tp->t_state, TS_WOPEN); + error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, + ttopen, 0); + if (error) { + CLR(tp->t_state, TS_WOPEN); + if (!sc->sc_cua && !ISSET(tp->t_state, TS_ISOPEN)) + compwroff(sc); + splx(s); + return error; + } } - if (!DEVCUA(dev) && sc->sc_cua) - continue; } } splx(s); @@ -821,8 +816,6 @@ comclose(dev, flag, mode, p) int unit = DEVUNIT(dev); struct com_softc *sc = com_cd.cd_devs[unit]; struct tty *tp = sc->sc_tty; - bus_space_tag_t iot = sc->sc_iot; - bus_space_handle_t ioh = sc->sc_ioh; int s; /* XXX This is for cons.c. */ @@ -831,40 +824,8 @@ comclose(dev, flag, mode, p) (*linesw[tp->t_line].l_close)(tp, flag); s = spltty(); - if (!ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) { - /* can't do any of this stuff .... */ - CLR(sc->sc_lcr, LCR_SBREAK); - bus_space_write_1(iot, ioh, com_lcr, 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)) { - /* 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; - } - } + if (!ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) + compwroff(sc); CLR(tp->t_state, TS_BUSY | TS_FLUSH); if (--comsopen == 0) untimeout(compoll, NULL); @@ -887,7 +848,48 @@ comclose(dev, flag, mode, p) #endif return 0; } - + +void +compwroff(sc) + struct com_softc *sc; +{ + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + struct tty *tp = sc->sc_tty; + + CLR(sc->sc_lcr, LCR_SBREAK); + bus_space_write_1(iot, ioh, com_lcr, 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)) { + /* 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; + } +} + int comread(dev, uio, flag) dev_t dev; |