Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-1-4]: src/sys/dev/ic Pull up revision 1.6:



details:   https://anonhg.NetBSD.org/src/rev/e54c30bb8120
branches:  netbsd-1-4
changeset: 469368:e54c30bb8120
user:      he <he%NetBSD.org@localhost>
date:      Fri Sep 10 23:32:12 1999 +0000

description:
Pull up revision 1.6:
  Fix panics seen by some people during mvme167 installation.  (scw)

diffstat:

 sys/dev/ic/clmpcc.c |  169 ++++++++++++++++++++++++++++-----------------------
 1 files changed, 92 insertions(+), 77 deletions(-)

diffs (287 lines):

diff -r fa402cf7754b -r e54c30bb8120 sys/dev/ic/clmpcc.c
--- a/sys/dev/ic/clmpcc.c       Fri Sep 10 23:31:15 1999 +0000
+++ b/sys/dev/ic/clmpcc.c       Fri Sep 10 23:32:12 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: clmpcc.c,v 1.4.2.1 1999/04/05 17:36:38 scw Exp $ */
+/*     $NetBSD: clmpcc.c,v 1.4.2.2 1999/09/10 23:32:12 he Exp $ */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -126,6 +126,8 @@
 integrate void      clmpcc_wrreg __P((struct clmpcc_softc *, u_int, u_int));
 integrate u_int8_t  clmpcc_rdreg_odd __P((struct clmpcc_softc *, u_int));
 integrate void      clmpcc_wrreg_odd __P((struct clmpcc_softc *, u_int, u_int));
+integrate void      clmpcc_wrtx_multi __P((struct clmpcc_softc *, u_int8_t *,
+                                       u_int));
 integrate u_int8_t  clmpcc_select_channel __P((struct clmpcc_softc *, u_int));
 integrate void      clmpcc_channel_cmd __P((struct clmpcc_softc *,int,int));
 integrate void      clmpcc_enable_transmitter __P((struct clmpcc_chan *));
@@ -191,6 +193,22 @@
        bus_space_write_1(sc->sc_iot, sc->sc_ioh, offset, val);
 }
 
+integrate void
+clmpcc_wrtx_multi(sc, buff, count)
+       struct clmpcc_softc *sc;
+       u_int8_t *buff;
+       u_int count;
+{
+       u_int offset = CLMPCC_REG_TDR;
+
+#if !defined(CLMPCC_ONLY_BYTESWAP_LOW) && !defined(CLMPCC_ONLY_BYTESWAP_HIGH)
+       offset ^= (sc->sc_byteswap & 2);
+#elif defined(CLMPCC_ONLY_BYTESWAP_HIGH)
+       offset ^= (CLMPCC_BYTESWAP_HIGH & 2);
+#endif
+       bus_space_write_multi_1(sc->sc_iot, sc->sc_ioh, offset, buff, count);
+}
+
 integrate u_int8_t
 clmpcc_select_channel(sc, new_chan)
        struct clmpcc_softc *sc;
@@ -234,13 +252,9 @@
        old = clmpcc_select_channel(ch->ch_sc, ch->ch_car);
 
        s = splserial();
-
        clmpcc_wrreg(ch->ch_sc, CLMPCC_REG_IER,
                clmpcc_rdreg(ch->ch_sc, CLMPCC_REG_IER) | CLMPCC_IER_TX_EMPTY);
-
-       CLR(ch->ch_flags, CLMPCC_FLG_START);
        SET(ch->ch_tty->t_state, TS_BUSY);
-
        splx(s);
 
        clmpcc_select_channel(ch->ch_sc, old);
@@ -1007,28 +1021,34 @@
 {
        struct clmpcc_softc *sc = clmpcc_cd.cd_devs[CLMPCCUNIT(tp->t_dev)];
        struct clmpcc_chan *ch = &sc->sc_chans[CLMPCCCHAN(tp->t_dev)];
+       u_int oldch;
        int s;
 
        s = spltty();
 
-       if ( ISCLR(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY) &&
-            ISCLR(ch->ch_flags, CLMPCC_FLG_STOP) ) {
+       if ( ISCLR(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY) ) {
                if ( tp->t_outq.c_cc <= tp->t_lowat ) {
                        if ( ISSET(tp->t_state, TS_ASLEEP) ) {
                                CLR(tp->t_state, TS_ASLEEP);
                                wakeup(&tp->t_outq);
                        }
                        selwakeup(&tp->t_wsel);
+               }
 
-                       if ( tp->t_outq.c_cc == 0 )
-                               goto out;
+               if ( tp->t_outq.c_cc > 0 ) {
+                       ch->ch_obuf_addr = tp->t_outq.c_cf;
+                       ch->ch_obuf_size = ndqb(&tp->t_outq, 0);
+
+                       /* Enable TX empty interrupts */
+                       oldch = clmpcc_select_channel(ch->ch_sc, ch->ch_car);
+                       clmpcc_wrreg(ch->ch_sc, CLMPCC_REG_IER,
+                               clmpcc_rdreg(ch->ch_sc, CLMPCC_REG_IER) |
+                                            CLMPCC_IER_TX_EMPTY);
+                       clmpcc_select_channel(ch->ch_sc, oldch);
+                       SET(tp->t_state, TS_BUSY);
                }
-               SET(tp->t_state, TS_BUSY);
-               clmpcc_enable_transmitter(ch);
        }
 
-out:
-       CLR(ch->ch_flags, CLMPCC_FLG_START);
        splx(s);
 }
 
@@ -1044,17 +1064,12 @@
        struct clmpcc_chan *ch = &sc->sc_chans[CLMPCCCHAN(tp->t_dev)];
        int s;
 
-       s = spltty();
+       s = splserial();
 
        if ( ISSET(tp->t_state, TS_BUSY) ) {
                if ( ISCLR(tp->t_state, TS_TTSTOP) )
                        SET(tp->t_state, TS_FLUSH);
-
-               /*
-                * The transmit interrupt routine will disable transmit when it
-                * notices that CLMPCC_FLG_STOP has been set.
-                */
-               SET(ch->ch_flags, CLMPCC_FLG_STOP);
+               ch->ch_obuf_size = 0;
        }
        splx(s);
 }
@@ -1247,62 +1262,48 @@
 
        /* Handle a delayed parameter change */
        if ( ISSET(ch->ch_flags, CLMPCC_FLG_UPDATE_PARMS) ) {
+               CLR(ch->ch_flags, CLMPCC_FLG_UPDATE_PARMS);
                clmpcc_set_params(ch);
-               CLR(ch->ch_flags, CLMPCC_FLG_UPDATE_PARMS);
-               SET(ch->ch_flags, CLMPCC_FLG_START);
-               goto tx_done;
        }
 
-       /* Stop transmitting if CLMPCC_FLG_STOP is set */
-       if ( ISSET(ch->ch_flags, CLMPCC_FLG_STOP) )
-               goto tx_done;
-
-       CLR(ch->ch_flags, CLMPCC_FLG_UPDATE_PARMS);
+       if ( ch->ch_obuf_size > 0 ) {
+               u_int n = min(ch->ch_obuf_size, ftc);
 
-       if ( tp->t_outq.c_cc > 0 ) {
-               SET(tp->t_state, TS_BUSY);
-               while (tp->t_outq.c_cc > 0 && ftc > 0 ) {
-                       clmpcc_wr_txdata(sc, getc(&tp->t_outq));
-                       ftc--;
-               }
+               clmpcc_wrtx_multi(sc, ch->ch_obuf_addr, n);
+
+               ftc -= n;
+               ch->ch_obuf_size -= n;
+               ch->ch_obuf_addr += n;
        } else {
                /*
                 * No data to send -- check if we should
                 * start/stop a break
                 */
-               /*
-                * XXX does this cause too much delay before
-                * breaks?
-                */
                if ( ISSET(ch->ch_flags, CLMPCC_FLG_START_BREAK) ) {
                        CLR(ch->ch_flags, CLMPCC_FLG_START_BREAK);
+                       /* TBD */
                }
 
                if ( ISSET(ch->ch_flags, CLMPCC_FLG_END_BREAK) ) {
                        CLR(ch->ch_flags, CLMPCC_FLG_END_BREAK);
+                       /* TBD */
                }
-       }
 
-       if ( tp->t_outq.c_cc == 0 ) {
-tx_done:
                /*
-                * No data to send, requested to stop or waiting for
-                * an INIT following a parameter change.
                 * Disable transmit interrupt
                 */
                clmpcc_wrreg(ch->ch_sc, CLMPCC_REG_IER,
                        clmpcc_rdreg(ch->ch_sc, CLMPCC_REG_IER) &
                                                ~CLMPCC_IER_TX_EMPTY);
-               CLR(ch->ch_flags, CLMPCC_FLG_STOP);
-               CLR(tp->t_state, TS_BUSY);
-       }
 
-       if ( tp->t_outq.c_cc <= tp->t_lowat )
-               SET(ch->ch_flags, CLMPCC_FLG_START);
-
-       if ( ISSET(ch->ch_flags, CLMPCC_FLG_START) && ! sc->sc_soft_running ) {
-               sc->sc_soft_running = 1;
-               (sc->sc_softhook)(sc);
+               /*
+                * Request Tx processing in the soft interrupt handler
+                */
+               ch->ch_tx_done = 1;
+               if ( ! sc->sc_soft_running ) {
+                       sc->sc_soft_running = 1;
+                       (sc->sc_softhook)(sc);
+               }
        }
 
        if ( ftc != oftc )
@@ -1365,7 +1366,6 @@
 
        sc->sc_soft_running = 0;
 
-
        /* Handle Modem state changes too... */
 
        for (chan = 0; chan < CLMPCC_NUM_CHANS; chan++) {
@@ -1380,8 +1380,8 @@
                        c = get[0];
                        c |= ((u_int)get[1]) << 8;
                        if ( (rint)(c, tp) == -1 ) {
-                           ch->ch_ibuf_rd = ch->ch_ibuf_wr;
-                           break;
+                               ch->ch_ibuf_rd = ch->ch_ibuf_wr;
+                               break;
                        }
 
                        get += 2;
@@ -1391,31 +1391,46 @@
                        ch->ch_ibuf_rd = get;
                }
 
-               if ( ISSET(ch->ch_flags, CLMPCC_FLG_NEED_INIT) ) {
-                       clmpcc_channel_cmd(sc, ch->ch_car, CLMPCC_CCR_T0_INIT |
-                                                          CLMPCC_CCR_T0_RX_EN |
-                                                          CLMPCC_CCR_T0_TX_EN);
-                       CLR(ch->ch_flags, CLMPCC_FLG_NEED_INIT);
+               /*
+                * Is the transmitter idle and in need of attention?
+                */
+               if ( ch->ch_tx_done ) {
+                       ch->ch_tx_done = 0;
+
+                       if ( ISSET(ch->ch_flags, CLMPCC_FLG_NEED_INIT) ) {
+                               clmpcc_channel_cmd(sc, ch->ch_car,
+                                                      CLMPCC_CCR_T0_INIT  |
+                                                      CLMPCC_CCR_T0_RX_EN |
+                                                      CLMPCC_CCR_T0_TX_EN);
+                               CLR(ch->ch_flags, CLMPCC_FLG_NEED_INIT);
 
-                       /*
-                        * Allow time for the channel to initialise.
-                        * (Empirically derived duration; the must be
-                        * another way to determine the command
-                        * has completed without busy-waiting...)
-                        */
-                       delay(800);
+                               /*
+                                * Allow time for the channel to initialise.
+                                * (Empirically derived duration; there must
+                                * be another way to determine the command
+                                * has completed without busy-waiting...)
+                                */
+                               delay(800);
 
-                       /*
-                        * Update the tty layer's idea of the carrier bit,
-                        * in case we changed CLOCAL or MDMBUF. We don't
-                        * hang up here; we only do that by explicit request.
-                        */
-                       reg = clmpcc_rd_msvr(sc) & CLMPCC_MSVR_CD;
-                       (void) (*linesw[tp->t_line].l_modem)(tp, reg != 0);
+                               /*
+                                * Update the tty layer's idea of the carrier
+                                * bit, in case we changed CLOCAL or MDMBUF.
+                                * We don't hang up here; we only do that by
+                                * explicit request.
+                                */
+                               reg = clmpcc_rd_msvr(sc) & CLMPCC_MSVR_CD;
+                               (*linesw[tp->t_line].l_modem)(tp, reg != 0);
+                       }
+
+                       CLR(tp->t_state, TS_BUSY);
+                       if ( ISSET(tp->t_state, TS_FLUSH) )
+                               CLR(tp->t_state, TS_FLUSH);
+                       else
+                               ndflush(&tp->t_outq,
+                                    (int)(ch->ch_obuf_addr - tp->t_outq.c_cf));
+
+                       (*linesw[tp->t_line].l_start)(tp);
                }
-
-               if ( ISSET(ch->ch_flags, CLMPCC_FLG_START) )
-                       (*linesw[tp->t_line].l_start)(tp);
        }
 
        return 0;



Home | Main Index | Thread Index | Old Index