summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Rees <rees@cvs.openbsd.org>1999-02-09 02:39:44 +0000
committerJim Rees <rees@cvs.openbsd.org>1999-02-09 02:39:44 +0000
commitfc07b0ec5a553f737121f7c95e73690b42cd19e3 (patch)
treecae5179b7f37422cfda186e3c422144e56c02d26
parentb45206b9b5c7445dab9dba61b43ec0177c17c2e7 (diff)
Fix cua device to not block on open.
Turn off chip (and dtr) on interrupted open.
-rw-r--r--sys/dev/ic/com.c130
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;