linux-mips-fnet
[Top] [All Lists]

Re: DECStation zs driver continued...

To: linux-mips@fnet.fr
Subject: Re: DECStation zs driver continued...
From: "Gleb O. Raiko" <raiko@niisi.msk.ru>
Date: Wed, 30 Jun 1999 11:06:32 +0400
Organization: NIISI RAN
References: <XFMail.990629214825.Harald.Koerfgen@home.ivm.de>
Hello Harald,

Harald Koerfgen wrote:
> 
> Maybe I'm simple naive but do we really need rs_wait_until_sent? Neither
> the sgi nor the sparc serial drivers have one and I'm wondering if
> tty_wait_until_sent(...) would do the trick.

There is a possibility that zs state is changed while tx buffer isn't
empty. Either we should reimplement driver for synchronous mode when we
wait for empty tx buffer at every transmit (and it will slow down
ppp/slip links). Or implement wait_until_sent.

> 
> Personally I'd prefer kicking zs.c in the bin and write a new one. zs.c
> is and was never ment to be anything else but a bad hack.

I'd like to note that I debugged DECstation zs at the point where it's
stable enough to carry terminal, keyboard, and mouse. The only thing I
have in TODO list is wait_until_sent. I think I'll ready to send a patch
during next week.

> 
> IMHO we really should think about a more general approach. Maintaining
> five or six different zs drivers simply is a pain in the *ss and a generic
> zs driver and some hardware specific helper routines for different
> machines _does_ make much more sense, doesn't it?

Let's wait until new implementation of the driver layer will come to
life. I mean the idea when we'll have bus independent drivers, dropped
Space.c, and driver initilization routines in an ELF section. It might
appear even in 2.3 series.

BTW, we've got at least 5 lance drivers (PC, Sparc, Atari, DECstation,
and Baget).

Ok. You might want to look at the following.

-static inline void zs_rtsdtr(struct dec_serial *ss, int set)
+static inline void zs_rtsdtr(struct dec_serial *info, int set)
 {
-       if (ss->zs_channel != ss->zs_chan_a) {
-               if (set)
-                       ss->zs_chan_a->curregs[5] |= (RTS | DTR);
-               else
-                       ss->zs_chan_a->curregs[5] &= ~(RTS | DTR);
-               write_zsreg(ss->zs_chan_a, 5,
ss->zs_chan_a->curregs[5]);
-       }
-       return;
+        unsigned long flags;
+
+        save_flags(flags); cli();
+        if(set) {
+                info->zs_channel->curregs[5] |= (RTS | DTR);
+        } else {
+                info->zs_channel->curregs[5] &= ~(RTS | DTR);
+        }
+       write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
+       restore_flags(flags);
}

@@ -362,7 +395,8 @@
                *tty->flip.flag_buf_ptr++ = flag;
                *tty->flip.char_buf_ptr++ = ch;
        }
-       tty_flip_buffer_push(tty);
+       if (tty)
+               tty_flip_buffer_push(tty);
}

@@ -473,7 +507,30 @@
                        status_handle(info);
                }
        }
+       
+       // FIXME: is it really needed (and why) ?
+       write_zsreg(info->zs_channel, 0, RES_H_IUS);
}

@@ -667,9 +725,9 @@
 
        info->zs_channel->curregs[5] &= ~TxENAB;
        write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
+
        if (!info->tty || C_HUPCL(info->tty)) {
-               info->zs_chan_a->curregs[5] &= ~(DTR | RTS);
-               write_zsreg(info->zs_chan_a, 5,
info->zs_chan_a->curregs[5]);
+               zs_rtsdtr(info, 0);
        }
 
        if (info->tty)

...

static void change_speed(struct dec_serial *info)
{
        unsigned short port;
        unsigned cflag;
        int     i;
        int     brg;
        unsigned long flags;
 
        if (!info->tty || !info->tty->termios)
                return;
        cflag = info->tty->termios->c_cflag;
        if (!(port = info->port))
                return;
        i = cflag & CBAUD;
        save_flags(flags); cli();
        info->zs_baud = baud_table[i];
        info->clk_divisor = 16;
-
-       switch (info->zs_baud) {
-       default:
+        if (info->zs_baud) {
                info->zs_channel->curregs[4] = X16CLK;
                brg = BPS_TO_BRG(info->zs_baud,
ZS_CLOCK/info->clk_divisor);
                info->zs_channel->curregs[12] = (brg & 255);
                info->zs_channel->curregs[13] = ((brg >> 8) & 255);
-       }
+               zs_rtsdtr(info, 1); 
+       } else {
+                zs_rtsdtr(info, 0);
+                return;
+       }
 
        /* byte size and parity */
        info->zs_channel->curregs[3] &= ~RxNBITS_MASK;

@@ -899,17 +964,7 @@
        }
 
        if (C_CRTSCTS(tty)) {
-               /*
-                * Here we want to turn off the RTS line.  On
Macintoshes,
-                * we only get the DTR line, which goes to both DTR and
-                * RTS on the modem.  RTS doesn't go out to the serial
-                * port socket.  So you should make sure your modem is
-                * set to ignore DTR if you're using CRTSCTS.
-                */
-               save_flags(flags); cli();
-               info->zs_chan_a->curregs[5] &= ~(DTR | RTS);
-               write_zsreg(info->zs_chan_a, 5,
info->zs_chan_a->curregs[5]);
-               restore_flags(flags);
+               zs_rtsdtr(info, 0);
        }
 }

@@ -941,11 +996,7 @@
        }
 
        if (C_CRTSCTS(tty)) {
-               /* Assert RTS and DTR lines */
-               save_flags(flags); cli();
-               info->zs_chan_a->curregs[5] |= DTR | RTS;
-               write_zsreg(info->zs_chan_a, 5,
info->zs_chan_a->curregs[5]);
-               restore_flags(flags);
+               zs_rtsdtr(info, 1);
        }
}

It's not a patch, but you might feel ideas. I copied most interesting
parts from the real patch I am prepearing and removed all Baget stuff.
Also, the part of the patch I sent before (considering wait_until_send)
was removed.

There is two fatal bugs fixed. First, missed check for NULL tty before
doing flip_buffer_push. Second, oversimplified switch with one default
case in change_spped which leads to division by zero.

Regards,
Gleb.

<Prev in Thread] Current Thread [Next in Thread>