diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ic/com.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/sys/dev/ic/com.c b/sys/dev/ic/com.c index e939597711f..7e492df0a98 100644 --- a/sys/dev/ic/com.c +++ b/sys/dev/ic/com.c @@ -1,4 +1,4 @@ -/* $OpenBSD: com.c,v 1.43 1999/02/09 02:39:43 rees Exp $ */ +/* $OpenBSD: com.c,v 1.44 1999/06/25 17:59:23 rees Exp $ */ /* $NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $ */ /*- @@ -89,6 +89,7 @@ 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 *)); +void com_raisedtr __P((void *)); #if NCOM_ISA struct cfattach com_isa_ca = { @@ -790,9 +791,13 @@ comopen(dev, flag, mode, p) (!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) { + error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen, 0); + /* + * If TS_WOPEN has been reset, that means the cua device + * has been closed. We don't want to fail in that case, + * so just go around again. + */ + if (error && ISSET(tp->t_state, TS_WOPEN)) { CLR(tp->t_state, TS_WOPEN); if (!sc->sc_cua && !ISSET(tp->t_state, TS_ISOPEN)) compwroff(sc); @@ -815,6 +820,8 @@ comclose(dev, flag, mode, p) { int unit = DEVUNIT(dev); struct com_softc *sc = com_cd.cd_devs[unit]; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; struct tty *tp = sc->sc_tty; int s; @@ -824,8 +831,17 @@ 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)) - compwroff(sc); + if (!ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) { + if (ISSET(tp->t_state, TS_WOPEN)) { + /* tty device is waiting for carrier; drop dtr then re-raise */ + CLR(sc->sc_mcr, MCR_DTR | MCR_RTS); + bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); + timeout(com_raisedtr, sc, hz * 2); + } else { + /* no one else waiting; turn off the uart */ + compwroff(sc); + } + } CLR(tp->t_state, TS_BUSY | TS_FLUSH); if (--comsopen == 0) untimeout(compoll, NULL); @@ -863,7 +879,8 @@ compwroff(sc) 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); + sc->sc_mcr = 0; + bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); } /* @@ -890,6 +907,16 @@ compwroff(sc) } } +void +com_raisedtr(arg) + void *arg; +{ + struct com_softc *sc = arg; + + SET(sc->sc_mcr, MCR_DTR | MCR_RTS); + bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_mcr, sc->sc_mcr); +} + int comread(dev, uio, flag) dev_t dev; |