summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authormarc <marc@NetBSD.org>1998-02-01 23:33:01 +0000
committermarc <marc@NetBSD.org>1998-02-01 23:33:01 +0000
commit1d4b77e754799446c627e32905f11f808df36ee1 (patch)
treeedc836415b45ded259adafe15fb73a1a926fcf06 /sys/dev/ic
parenta71698f1083d992bff086f6d78365c9c7b344203 (diff)
split com_attach_subr into attach stuff and per-open initialization stuff
add timeouts to all splserial() while loops so bugs elsewhere don't cause the com driver to wedge the machine add power management support
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/com.c167
1 files changed, 135 insertions, 32 deletions
diff --git a/sys/dev/ic/com.c b/sys/dev/ic/com.c
index 00e1a61e234..ec461dbdd98 100644
--- a/sys/dev/ic/com.c
+++ b/sys/dev/ic/com.c
@@ -1,4 +1,4 @@
-/* $NetBSD: com.c,v 1.130 1998/01/12 09:23:19 thorpej Exp $ */
+/* $NetBSD: com.c,v 1.131 1998/02/01 23:33:01 marc Exp $ */
/*-
* Copyright (c) 1993, 1994, 1995, 1996, 1997
@@ -117,6 +117,7 @@ int comprobeHAYESP __P((bus_space_handle_t hayespioh, struct com_softc *sc));
static void com_enable_debugport __P((struct com_softc *));
#endif
void com_attach_subr __P((struct com_softc *sc));
+void com_config __P((struct com_softc *));
int comspeed __P((long, long));
static u_char cflag2lcr __P((tcflag_t));
int comparam __P((struct tty *, struct termios *));
@@ -370,7 +371,7 @@ com_attach_subr(sc)
/* Disable interrupts before configuring the device. */
sc->sc_ier = 0;
- bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier);
+ bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
if (iot == comconstag && iobase == comconsaddr) {
comconsattached = 1;
@@ -393,34 +394,12 @@ com_attach_subr(sc)
sc->sc_hayespioh = hayespioh;
sc->sc_fifolen = 1024;
- /* Set 16550 compatibility mode */
- bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_SETMODE);
- bus_space_write_1(iot, hayespioh, HAYESP_CMD2,
- HAYESP_MODE_FIFO|HAYESP_MODE_RTS|
- HAYESP_MODE_SCALE);
-
- /* Set RTS/CTS flow control */
- bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_SETFLOWTYPE);
- bus_space_write_1(iot, hayespioh, HAYESP_CMD2, HAYESP_FLOW_RTS);
- bus_space_write_1(iot, hayespioh, HAYESP_CMD2, HAYESP_FLOW_CTS);
-
- /* Set flow control levels */
- bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_SETRXFLOW);
- bus_space_write_1(iot, hayespioh, HAYESP_CMD2,
- HAYESP_HIBYTE(HAYESP_RXHIWMARK));
- bus_space_write_1(iot, hayespioh, HAYESP_CMD2,
- HAYESP_LOBYTE(HAYESP_RXHIWMARK));
- bus_space_write_1(iot, hayespioh, HAYESP_CMD2,
- HAYESP_HIBYTE(HAYESP_RXLOWMARK));
- bus_space_write_1(iot, hayespioh, HAYESP_CMD2,
- HAYESP_LOBYTE(HAYESP_RXLOWMARK));
-
break;
}
bus_space_unmap(iot, hayespioh, HAYESP_NPORTS);
}
/* No ESP; look for other things. */
- if (*hayespp == 0) {
+ if (!ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
#endif
sc->sc_fifolen = 1;
/* look for a NS 16550AF UART with FIFOs */
@@ -502,9 +481,7 @@ com_attach_subr(sc)
break;
cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit);
-#ifdef DDB
- com_enable_debugport(sc);
-#endif
+
printf("%s: console\n", sc->sc_dev.dv_xname);
}
@@ -517,7 +494,6 @@ com_attach_subr(sc)
com_kgdb_attached = 1;
SET(sc->sc_hwflags, COM_HW_KGDB);
- com_enable_debugport(sc);
printf("%s: kgdb\n", sc->sc_dev.dv_xname);
}
#endif
@@ -530,6 +506,73 @@ com_attach_subr(sc)
rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
RND_TYPE_TTY);
#endif
+
+ /* if there are no enable/disable functions, assume the device
+ is always enabled */
+ if (!sc->enable)
+ sc->enabled = 1;
+
+ com_config(sc);
+}
+
+void
+com_config(sc)
+ struct com_softc *sc;
+{
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh = sc->sc_ioh;
+
+ /* Disable interrupts before configuring the device. */
+ sc->sc_ier = 0;
+ bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
+
+#ifdef COM_HAYESP
+ /* Look for a Hayes ESP board. */
+ if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
+ sc->sc_fifolen = 1024;
+
+ /* Set 16550 compatibility mode */
+ bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD1,
+ HAYESP_SETMODE);
+ bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
+ HAYESP_MODE_FIFO|HAYESP_MODE_RTS|
+ HAYESP_MODE_SCALE);
+
+ /* Set RTS/CTS flow control */
+ bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD1,
+ HAYESP_SETFLOWTYPE);
+ bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
+ HAYESP_FLOW_RTS);
+ bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
+ HAYESP_FLOW_CTS);
+
+ /* Set flow control levels */
+ bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD1,
+ HAYESP_SETRXFLOW);
+ bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
+ HAYESP_HIBYTE(HAYESP_RXHIWMARK));
+ bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
+ HAYESP_LOBYTE(HAYESP_RXHIWMARK));
+ bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
+ HAYESP_HIBYTE(HAYESP_RXLOWMARK));
+ bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
+ HAYESP_LOBYTE(HAYESP_RXLOWMARK));
+ }
+#endif
+
+#ifdef DDB
+ if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
+ com_enable_debugport(sc);
+#endif
+
+#ifdef KGDB
+ /*
+ * Allow kgdb to "take over" this port. If this is
+ * the kgdb device, it has exclusive use.
+ */
+ if (ISSET(sc->sc_hwflags, COM_HW_KGDB))
+ com_enable_debugport(sc);
+#endif
}
int
@@ -580,6 +623,16 @@ comopen(dev, flag, mode, p)
s2 = splserial();
+ if (sc->enable) {
+ if ((*sc->enable)(sc)) {
+ printf("%s: device enable failed\n",
+ sc->sc_dev.dv_xname);
+ return (EIO);
+ }
+ sc->enabled = 1;
+ com_config(sc);
+ }
+
/* Turn on interrupts. */
sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier);
@@ -719,6 +772,13 @@ comclose(dev, flag, mode, p)
sc->sc_ier = 0;
bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier);
+ if (sc->disable) {
+ if (sc->enabled) {
+ (*sc->disable)(sc);
+ sc->enabled = 0;
+ }
+ }
+
splx(s);
return (0);
@@ -1142,10 +1202,29 @@ com_iflush(sc)
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
+#ifdef DIAGNOSTIC
+ int reg;
+#endif
+ int timo;
+#ifdef DIAGNOSTIC
+ reg = 0xffff;
+#endif
+ timo = 50000;
/* flush any pending I/O */
- while (ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
- (void) bus_space_read_1(iot, ioh, com_data);
+ while (ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY)
+ && --timo)
+#ifdef DIAGNOSTIC
+ reg =
+#else
+ (void)
+#endif
+ bus_space_read_1(iot, ioh, com_data);
+#ifdef DIAGNOSTIC
+ if (!timo)
+ printf("%s: com_iflush timeout %02x\n", sc->sc_dev.dv_xname,
+ reg);
+#endif
}
void
@@ -1486,6 +1565,9 @@ comsoft(arg)
struct com_softc *sc = arg;
struct tty *tp;
+ if (!sc->enabled)
+ return;
+
{
#else
void
@@ -1511,6 +1593,9 @@ comsoft(arg)
if (sc == NULL)
continue;
+ if (!sc->enabled)
+ continue;
+
tp = sc->sc_tty;
if (tp == NULL || !ISSET(tp->t_state, TS_ISOPEN | TS_WOPEN))
continue;
@@ -1551,6 +1636,9 @@ comintr(arg)
u_int cc;
u_char lsr, iir;
+ if (!sc->enabled)
+ return (0);
+
iir = bus_space_read_1(iot, ioh, com_iir);
if (ISSET(iir, IIR_NOPEND))
return (0);
@@ -1731,9 +1819,16 @@ com_common_getc(iot, ioh)
{
int s = splserial();
u_char stat, c;
+ int timo;
- while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
+ timo = 50000;
+ while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY)
+ && --timo)
;
+#ifdef DIAGNOSTIC
+ if (!timo)
+ printf("com_common_getc timeout\n");
+#endif
c = bus_space_read_1(iot, ioh, com_data);
stat = bus_space_read_1(iot, ioh, com_iir);
splx(s);
@@ -1755,12 +1850,20 @@ com_common_putc(iot, ioh, c)
while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY)
&& --timo)
;
+#ifdef DIAGNOSTIC
+ if (!timo)
+ printf("com_common_putc flush timeout\n");
+#endif
bus_space_write_1(iot, ioh, com_data, c);
/* wait for this transmission to complete */
timo = 1500000;
while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY)
&& --timo)
;
+#ifdef DIAGNOSTIC
+ if (!timo)
+ printf("com_common_putc wait timeout\n");
+#endif
/* clear any interrupts generated by this transmission */
stat = bus_space_read_1(iot, ioh, com_iir);
splx(s);