somehow a real old version snuck in
[unix-history] / usr / src / sys / vax / uba / dz.c
index 5fb464c..bb42256 100644 (file)
-/*     dz.c    4.10    %G%     */
+/*     dz.c    4.35    82/03/13        */
 
 #include "dz.h"
 
 #include "dz.h"
-#if NDZ11 > 0
+#if NDZ > 0
 /*
 /*
- *  DZ-11 Driver
+ *  DZ-11 and DZ32 Driver
+ *
+ * This driver mimics dh.c; see it for explanation of common code.
  */
  */
+#include "bk.h"
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../h/tty.h"
 #include "../h/dir.h"
 #include "../h/user.h"
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../h/tty.h"
 #include "../h/dir.h"
 #include "../h/user.h"
+#include "../h/proc.h"
 #include "../h/map.h"
 #include "../h/pte.h"
 #include "../h/buf.h"
 #include "../h/map.h"
 #include "../h/pte.h"
 #include "../h/buf.h"
-#include "../h/uba.h"
+#include "../h/vm.h"
+#include "../h/ubavar.h"
 #include "../h/conf.h"
 #include "../h/pdma.h"
 #include "../h/bk.h"
 #include "../h/file.h"
 #include "../h/conf.h"
 #include "../h/pdma.h"
 #include "../h/bk.h"
 #include "../h/file.h"
-#include "../h/mx.h"
 
 /*
 
 /*
- * When running dz's using only SAE (silo alarm) on input
- * it is necessary to call dzrint() at clock interrupt time.
- * This is unsafe unless spl5()s in tty code are changed to
- * spl6()s to block clock interrupts.  Note that the dh driver
- * currently in use works the same way as the dz, even though
- * we could try to more intelligently manage its silo.
- * Thus don't take this out if you have no dz's unless you
- * change clock.c and dhtimer().
- *
- * SHOULD RATHER QUEUE SOFTWARE INTERRUPT AT CLOCK TIME.
+ * Driver information for auto-configuration stuff.
  */
  */
-#define        spl5    spl6
-int    dzcntrlr(), dzslave(), dzrint();
-struct uba_dinfo *dzinfo[NDZ11];
+int    dzprobe(), dzattach(), dzrint();
+struct uba_device *dzinfo[NDZ];
 u_short        dzstd[] = { 0 };
 u_short        dzstd[] = { 0 };
-int    (*dzivec[])() = { dzrint, 0 }; /* omit dzxint so we can do it here */
 struct uba_driver dzdriver =
 struct uba_driver dzdriver =
-       { dzcntrlr, dzslave, (int (*)())0, 0, 0, dzstd, dzinfo, dzivec };
+       { dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo };
 
 
-#define NDZ    (NDZ11*8)
+#define        NDZLINE         (NDZ*8)
  
  
-#define BITS7  020
-#define BITS8  030
-#define TWOSB  040
-#define PENABLE        0100
-#define OPAR   0200
-#define MSE    040             /* Master Scan Enable */
-#define RIE    0100            /* Receiver Interrupt Enable */
-#define        SAE     010000          /* Silo Alarm Enable */
-#define TIE    040000          /* Transmit Interrupt Enable */
-#define DZ_IEN (MSE+RIE+TIE+SAE)
-#define PERROR 010000
-#define FRERROR        020000
-#define        OVERRUN 040000
-#define SSPEED 7               /* std speed = 300 baud */
-
-#define        dzlpr   dzrbuf
-#define dzmsr  dzbrk
-#define ON     1
-#define OFF    0
+/*
+ * Registers and bits
+ */
+
+/* bits in dzlpr */
+#define        BITS7   0020
+#define        BITS8   0030
+#define        TWOSB   0040
+#define        PENABLE 0100
+#define        OPAR    0200
+
+/* bits in dzrbuf */
+#define        DZ_PE   010000
+#define        DZ_FE   020000
+#define        DZ_DO   040000
+
+/* bits in dzcsr */
+#define        DZ_32   000001          /* DZ32 mode */
+#define        DZ_MIE  000002          /* Modem Interrupt Enable */
+#define        DZ_CLR  000020          /* Reset dz */
+#define        DZ_MSE  000040          /* Master Scan Enable */
+#define        DZ_RIE  000100          /* Receiver Interrupt Enable */
+#define DZ_MSC 004000          /* Modem Status Change */
+#define        DZ_SAE  010000          /* Silo Alarm Enable */
+#define        DZ_TIE  040000          /* Transmit Interrupt Enable */
+#define        DZ_IEN  (DZ_32|DZ_MIE|DZ_MSE|DZ_RIE|DZ_TIE|DZ_SAE)
+
+/* flags for modem-control */
+#define        DZ_ON   DZ_DTR
+#define        DZ_OFF  0
+
+/* bits in dzlcs */
+#define DZ_ACK 0100000         /* ACK bit in dzlcs */
+#define DZ_RTS 0010000         /* Request To Send */
+#define        DZ_ST   0004000         /* Secondary Transmit */
+#define        DZ_BRK  0002000         /* Break */
+#define DZ_DTR 0001000         /* Data Terminal Ready */
+#define        DZ_LE   0000400         /* Line Enable */
+#define        DZ_DSR  0000200         /* Data Set Ready */
+#define        DZ_RI   0000100         /* Ring Indicate */
+#define DZ_CD  0000040         /* Carrier Detect */
+#define        DZ_CTS  0000020         /* Clear To Send */
+#define        DZ_SR   0000010         /* Secondary Receive */
  
  
-int    dzstart();
-int    dzxint();
-int    dzdma();
+/* bits in dm lsr, copied from dh.c */
+#define        DML_DSR         0000400         /* data set ready, not a real DM bit */
+#define        DML_RNG         0000200         /* ring */
+#define        DML_CAR         0000100         /* carrier detect */
+#define        DML_CTS         0000040         /* clear to send */
+#define        DML_SR          0000020         /* secondary receive */
+#define        DML_ST          0000010         /* secondary transmit */
+#define        DML_RTS         0000004         /* request to send */
+#define        DML_DTR         0000002         /* data terminal ready */
+#define        DML_LE          0000001         /* line enable */
+
+int    dzstart(), dzxint(), dzdma();
 int    ttrstrt();
 int    ttrstrt();
-struct tty dz_tty[NDZ];
-int    dz_cnt = { NDZ };
+struct tty dz_tty[NDZLINE];
+int    dz_cnt = { NDZLINE };
 int    dzact;
 
 struct device {
 int    dzact;
 
 struct device {
-       short   dzcsr;
-       short   dzrbuf;
-       char    dztcr;
-       char    dzdtr;
-       char    dztbuf;
-       char    dzbrk;
+       short dzcsr;
+       short dzrbuf;
+       union {
+               struct {
+                       char    dztcr0;
+                       char    dzdtr0;
+                       char    dztbuf0;
+                       char    dzbrk0;
+               } dz11;
+               struct {
+                       short   dzlcs0;
+                       char    dztbuf0;
+                       char    dzlnen0;
+               } dz32;
+       } dzun;
 };
 
 };
 
-struct pdma dzpdma[NDZ];
-char   dz_timer;
+#define dzlpr  dzrbuf
+#define dzmsr  dzun.dz11.dzbrk0
+#define dztcr  dzun.dz11.dztcr0
+#define dzdtr  dzun.dz11.dzdtr0
+#define dztbuf dzun.dz11.dztbuf0
+#define dzlcs  dzun.dz32.dzlcs0
+#define        dzbrk   dzmsr
+#define dzlnen dzun.dz32.dzlnen0
+#define dzmtsr dzun.dz32.dztbuf0;
+
+#define dzwait(x)      while (((x)->dzlcs & DZ_ACK) == 0)
+
+/*
+ * Software copy of dzbrk since it isn't readable
+ */
+char   dz_brk[NDZ];
+char   dzsoftCAR[NDZ];
+char   dz_lnen[NDZ];   /* saved line enable bits for DZ32 */
+
+/*
+ * The dz11 doesn't interrupt on carrier transitions, so
+ * we have to use a timer to watch it.
+ */
+char   dz_timer;               /* timer started? */
+
+/*
+ * Pdma structures for fast output code
+ */
+struct pdma dzpdma[NDZLINE];
+
 char   dz_speeds[] =
        { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 };
 char   dz_speeds[] =
        { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 };
-char   dz_brk[NDZ11];
  
  
-dzcntrlr(ui, reg)
-       struct uba_dinfo *ui;
+dzprobe(reg)
        caddr_t reg;
 {
        caddr_t reg;
 {
+       register int br, cvec;
+       register struct device *dzaddr = (struct device *)reg;
 
 
-       ((struct device *)reg)->dzcsr |= IENABLE;
-       /* get it to interrupt */
+#ifdef lint
+       br = 0; cvec = br; br = cvec;
+       dzrint(0); dzxint((struct tty *)0);
+#endif
+       dzaddr->dzcsr = DZ_TIE|DZ_MSE|DZ_32;
+       if (dzaddr->dzcsr & DZ_32)
+               dzaddr->dzlnen = 1;
+       else
+               dzaddr->dztcr = 1;              /* enable any line */
+       DELAY(100000);
+       dzaddr->dzcsr = DZ_CLR|DZ_32;           /* reset everything */
+       if (cvec && cvec != 0x200)
+               cvec -= 4;
+       return (1);
 }
 
 }
 
-dzslave(ui, reg, slaveno, uban)
-       register struct uba_dinfo *ui;
-       caddr_t reg;
+dzattach(ui)
+       register struct uba_device *ui;
 {
        register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
        register struct tty *tp = &dz_tty[ui->ui_unit*8];
 {
        register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
        register struct tty *tp = &dz_tty[ui->ui_unit*8];
-       register int cnt;
-       register int *urk = (int *)(&reg - 24); /* white magic */
-       caddr_t cp;
-       int urk2;
+       register int cntr;
+       extern dzscan();
 
 
-       for (cnt = 0; cnt < 8; cnt++) {
-               pdp->p_addr = (struct device *)reg;
+       for (cntr = 0; cntr < 8; cntr++) {
+               pdp->p_addr = (struct device *)ui->ui_addr;
                pdp->p_arg = (int)tp;
                pdp->p_fcn = dzxint;
                pdp++, tp++;
        }
                pdp->p_arg = (int)tp;
                pdp->p_fcn = dzxint;
                pdp++, tp++;
        }
-       if ((cp = calloc(12)) == 0)
-               panic("dz iv nm\n");
-       uba_hd[uban].uh_vec[*urk] = (int (*)())cp;      /* more white magic */
-       *cp++ = 0xbb; *cp++ = 0xff; *cp++ = 0xd0;       /* black magic */
-       *cp++ = ui->ui_unit&0x3f; *cp++ = 0x50;
-       *cp++ = 0x17; *cp++ = 0x9f;
-       urk2 = (int)dzdma;
-       for (cnt = 0; cnt < 4; cnt++)
-               *cp++ = urk2, urk2 >>= 4;               /* the spell ends */
-       return (1);
+       dzsoftCAR[ui->ui_unit] = ui->ui_flags;
+       if (dz_timer == 0) {
+               dz_timer++;
+               timeout(dzscan, (caddr_t)0, hz);
+       }
 }
 
 /*ARGSUSED*/
 }
 
 /*ARGSUSED*/
@@ -130,36 +196,30 @@ dzopen(dev, flag)
 {
        register struct tty *tp;
        register int unit;
 {
        register struct tty *tp;
        register int unit;
-       extern dzscan();
  
        unit = minor(dev);
        if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) {
                u.u_error = ENXIO;
                return;
        }
  
        unit = minor(dev);
        if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) {
                u.u_error = ENXIO;
                return;
        }
-       if (dz_timer == 0) {
-               dz_timer++;
-               timeout(dzscan, (caddr_t)0, 60);
-       }
        tp = &dz_tty[unit];
        tp->t_addr = (caddr_t)&dzpdma[unit];
        tp->t_oproc = dzstart;
        tp = &dz_tty[unit];
        tp->t_addr = (caddr_t)&dzpdma[unit];
        tp->t_oproc = dzstart;
-       tp->t_iproc = NULL;
-       tp->t_state |= WOPEN;
-       if ((tp->t_state & ISOPEN) == 0) {
+       tp->t_state |= TS_WOPEN;
+       if ((tp->t_state & TS_ISOPEN) == 0) {
                ttychars(tp);
                ttychars(tp);
-               tp->t_ospeed = tp->t_ispeed = SSPEED;
+               tp->t_ospeed = tp->t_ispeed = B300;
                tp->t_flags = ODDP|EVENP|ECHO;
                tp->t_flags = ODDP|EVENP|ECHO;
-               /*tp->t_state |= HUPCLS;*/
+               /* tp->t_state |= TS_HUPCLS; */
                dzparam(unit);
                dzparam(unit);
-       } else if (tp->t_state&XCLUDE && u.u_uid != 0) {
+       } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) {
                u.u_error = EBUSY;
                return;
        }
                u.u_error = EBUSY;
                return;
        }
-       dzmodem(unit, ON);
+       (void) dzmctl(dev, DZ_ON, DMSET);
        (void) spl5();
        (void) spl5();
-       while ((tp->t_state & CARR_ON) == 0) {
-               tp->t_state |= WOPEN;
+       while ((tp->t_state & TS_CARR_ON) == 0) {
+               tp->t_state |= TS_WOPEN;
                sleep((caddr_t)&tp->t_rawq, TTIPRI);
        }
        (void) spl0();
                sleep((caddr_t)&tp->t_rawq, TTIPRI);
        }
        (void) spl0();
@@ -172,16 +232,20 @@ dzclose(dev, flag)
 {
        register struct tty *tp;
        register int unit;
 {
        register struct tty *tp;
        register int unit;
+       register struct device *dzaddr;
        int dz;
  
        unit = minor(dev);
        dz = unit >> 3;
        tp = &dz_tty[unit];
        (*linesw[tp->t_line].l_close)(tp);
        int dz;
  
        unit = minor(dev);
        dz = unit >> 3;
        tp = &dz_tty[unit];
        (*linesw[tp->t_line].l_close)(tp);
-       ((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
-           (dz_brk[dz] &= ~(1 << (unit&07)));
-       if (tp->t_state & HUPCLS)
-               dzmodem(unit, OFF);
+       dzaddr = dzpdma[unit].p_addr;
+       if (dzaddr->dzcsr&DZ_32)
+               (void) dzmctl(dev, DZ_BRK, DMBIC);
+       else
+               dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
+       if ((tp->t_state&TS_HUPCLS) || (tp->t_state&TS_ISOPEN) == 0)
+               (void) dzmctl(dev, DZ_OFF, DMSET);
        ttyclose(tp);
 }
  
        ttyclose(tp);
 }
  
@@ -212,48 +276,67 @@ dzrint(dz)
        register struct device *dzaddr;
        register struct tty *tp0;
        register int unit;
        register struct device *dzaddr;
        register struct tty *tp0;
        register int unit;
-       int s;
+       int overrun = 0;
  
  
-       s = spl6();     /* see comment in clock.c */
-       /* as long as we are here, service them all */
-       for (unit = 0; unit < NDZ; unit += 8) {
-               if ((dzact & (1<<(unit>>3))) == 0)
-                       continue;
-               dzaddr = dzpdma[unit].p_addr;
-               tp0 = &dz_tty[unit];
-               while ((c = dzaddr->dzrbuf) < 0) {      /* char present */
-                       tp = tp0 + ((c>>8)&07);
-                       if (tp >= &dz_tty[dz_cnt])
-                               continue;
-                       if ((tp->t_state & ISOPEN) == 0) {
+       if ((dzact & (1<<dz)) == 0)
+               return;
+       unit = dz * 8;
+       dzaddr = dzpdma[unit].p_addr;
+       tp0 = &dz_tty[unit];
+       dzaddr->dzcsr &= ~(DZ_RIE|DZ_MIE);      /* the manual says this song */
+       dzaddr->dzcsr |= DZ_RIE|DZ_MIE;         /*   and dance is necessary */
+       while (dzaddr->dzcsr & DZ_MSC) {        /* DZ32 modem change interrupt */
+               c = dzaddr->dzmtsr;
+               tp = tp0 + (c&7);
+               if (tp >= &dz_tty[dz_cnt])
+                       break;
+               dzaddr->dzlcs = c&7;    /* get status of modem lines */
+               dzwait(dzaddr);         /* wait for them */
+               if (c & DZ_CD)          /* carrier status change? */
+               if (dzaddr->dzlcs & DZ_CD) {    /* carrier up? */
+                       if ((tp->t_state&TS_CARR_ON) == 0) {
                                wakeup((caddr_t)&tp->t_rawq);
                                wakeup((caddr_t)&tp->t_rawq);
-                               continue;
+                               tp->t_state |= TS_CARR_ON;
                        }
                        }
-                       if (c&FRERROR)
-                               /* framing error = break */
-                               if (tp->t_flags & RAW)
-                                       c = 0;          /* null for getty */
-                               else
-#ifdef IIASA
-                                       continue;
-#else
-                                       c = tun.t_intrc;
-#endif
-                       if (c&OVERRUN)
-                               printf("o");
-                       if (c&PERROR)   
-                               /* parity error */
-                               if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
-                                 || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
-                                       continue;
-                       if (tp->t_line == NETLDISC) {
-                               c &= 0177;
-                               BKINPUT(c, tp);
-                       } else
-                               (*linesw[tp->t_line].l_rint)(c, tp);
+               } else {        /* no carrier */
+                       if (tp->t_state&TS_CARR_ON) {
+                               gsignal(tp->t_pgrp, SIGHUP);
+                               gsignal(tp->t_pgrp, SIGCONT);
+                               dzaddr->dzlcs = DZ_ACK|(c&7);
+                               flushtty(tp, FREAD|FWRITE);
+                       }
+                       tp->t_state &= ~TS_CARR_ON;
                }
        }
                }
        }
-       splx(s);
+       while ((c = dzaddr->dzrbuf) < 0) {      /* char present */
+               tp = tp0 + ((c>>8)&07);
+               if (tp >= &dz_tty[dz_cnt])
+                       continue;
+               if ((tp->t_state & TS_ISOPEN) == 0) {
+                       wakeup((caddr_t)&tp->t_rawq);
+                       continue;
+               }
+               if (c&DZ_FE)
+                       if (tp->t_flags & RAW)
+                               c = 0;
+                       else
+                               c = tun.t_intrc;
+               if (c&DZ_DO && overrun == 0) {
+                       /* printf("dz%d,%d: silo overflow\n", dz, (c>>8)&7); */
+                       overrun = 1;
+               }
+               if (c&DZ_PE)    
+                       if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
+                         || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
+                               continue;
+#if NBK > 0
+               if (tp->t_line == NETLDISC) {
+                       c &= 0177;
+                       BKINPUT(c, tp);
+               } else
+#endif
+                       (*linesw[tp->t_line].l_rint)(c, tp);
+       }
 }
  
 /*ARGSUSED*/
 }
  
 /*ARGSUSED*/
@@ -264,6 +347,8 @@ dzioctl(dev, cmd, addr, flag)
        register struct tty *tp;
        register int unit = minor(dev);
        register int dz = unit >> 3;
        register struct tty *tp;
        register int unit = minor(dev);
        register int dz = unit >> 3;
+       register struct device *dzaddr;
+       int temp;
  
        tp = &dz_tty[unit];
        cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
  
        tp = &dz_tty[unit];
        cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
@@ -275,23 +360,78 @@ dzioctl(dev, cmd, addr, flag)
        } else switch(cmd) {
 
        case TIOCSBRK:
        } else switch(cmd) {
 
        case TIOCSBRK:
-               ((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
-                       (dz_brk[dz] |= 1 << (unit&07));
+               dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
+               if (dzaddr->dzcsr&DZ_32)
+                       (void) dzmctl(dev, DZ_BRK, DMBIS);
+               else
+                       dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07));
                break;
        case TIOCCBRK:
                break;
        case TIOCCBRK:
-               ((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
-                       (dz_brk[dz] &= ~(1 << (unit&07)));
+               dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
+               if (dzaddr->dzcsr&DZ_32)
+                       (void) dzmctl(dev, DZ_BRK, DMBIC);
+               else
+                       dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
                break;
        case TIOCSDTR:
                break;
        case TIOCSDTR:
-               dzmodem(unit, ON);
+               (void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS);
                break;
        case TIOCCDTR:
                break;
        case TIOCCDTR:
-               dzmodem(unit, OFF);
+               (void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC);
+               break;
+       case TIOCMSET:
+               if (copyin(addr, (caddr_t) &temp, sizeof(temp)))
+                       u.u_error = EFAULT;
+               else
+                       (void) dzmctl(dev, dmtodz(temp), DMSET);
+               break;
+       case TIOCMBIS:
+               if (copyin(addr, (caddr_t) &temp, sizeof(temp)))
+                       u.u_error = EFAULT;
+               else
+                       (void) dzmctl(dev, dmtodz(temp), DMBIS);
+               break;
+       case TIOCMBIC:
+               if (copyin(addr, (caddr_t) &temp, sizeof(temp)))
+                       u.u_error = EFAULT;
+               else
+                       (void) dzmctl(dev, dmtodz(temp), DMBIC);
+               break;
+       case TIOCMGET:
+               temp = dztodm(dzmctl(dev, 0, DMGET));
+               if (copyout((caddr_t) &temp, addr, sizeof(temp)))
+                       u.u_error = EFAULT;
                break;
        default:
                u.u_error = ENOTTY;
        }
 }
                break;
        default:
                u.u_error = ENOTTY;
        }
 }
+
+dmtodz(bits)
+       register int bits;
+{
+       register int b;
+
+       b = (bits >>1) & 0370;
+       if (bits & DML_ST) b |= DZ_ST;
+       if (bits & DML_RTS) b |= DZ_RTS;
+       if (bits & DML_DTR) b |= DZ_DTR;
+       if (bits & DML_LE) b |= DZ_LE;
+       return(b);
+}
+
+dztodm(bits)
+       register int bits;
+{
+       register int b;
+
+       b = (bits << 1) & 0360;
+       if (bits & DZ_DSR) b |= DML_DSR;
+       if (bits & DZ_DTR) b |= DML_DTR;
+       if (bits & DZ_ST) b |= DML_ST;
+       if (bits & DZ_RTS) b |= DML_RTS;
+       return(b);
+}
  
 dzparam(unit)
        register int unit;
  
 dzparam(unit)
        register int unit;
@@ -305,29 +445,18 @@ dzparam(unit)
        dzaddr->dzcsr = DZ_IEN;
        dzact |= (1<<(unit>>3));
        if (tp->t_ispeed == 0) {
        dzaddr->dzcsr = DZ_IEN;
        dzact |= (1<<(unit>>3));
        if (tp->t_ispeed == 0) {
-               dzmodem(unit, OFF);             /* hang up line */
+               (void) dzmctl(unit, DZ_OFF, DMSET);     /* hang up line */
                return;
        }
        lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
                return;
        }
        lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
-#ifndef IIASA
        if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW))
                lpr |= BITS8;
        else
                lpr |= (BITS7|PENABLE);
        if ((tp->t_flags & EVENP) == 0)
                lpr |= OPAR;
        if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW))
                lpr |= BITS8;
        else
                lpr |= (BITS7|PENABLE);
        if ((tp->t_flags & EVENP) == 0)
                lpr |= OPAR;
-#else IIASA
-       if ((tp->t_flags & (EVENP|ODDP)) == (EVENP|ODDP))
-               lpr |= BITS8;
-       else if (tp->t_flags & EVENP)
-               lpr |= (BITS7|PENABLE);
-       else if (tp->t_flags & ODDP)
-               lpr |= (BITS7|OPAR|PENABLE);
-       else
-               lpr |= BITS7;
-#endif IIASA
-       if (tp->t_ispeed == 3)
-               lpr |= TWOSB;                   /* 110 baud: 2 stop bits */
+       if (tp->t_ispeed == B110)
+               lpr |= TWOSB;
        dzaddr->dzlpr = lpr;
 }
  
        dzaddr->dzlpr = lpr;
 }
  
@@ -335,21 +464,28 @@ dzxint(tp)
        register struct tty *tp;
 {
        register struct pdma *dp;
        register struct tty *tp;
 {
        register struct pdma *dp;
-       register s;
-       s = spl6();     /* block the clock */
+       register s, dz, unit;
  
  
+       s = spl5();             /* block pdma interrupts */
        dp = (struct pdma *)tp->t_addr;
        dp = (struct pdma *)tp->t_addr;
-       tp->t_state &= ~BUSY;
-       if (tp->t_state & FLUSH)
-               tp->t_state &= ~FLUSH;
-       else
+       tp->t_state &= ~TS_BUSY;
+       if (tp->t_state & TS_FLUSH)
+               tp->t_state &= ~TS_FLUSH;
+       else {
                ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
                ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
+               dp->p_end = dp->p_mem = tp->t_outq.c_cf;
+       }
        if (tp->t_line)
                (*linesw[tp->t_line].l_start)(tp);
        else
                dzstart(tp);
        if (tp->t_line)
                (*linesw[tp->t_line].l_start)(tp);
        else
                dzstart(tp);
-       if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
-               dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07));
+       dz = minor(tp->t_dev) >> 3;
+       unit = minor(tp->t_dev) & 7;
+       if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0)
+               if (dp->p_addr->dzcsr & DZ_32)
+                       dp->p_addr->dzlnen = (dz_lnen[dz] &= ~(1<<unit));
+               else
+                       dp->p_addr->dztcr &= ~(1<<unit);
        splx(s);
 }
 
        splx(s);
 }
 
@@ -359,44 +495,52 @@ dzstart(tp)
        register struct pdma *dp;
        register struct device *dzaddr;
        register int cc;
        register struct pdma *dp;
        register struct device *dzaddr;
        register int cc;
-       int s;
+       int s, dz, unit;
  
        dp = (struct pdma *)tp->t_addr;
        dzaddr = dp->p_addr;
        s = spl5();
  
        dp = (struct pdma *)tp->t_addr;
        dzaddr = dp->p_addr;
        s = spl5();
-       if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
+       if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
                goto out;
                goto out;
-       if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) {
-               tp->t_state &= ~ASLEEP;
-               if (tp->t_chan)
-                       mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
-               else
+       if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
+               if (tp->t_state&TS_ASLEEP) {
+                       tp->t_state &= ~TS_ASLEEP;
                        wakeup((caddr_t)&tp->t_outq);
                        wakeup((caddr_t)&tp->t_outq);
+               }
+               if (tp->t_wsel) {
+                       selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
+                       tp->t_wsel = 0;
+                       tp->t_state &= ~TS_WCOLL;
+               }
        }
        if (tp->t_outq.c_cc == 0)
                goto out;
        }
        if (tp->t_outq.c_cc == 0)
                goto out;
-       if (tp->t_flags&RAW)
+       if ((tp->t_flags&RAW) || (tp->t_local&LLITOUT))
                cc = ndqb(&tp->t_outq, 0);
        else {
                cc = ndqb(&tp->t_outq, 0200);
                if (cc == 0) {
                        cc = getc(&tp->t_outq);
                cc = ndqb(&tp->t_outq, 0);
        else {
                cc = ndqb(&tp->t_outq, 0200);
                if (cc == 0) {
                        cc = getc(&tp->t_outq);
-                       timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6);
-                       tp->t_state |= TIMEOUT;
+                       timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
+                       tp->t_state |= TS_TIMEOUT;
                        goto out;
                }
        }
                        goto out;
                }
        }
-       tp->t_state |= BUSY;
+       tp->t_state |= TS_BUSY;
        dp->p_end = dp->p_mem = tp->t_outq.c_cf;
        dp->p_end += cc;
        dp->p_end = dp->p_mem = tp->t_outq.c_cf;
        dp->p_end += cc;
-       dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07);
+       dz = minor(tp->t_dev) >> 3;
+       unit = minor(tp->t_dev) & 7;
+       if (dzaddr->dzcsr & DZ_32)
+               dzaddr->dzlnen = (dz_lnen[dz] |= (1<<unit));
+       else
+               dzaddr->dztcr |= (1<<unit);
 out:
        splx(s);
 }
  
 /*
  * Stop output on a line.
 out:
        splx(s);
 }
  
 /*
  * Stop output on a line.
- * Assume call is made at spl6.
  */
 /*ARGSUSED*/
 dzstop(tp, flag)
  */
 /*ARGSUSED*/
 dzstop(tp, flag)
@@ -406,27 +550,69 @@ dzstop(tp, flag)
        register int s;
 
        dp = (struct pdma *)tp->t_addr;
        register int s;
 
        dp = (struct pdma *)tp->t_addr;
-       s = spl6();
-       if (tp->t_state & BUSY) {
+       s = spl5();
+       if (tp->t_state & TS_BUSY) {
                dp->p_end = dp->p_mem;
                dp->p_end = dp->p_mem;
-               if ((tp->t_state&TTSTOP)==0)
-                       tp->t_state |= FLUSH;
+               if ((tp->t_state&TS_TTSTOP)==0)
+                       tp->t_state |= TS_FLUSH;
        }
        splx(s);
 }
  
        }
        splx(s);
 }
  
-dzmodem(unit, flag)
-       register int unit;
+dzmctl(dev, bits, how)
+       dev_t dev;
+       int bits, how;
 {
        register struct device *dzaddr;
 {
        register struct device *dzaddr;
-       register char bit;
+       register int unit, mbits;
+       int b, s;
+
+       unit = minor(dev);
+       b = 1<<(unit&7);
        dzaddr = dzpdma[unit].p_addr;
        dzaddr = dzpdma[unit].p_addr;
-       bit = 1<<(unit&07);
-       if (flag == OFF)
-               dzaddr->dzdtr &= ~bit;
-       else
-               dzaddr->dzdtr |= bit;
+       s = spl5();
+       if (dzaddr->dzcsr & DZ_32) {
+               dzwait(dzaddr)
+               DELAY(100);             /* IS 100 TOO MUCH? */
+               dzaddr->dzlcs = unit&7;
+               DELAY(100);
+               dzwait(dzaddr)
+               DELAY(100);
+               mbits = dzaddr->dzlcs;
+               mbits &= 0177770;
+       } else {
+               mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0;
+               mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0;
+               mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0;
+       }
+       switch (how) {
+       case DMSET:
+               mbits = bits;
+               break;
+
+       case DMBIS:
+               mbits |= bits;
+               break;
+
+       case DMBIC:
+               mbits &= ~bits;
+               break;
+
+       case DMGET:
+               (void) splx(s);
+               return(mbits);
+       }
+       if (dzaddr->dzcsr & DZ_32) {
+               mbits |= DZ_ACK|(unit&7);
+               dzaddr->dzlcs = mbits;
+       } else {
+               if (mbits & DZ_DTR)
+                       dzaddr->dzdtr |= b;
+               else
+                       dzaddr->dzdtr &= ~b;
+       }
+       (void) splx(s);
+       return(mbits);
 }
  
 dzscan()
 }
  
 dzscan()
@@ -435,37 +621,52 @@ dzscan()
        register struct device *dzaddr;
        register bit;
        register struct tty *tp;
        register struct device *dzaddr;
        register bit;
        register struct tty *tp;
+       register car;
  
        for (i = 0; i < dz_cnt ; i++) {
                dzaddr = dzpdma[i].p_addr;
  
        for (i = 0; i < dz_cnt ; i++) {
                dzaddr = dzpdma[i].p_addr;
+               if (dzaddr == 0)
+                       continue;
                tp = &dz_tty[i];
                bit = 1<<(i&07);
                tp = &dz_tty[i];
                bit = 1<<(i&07);
-               if (dzaddr->dzmsr & bit || (i == 6 || i == 7)) {
+               car = 0;
+               if (dzsoftCAR[i>>3]&bit)
+                       car = 1;
+               else if (dzaddr->dzcsr & DZ_32) {
+                       dzaddr->dzlcs = i&07;
+                       dzwait(dzaddr);
+                       car = dzaddr->dzlcs & DZ_CD;
+               } else
+                       car = dzaddr->dzmsr&bit;
+               if (car) {
                        /* carrier present */
                        /* carrier present */
-                       if ((tp->t_state & CARR_ON) == 0) {
+                       if ((tp->t_state & TS_CARR_ON) == 0) {
                                wakeup((caddr_t)&tp->t_rawq);
                                wakeup((caddr_t)&tp->t_rawq);
-                               tp->t_state |= CARR_ON;
+                               tp->t_state |= TS_CARR_ON;
                        }
                } else {
                        }
                } else {
-                       if ((tp->t_state&CARR_ON) && (tp->t_local&LNOHANG)==0) {
+                       if ((tp->t_state&TS_CARR_ON) &&
+                           (tp->t_local&LNOHANG)==0) {
                                /* carrier lost */
                                /* carrier lost */
-                               if (tp->t_state&ISOPEN) {
+                               if (tp->t_state&TS_ISOPEN) {
                                        gsignal(tp->t_pgrp, SIGHUP);
                                        gsignal(tp->t_pgrp, SIGCONT);
                                        dzaddr->dzdtr &= ~bit;
                                        flushtty(tp, FREAD|FWRITE);
                                }
                                        gsignal(tp->t_pgrp, SIGHUP);
                                        gsignal(tp->t_pgrp, SIGCONT);
                                        dzaddr->dzdtr &= ~bit;
                                        flushtty(tp, FREAD|FWRITE);
                                }
-                               tp->t_state &= ~CARR_ON;
+                               tp->t_state &= ~TS_CARR_ON;
                        }
                }
        }
                        }
                }
        }
-       timeout(dzscan, (caddr_t)0, 2*HZ);
+       timeout(dzscan, (caddr_t)0, 2*hz);
 }
 
 dztimer()
 {
 }
 
 dztimer()
 {
+       int dz;
 
 
-       dzrint(0);
+       for (dz = 0; dz < NDZ; dz++)
+               dzrint(dz);
 }
 
 /*
 }
 
 /*
@@ -473,19 +674,23 @@ dztimer()
  * Reset parameters and restart transmission on open lines.
  */
 dzreset(uban)
  * Reset parameters and restart transmission on open lines.
  */
 dzreset(uban)
+       int uban;
 {
        register int unit;
        register struct tty *tp;
 {
        register int unit;
        register struct tty *tp;
+       register struct uba_device *ui;
 
 
-       /*** WE SHOULD LOOK TO SEE IF WE CARE ABOUT UBA BEING RESET ***/
-
-       printf(" dz");
-       for (unit = 0; unit < NDZ; unit++) {
+       for (unit = 0; unit < NDZLINE; unit++) {
+               ui = dzinfo[unit >> 3];
+               if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
+                       continue;
+               if (unit%8 == 0)
+                       printf(" dz%d", unit>>3);
                tp = &dz_tty[unit];
                tp = &dz_tty[unit];
-               if (tp->t_state & (ISOPEN|WOPEN)) {
+               if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
                        dzparam(unit);
                        dzparam(unit);
-                       dzmodem(unit, ON);
-                       tp->t_state &= ~BUSY;
+                       (void) dzmctl(unit, DZ_ON, DMSET);
+                       tp->t_state &= ~TS_BUSY;
                        dzstart(tp);
                }
        }
                        dzstart(tp);
                }
        }