From 1d4b77e754799446c627e32905f11f808df36ee1 Mon Sep 17 00:00:00 2001 From: marc Date: Sun, 1 Feb 1998 23:33:01 +0000 Subject: [PATCH] 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 --- sys/dev/ic/com.c | 167 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 135 insertions(+), 32 deletions(-) diff --git a/sys/dev/ic/com.c b/sys/dev/ic/com.c index 00e1a61e2340..ec461dbdd987 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);