set WOPEN on first open
[unix-history] / usr / src / sys / tahoe / vba / vx.c
index ae9ef58..c1ce194 100644 (file)
-/*     vx.c    1.1     85/07/21        */
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Computer Consoles Inc.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *     @(#)vx.c        7.8 (Berkeley) %G%
+ */
 
 #include "vx.h"
 #if NVX > 0
 /*
 
 #include "vx.h"
 #if NVX > 0
 /*
- *     VIOC-X driver
+ * VIOC-X driver
  */
  */
-
-#include "../h/param.h"
-#include "../h/ioctl.h"
-#include "../h/tty.h"
-#include "../h/dir.h"
-#include "../h/user.h"
-#include "../h/map.h"
-#include "../machine/pte.h"
-#include "../h/buf.h"
-#include "../vba/vbavar.h"
-#include "../h/conf.h"
-#include "../h/file.h"
-#include "../h/uio.h"
-#include "../vba/vioc.h"
 #ifdef VXPERF
 #ifdef VXPERF
-#include "../vba/scope.h"
-#endif VXPERF
-#include "vbsc.h"
-#if NVBSC > 0
-#include "../bsc/bscio.h"
-#include "../bsc/bsc.h"
-char bscport[NVXPORTS];
+#define        DOSCOPE
 #endif
 
 #endif
 
-#ifdef BSC_DEBUG
-#include "../bsc/bscdebug.h"
-#endif
+#include "param.h"
+#include "ioctl.h"
+#include "tty.h"
+#include "user.h"
+#include "map.h"
+#include "buf.h"
+#include "conf.h"
+#include "file.h"
+#include "proc.h"
+#include "vm.h"
+#include "kernel.h"
+#include "syslog.h"
+
+#include "../tahoe/pte.h"
+
+#include "../tahoevba/vbavar.h"
+#include "../tahoevba/vbaparam.h"
+#include "../tahoevba/vxreg.h"
+#include "../tahoevba/scope.h"
 
 
-#ifdef VX_DEBUG
-long vxintr4 = 0;
-long vxdebug = 0;
-#include "../vba/vxdebug.h"
+#ifdef VX_DEBUG
+long   vxintr4 = 0;
+#define        VXERR4  1
+#define        VXNOBUF 2
+long   vxdebug = 0;
+#define        VXVCM   1
+#define        VXVCC   2
+#define        VXVCX   4
 #endif
 
 #endif
 
-#define RSPquals       1
+/*
+ * Interrupt type bits passed to vinthandl().
+ */
+#define        CMDquals 0              /* command completed interrupt */
+#define        RSPquals 1              /* command response interrupt */
+#define        UNSquals 2              /* unsolicited interrupt */
 
 
-struct vcx     vcx[NVIOCX] ;
-struct tty     vx_tty[NVXPORTS];
-extern struct vcmds v_cmds[];
-extern long reinit;
+#define        VXUNIT(n)       ((n) >> 4)
+#define        VXPORT(n)       ((n) & 0xf)
 
 
-int    vxstart() ;
-int    ttrstrt() ;
-caddr_t vtoph();
-struct vxcmd   *vobtain() ;
-struct vxcmd   *nextcmd() ;
+struct tty vx_tty[NVX*16];
+#ifndef lint
+int    nvx = NVX*16;
+#endif
+int    vxstart(), ttrstrt();
+struct vxcmd *vobtain(), *nextcmd();
 
 /*
  * Driver information for auto-configuration stuff.
 
 /*
  * Driver information for auto-configuration stuff.
- * (not tested and probably should be changed)
  */
 int    vxprobe(), vxattach(), vxrint();
  */
 int    vxprobe(), vxattach(), vxrint();
-struct vba_device *vxinfo[NVIOCX];
+struct vba_device *vxinfo[NVX];
 long   vxstd[] = { 0 };
 struct vba_driver vxdriver =
 long   vxstd[] = { 0 };
 struct vba_driver vxdriver =
-       { vxprobe, 0, vxattach, 0, vxstd, "vioc ", vxinfo };
-
-char vxtype[NVIOCX];   /* 0: viox-x/vioc-b; 1: vioc-bop */
-char vxbbno = -1;
-char vxbopno[NVIOCX];  /* BOP board no. if indicated by vxtype[] */
-extern vbrall();
-
-
-vxprobe(reg)
+    { vxprobe, 0, vxattach, 0, vxstd, "vx", vxinfo };
+
+struct vx_softc {
+       struct  vxdevice *vs_addr;      /* H/W address */
+       u_char  vs_type;        /* 0: viox-x/vioc-b, 1: vioc-bop */
+       u_char  vs_bop;         /* bop board # for vioc-bop's */
+       u_char  vs_loport;      /* low port nbr */
+       u_char  vs_hiport;      /* high port nbr */
+       u_short vs_nbr;         /* viocx number */
+       u_short vs_maxcmd;      /* max number of concurrent cmds */
+       u_short vs_silosiz;     /* silo size */
+       short   vs_vers;        /* vioc/pvioc version */
+#define        VXV_OLD 0               /* PVIOCX | VIOCX */
+#define        VXV_NEW 1               /* NPVIOCX | NVIOCX */
+       short   vs_state;       /* controller state */
+#define        VXS_READY       0       /* ready for commands */
+#define        VXS_RESET       1       /* in process of reseting */
+       u_short vs_softCAR;     /* soft carrier */
+       u_int   vs_ivec;        /* interrupt vector base */
+       caddr_t vs_mricmd;      /* most recent issued cmd */
+       /* The remaining fields are zeroed on reset... */
+#define vs_zero vs_xmtcnt
+       int     vs_xmtcnt;      /* xmit commands pending */
+       struct  vxcmd *vs_avail;/* next available command buffer */
+       struct  vxcmd *vs_build;
+       struct  vxcmd vs_lst[NVCXBUFS];
+       struct  vcmds vs_cmds;
+} vx_softc[NVX];
+
+struct speedtab vxspeedtab[] = {
+       EXTA,   V19200,
+       EXTB,   V19200,
+       19200,  V19200,
+       9600,   13,
+       4800,   12,
+       2400,   11,
+       1800,   10,
+       1200,   9,
+       600,    8,
+       300,    7,
+       200,    6,
+       150,    5,
+       134,    4,
+       110,    3,
+       75,     2,
+       50,     1,
+       0,      0,
+       -1,     -1,
+};
+
+vxprobe(reg, vi)
        caddr_t reg;
        caddr_t reg;
+       struct vba_device *vi;
 {
 {
-       register int br, cvec;
-       register struct vblok *vp = (struct vblok *)reg;
+       register int br, cvec;                  /* must be r12, r11 */
+       register struct vxdevice *vp;
+       register struct vx_softc *vs;
+       struct pte *dummypte;
 
 #ifdef lint
        br = 0; cvec = br; br = cvec;
 
 #ifdef lint
        br = 0; cvec = br; br = cvec;
+       vackint(0); vunsol(0); vcmdrsp(0);
+#ifdef VX_DEBUG
+       vxfreset(0);
 #endif
 #endif
-
-       if(badaddr(vp, 1))
+#endif /* lint */
+       /*
+        * If on an HCX-9, the device has a 32-bit address,
+        * and we receive that address so we can set up a map.
+        * On VERSAbus devices, the address is 24-bit, and is
+        * already mapped (into vmem[]) by autoconf.
+        */
+       if (!(reg >= vmem && reg < &vmem[ctob(VBIOSIZE)]) &&    /* XXX */
+           !vbmemalloc(16, reg, &dummypte, &reg)) {
+               printf("vx%d: vbmemalloc failed.\n", vi->ui_unit);
                return(0);
                return(0);
-       vp->v_fault = 0 ;
-       vp->v_vioc = V_BSY ;
-       vp->v_hdwre = V_RESET ;         /* reset interrupt */
-
+       }
+       vp = (struct vxdevice *)reg;
+       if (badaddr((caddr_t)vp, 1))
+               return (0);
+       vp->v_fault = 0;
+       vp->v_vioc = V_BSY;
+       vp->v_hdwre = V_RESET;          /* reset interrupt */
        DELAY(4000000);
        DELAY(4000000);
-       return ( vp->v_fault == VREADY);
+       if (vp->v_fault != VXF_READY)
+               return (0);
+       vs = &vx_softc[vi->ui_unit];
+#ifdef notdef
+       /*
+        * Align vioc interrupt vector base to 4 vector
+        * boundary and fitting in 8 bits (is this necessary,
+        * wish we had documentation).
+        */
+       if ((vi->ui_hd->vh_lastiv -= 3) > 0xff)
+               vi->ui_hd->vh_lastiv = 0xff;
+       vs->vs_ivec = vi->ui_hd->vh_lastiv = vi->ui_hd->vh_lastiv &~ 0x3;
+#else
+       vs->vs_ivec = 0x40+vi->ui_unit*4;
+#endif
+       br = 0x18, cvec = vs->vs_ivec;  /* XXX */
+       return (sizeof (struct vxdevice));
 }
 
 }
 
-vxattach(ui)
-       register struct vba_device *ui;
+vxattach(vi)
+       register struct vba_device *vi;
 {
 {
-       VIOCBAS[ui->ui_unit] = ui->ui_addr;
-       vxinit(ui->ui_unit,1);
+       register struct vx_softc *vs = &vx_softc[vi->ui_unit];
+
+       vs->vs_softCAR = vi->ui_flags;
+       vs->vs_addr = (struct vxdevice *)vi->ui_addr;
+       vxinit(vi->ui_unit, 1);
 }
 
 /*
  * Open a VX line.
  */
 }
 
 /*
  * Open a VX line.
  */
+/*ARGSUSED*/
 vxopen(dev, flag)
 vxopen(dev, flag)
+       dev_t dev;
+       int flag;
 {
        register struct tty *tp;        /* pointer to tty struct for port */
 {
        register struct tty *tp;        /* pointer to tty struct for port */
-       register struct vcx *xp;        /* pointer to VIOC-X info/cmd buffer */
-       register d;                     /* minor device number */
-       register long jj;
-
-
-       d = minor(dev);                 /* get minor device number */
-       if (d >= NVXPORTS)              /* validate minor device number */
-               return ENXIO;           /* set errno to indicate bad port # */
-       tp = &vx_tty[d];                /* index the tty structure for port */
-
-       xp = &vcx[d>>4];                        /* index VIOC-X info/cmd area */
-       d &= 017;
-
-       /* If we did not find a board with the correct port number on
-          it, or the entry for the VIOC-X had no ports on it, inform the
-          caller that the port does not exist. */
-       if(!( xp->v_loport <= d && d <= xp->v_hiport )  /* home? */
-        || (xp->v_hiport - xp->v_loport)==0)
-               return ENXIO;   /* bad minor device number */
-       tp->t_addr = (caddr_t)xp;       /* store address of VIOC-X info */
-       tp->t_oproc = vxstart;          /* store address of startup routine */
-       tp->t_dev = dev;                /* store major/minor device numbers */
-       d = spl8();
-       tp->t_state |= TS_WOPEN;        /* mark device as waiting for open */
-       if ((tp->t_state&TS_ISOPEN) == 0)       /* is device already open? */
-       {                               /*  no, open it */
-               ttychars(tp);           /* set default control chars */
-               if (tp->t_ispeed == 0)  /* if no default speeds set them */
-               {
-                       tp->t_ispeed = SSPEED;  /* default input baud */
-                       tp->t_ospeed = SSPEED;  /* default output baud */
-                       tp->t_flags |= (ODDP|EVENP|ECHO); /* default modes */
+       register struct vx_softc *vs;
+       register struct vba_device *vi;
+       int unit, vx, s, error = 0;
+       int vxparam();
+
+       unit = minor(dev);
+       vx = VXUNIT(unit);
+       if (vx >= NVX || (vi = vxinfo[vx])== 0 || vi->ui_alive == 0)
+               return (ENXIO);
+       vs = &vx_softc[vx];
+       tp = &vx_tty[unit];
+       unit = VXPORT(unit);
+       if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
+               return (EBUSY);
+       if (unit < vs->vs_loport || unit > vs->vs_hiport)
+               return (ENXIO);
+       tp->t_addr = (caddr_t)vs;
+       tp->t_oproc = vxstart;
+       tp->t_param = vxparam;
+       tp->t_dev = dev;
+       s = spl8();
+       if ((tp->t_state&TS_ISOPEN) == 0) {
+               tp->t_state |= TS_WOPEN;
+               ttychars(tp);
+               if (tp->t_ispeed == 0) {
+                       tp->t_iflag = TTYDEF_IFLAG;
+                       tp->t_oflag = TTYDEF_OFLAG;
+                       tp->t_lflag = TTYDEF_LFLAG;
+                       tp->t_cflag = TTYDEF_CFLAG;
+                       tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
                }
                }
-               vxparam(dev);           /* set parameters for this port */
+               vxparam(tp, &tp->t_termios);
+               ttsetwater(tp);
        }
        }
-       splx(d);
-       /* ? if already open for exclusive use open fails unless caller is 
-            root. */
-       if (tp->t_state&TS_XCLUDE && u.u_uid!=0)
-               return EBUSY;   /* device is busy, sorry */
-
-       /* wait for data carrier detect to go high */
-       d = spl8();
-       if( !vcmodem(dev,VMOD_ON) )
-               while( (tp->t_state&TS_CARR_ON) == 0 )
-                       sleep(&tp->t_canq,TTIPRI);
-       jj= (*linesw[tp->t_line].l_open)(dev,tp); /*let tty.c finish the open */
-       splx(d);        /* 1/2/85 : assures open complete */
-       return (jj);
+       vcmodem(dev, VMOD_ON);
+       while (!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) && 
+             (tp->t_state&TS_CARR_ON) == 0)
+               tp->t_state |= TS_WOPEN;
+               if ((error = tsleep((caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
+                                   ttopen, 0)) ||
+                   (error = ttclosed(tp)))
+                       break;
+       if (error == 0)
+               error = (*linesw[tp->t_line].l_open)(dev,tp);
+       splx(s);
+       return (error);
 }
 
 /*
  * Close a VX line.
  */
 }
 
 /*
  * Close a VX line.
  */
+/*ARGSUSED*/
 vxclose(dev, flag)
 vxclose(dev, flag)
-dev_t dev;
-int  flag;
+       dev_t dev;
+       int flag;
 {
        register struct tty *tp;
 {
        register struct tty *tp;
-       register d;
+       int unit, s, error = 0;
 
 
-       d = minor(dev) & 0377;
-       tp = &vx_tty[d];
-       d = spl8();
+       unit = minor(dev);
+       tp = &vx_tty[unit];
+       s = spl8();
        (*linesw[tp->t_line].l_close)(tp);
        (*linesw[tp->t_line].l_close)(tp);
-       if ((tp->t_state&TS_ISOPEN) && (tp->t_state&TS_HUPCLS))
-               if( !vcmodem(dev,VMOD_OFF) )
-                       tp->t_state &= ~TS_CARR_ON;
+       if (tp->t_cflag & HUPCL || (tp->t_state & TS_ISOPEN) == 0)
+               vcmodem(dev, VMOD_OFF);
        /* wait for the last response */
        /* wait for the last response */
-       while(tp->t_state & TS_FLUSH)
-               sleep( (caddr_t)&tp->t_state, TTOPRI ) ;
-       ttyclose(tp);   /* let tty.c finish the close */
-       splx(d);
+       while (tp->t_state&TS_FLUSH && error == 0)
+               error = tsleep((caddr_t)&tp->t_state, TTOPRI | PCATCH,
+                   ttclos, 0);
+       splx(s);
+       if (error)
+               return (error);
+       return (ttyclose(tp));
 }
 
 /*
  * Read from a VX line.
  */
 }
 
 /*
  * Read from a VX line.
  */
-vxread(dev, uio)
+vxread(dev, uio, flag)
        dev_t dev;
        struct uio *uio;
 {
        dev_t dev;
        struct uio *uio;
 {
-       register struct tty *tp = &vx_tty[minor(dev) & 0377];
-       return (*linesw[tp->t_line].l_read)(tp, uio);
+       struct tty *tp = &vx_tty[minor(dev)];
+
+       return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
 }
 
 /*
  * write on a VX line
  */
 }
 
 /*
  * write on a VX line
  */
-vxwrite(dev, uio)
+vxwrite(dev, uio, flag)
        dev_t dev;
        struct uio *uio;
 {
        dev_t dev;
        struct uio *uio;
 {
-       register struct tty *tp = &vx_tty[minor(dev) & 0377];
-       return (*linesw[tp->t_line].l_write)(tp, uio);
+       register struct tty *tp = &vx_tty[minor(dev)];
+
+       return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
 }
 
 /*
  * VIOCX unsolicited interrupt.
  */
 }
 
 /*
  * VIOCX unsolicited interrupt.
  */
-vxrint(n)
-register n;                            /* mux number */
+vxrint(vx)
+       register vx;
 {
 {
-       register struct tty *tp;
-       register struct vcx *xp;
-       register short *sp;
-       register struct vblok *kp;
-       register int i, c;
-       short *savsilo;
-       struct silo {
-               char    data;
-               char    port;
-       };
-
-       kp = VBAS(n);
-       xp = &vcx[n];
-       switch(kp->v_uqual&037) {
+       register struct tty *tp, *tp0;
+       register struct vxdevice *addr;
+       register struct vx_softc *vs;
+       struct vba_device *vi;
+       register int nc, c;
+       register struct silo {
+               u_char  data, port;
+       } *sp;
+       short *osp;
+       int overrun = 0;
+
+       vi = vxinfo[vx];
+       if (vi == 0 || vi->ui_alive == 0)
+               return;
+       addr = (struct vxdevice *)vi->ui_addr;
+       switch (addr->v_uqual&037) {
        case 0:
                break;
        case 2:
        case 0:
                break;
        case 2:
-               printf(" ERR NBR %x\n",kp->v_ustat);
-               vpanic("vc: VC PROC ERR");
-               vxstreset(n);
-               return(0);
+               if (addr->v_ustat == VP_SILO_OFLOW)
+                       log(LOG_ERR, "vx%d: input silo overflow\n", vx);
+               else {
+                       printf("vx%d: vc proc err, ustat %x\n",
+                           vx, addr->v_ustat);
+                       vxstreset(vx);
+               }
+               return;
        case 3:
        case 3:
-               vcmintr(n);
-               return(1);
+               vcmintr(vx);
+               return;
        case 4:
        case 4:
-               return(1);
+               return;
        default:
        default:
-               printf(" ERR NBR %x\n",kp->v_uqual);
-               vpanic("vc: VC UQUAL ERR");
-               vxstreset(n);
-               return(0);
+               printf("vx%d: vc uqual err, uqual %x\n", vx, addr->v_uqual);
+               vxstreset(vx);
+               return;
        }
        }
-       if(xp->v_vers == V_NEW) {
-               register short *aa ;
-               aa = (short *)kp->v_usdata;
-               sp = (short *)(*aa  + (char *)kp) ;
-       } else {
-               c = kp->v_usdata[0] << 6;
-               sp = (short *)((char *)kp + SILOBAS + c);
-       }
-nextsilo:
-       i = *(savsilo = sp);
-       if (i == 0) return(1);
-       if(xp->v_vers == V_NEW)
-               if( i > xp->v_silosiz ) {
-                       printf("vx: %d exceeds silo size\n",i) ;
-                       i = xp->v_silosiz;
-               }
-       for(sp++;i > 0;i--,sp++) {
-               c = ((struct silo *)sp)->port & 017;
-               tp = &vx_tty[c+n*16];
-               if(xp->v_loport > c || c > xp->v_hiport)
-                       continue;       /* port out of bounds */
-               if( (tp->t_state & TS_ISOPEN) == 0) {
+       vs = &vx_softc[vx];
+       if (vs->vs_vers == VXV_NEW)
+               sp = (struct silo *)((caddr_t)addr + *(short *)addr->v_usdata);
+       else
+               sp = (struct silo *)((caddr_t)addr+VX_SILO+(addr->v_usdata[0]<<6));
+       nc = *(osp = (short *)sp);
+       if (nc == 0)
+               return;
+       if (vs->vs_vers == VXV_NEW && nc > vs->vs_silosiz) {
+               printf("vx%d: %d exceeds silo size\n", nc);
+               nc = vs->vs_silosiz;
+       }
+       tp0 = &vx_tty[vx*16];
+       sp = (struct silo *)(((short *)sp)+1);
+       for (; nc > 0; nc--, sp = (struct silo *)(((short *)sp)+1)) {
+               c = sp->port & 017;
+               if (vs->vs_loport > c || c > vs->vs_hiport)
+                       continue;
+               tp = tp0 + c;
+               if( (tp->t_state&TS_ISOPEN) == 0) {
                        wakeup((caddr_t)&tp->t_rawq);
                        continue;
                }
                        wakeup((caddr_t)&tp->t_rawq);
                        continue;
                }
-               c = ((struct silo *)sp)->data;
-               switch(((struct silo *)sp)->port&(PERROR|FERROR)) {
-               case PERROR:
-               case PERROR|FERROR:
-                       if( (tp->t_flags&(EVENP|ODDP)) == EVENP
-                       || (tp->t_flags & (EVENP|ODDP)) == ODDP )
-                               continue;
-                       if(!(((struct silo *)sp)->port&FERROR))
-                               break;
-               case FERROR:
-                       if(tp->t_flags & RAW) c = 0;
-                       else c = tp->t_intrc;
+               c = sp->data&((tp->t_cflag&CSIZE)==CS8 ? 0xff : 0x7f);
+               if ((sp->port&VX_RO) == VX_RO && !overrun) {
+                       log(LOG_ERR, "vx%d: receiver overrun\n", vi->ui_unit);
+                       overrun = 1;
+                       continue;
                }
                }
+               if (sp->port&VX_PE)
+                       c |= TTY_PE;
+               if (sp->port&VX_FE) 
+                       c |= TTY_FE;
                (*linesw[tp->t_line].l_rint)(c, tp);
        }
                (*linesw[tp->t_line].l_rint)(c, tp);
        }
-       *savsilo = 0;
-       return(1);
+       *osp = 0;
 }
 
 /*
 }
 
 /*
- * stty/gtty for VX
+ * Ioctl for VX.
  */
 vxioctl(dev, cmd, data, flag)
  */
 vxioctl(dev, cmd, data, flag)
-int    dev;                    /* major, minor device numbers */
-int    cmd;                    /* command */
-caddr_t        data;
-int    flag;
+       dev_t dev;
+       caddr_t data;
 {
 {
-       register struct tty     *tp;
-       register error;
+       register struct tty *tp;
+       int error;
 
 
-       tp = &vx_tty[minor(dev) & 0377];
+       tp = &vx_tty[minor(dev)];
        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
-       if (error == 0)
-               return error;
-       if((error = ttioctl(tp, cmd, data, flag)) >= 0)
-       {
-               if (cmd==TIOCSETP||cmd==TIOCSETN)
-                       vxparam(dev);
-               return error;
-       } else
-               return ENOTTY;
+       if (error >= 0)
+               return (error);
+       error = ttioctl(tp, cmd, data, flag);
+       if (error >= 0) 
+               return (error);
+       return (ENOTTY);
 }
 
 }
 
-
-vxparam(dev)
-dev_t  dev;
+vxparam(tp, t)
+       struct tty *tp;
+       struct termios *t;
 {
 {
-       vxcparam(dev, 1);
+
+       return (vxcparam(tp, t, 1));
 }
 
 /*
  * Set parameters from open or stty into the VX hardware
  * registers.
  */
 }
 
 /*
  * Set parameters from open or stty into the VX hardware
  * registers.
  */
-vxcparam(dev, wait)
-dev_t  dev;                    /* major, minor device numbers */
-int wait;                      /* nonzero if we should wait for finish */
-{
-       register struct tty     *tp;
-       register struct vcx     *xp;
-       register struct vxcmd   *cp;
-       register s;
-
-       tp = &vx_tty[minor(dev)];       /* pointer to tty structure for port */
-       xp = (struct vcx *)tp->t_addr;  /* pointer to VIOCX info/cmd buffer */
-       cp = vobtain(xp);
+vxcparam(tp, t, wait)
+       struct tty *tp;
+       struct termios *t;
+       int wait;
+{
+       register struct vx_softc *vs;
+       register struct vxcmd *cp;
+       int s, error = 0;
+       int speedcode = ttspeedtab(t->c_ospeed, vxspeedtab);
+
+       if (speedcode < 0 || (t->c_ispeed != t->c_ospeed && t->c_ispeed))
+               return (EINVAL);
+       vs = (struct vx_softc *)tp->t_addr;
+       cp = vobtain(vs);
        s = spl8();
        s = spl8();
-       cp->cmd = LPARAX;               /* set command to "load parameters" */
-       cp->par[1] = minor(dev)&017;    /* port number */
-
-       cp->par[2] = (tp->t_flags&RAW)? 0 : tp->t_startc;       /* XON char */
-       cp->par[3] = (tp->t_flags&RAW)? 0 : tp->t_stopc;        /* XOFF char */
-
-       if(tp->t_flags&(RAW|LITOUT) ||
-         (tp->t_flags&(EVENP|ODDP)) == (EVENP|ODDP)) {
-               cp->par[4] = 0xc0;      /* 8 bits of data */
-               cp->par[7] = 0;         /* no parity */
-       } else {
-               cp->par[4] = 0x40;      /* 7 bits of data */
-               if((tp->t_flags&(EVENP|ODDP)) == ODDP)
-                       cp->par[7] = 1;         /* odd parity */
-               else if((tp->t_flags&(EVENP|ODDP)) == EVENP)
-                       cp->par[7] = 3;         /* even parity */
+       /*
+        * Construct ``load parameters'' command block
+        * to setup baud rates, xon-xoff chars, parity,
+        * and stop bits for the specified port.
+        */
+       cp->cmd = VXC_LPARAX;
+       cp->par[1] = VXPORT(minor(tp->t_dev));
+       /*
+        * note: if the hardware does flow control, ^V doesn't work
+        * to escape ^S
+        */
+       if (t->c_iflag&IXON) {
+               if (t->c_cc[VSTART] == _POSIX_VDISABLE)
+                       cp->par[2] = 0;
+               else
+                       cp->par[2] = t->c_cc[VSTART];
+               if (t->c_cc[VSTOP] == _POSIX_VDISABLE)
+                       cp->par[3] = 0;
                else
                else
-                       cp->par[7] = 0;         /* no parity */
+                       cp->par[3] = t->c_cc[VSTOP];
+       } else 
+               cp->par[2] = cp->par[3] = 0;
+#ifdef notnow
+       switch (t->c_cflag & CSIZE) {   /* XXX */
+       case CS8:
+#endif
+               cp->par[4] = BITS8;             /* 8 bits of data */
+#ifdef notnow
+               break;
+       case CS7:
+               cp->par[4] = BITS7;             /* 7 bits of data */
+               break;
+       case CS6:
+               cp->par[4] = BITS6;             /* 6 bits of data */
+               break;
+       case CS5:
+               cp->par[4] = BITS5;             /* 5 bits of data */
+               break;
+       }
+       if ((t->c_cflag & PARENB) == 0)         /* XXX */
+#endif
+               cp->par[7] = VNOPARITY;         /* no parity */
+#ifdef notnow
+       else if (t->c_cflag&PARODD)
+               cp->par[7] = VODDP;     /* odd parity */
+       else
+               cp->par[7] = VEVENP;    /* even parity */
+#endif
+       cp->par[5] = (t->c_cflag&CSTOPB) ? VSTOP2 : VSTOP1;
+       cp->par[6] = speedcode;
+       if (vcmd((int)vs->vs_nbr, (caddr_t)&cp->cmd) && wait)
+               error = tsleep((caddr_t)cp, TTIPRI | PCATCH, ttyout, 0);
+       if ((t->c_ospeed)==0) {
+               tp->t_cflag |= HUPCL;
+               vcmodem(tp->t_dev, VMOD_OFF);
        }
        }
-       cp->par[5] = 0x4;                       /* 1 stop bit */
-       cp->par[6] = tp->t_ospeed;
-
-       if (vcmd(xp->v_nbr, &cp->cmd) && wait)
-               sleep(cp,TTIPRI);
        splx(s);
        splx(s);
+       return (error);
 }
 
 /*
 }
 
 /*
@@ -361,112 +497,79 @@ int wait;                        /* nonzero if we should wait for finish */
  * For transmission, restart output to any active port.
  * For all other commands, just clean up.
  */
  * For transmission, restart output to any active port.
  * For all other commands, just clean up.
  */
-vxxint(n,cp)
-register int n;                        /* VIOC number */
-register struct vxcmd  *cp;    /* command structure */
-{
-       register struct vxmit   *vp, *pvp;
-       register struct tty     *tp;
-       register struct vcx     *xp;
-       register struct tty     *hp;
-
-       xp = &vcx[n];
-       cp = (struct vxcmd *)( (long *)cp - 1);
-#if NVBSC > 0
-       switch(cp->cmd) {
-       case MDMCTL1: case HUNTMD1: case LPARAX1:
-               vrelease(xp, cp);
-               wakeup(cp);
-               return;
-       }
-#endif
-       switch(cp->cmd&0xff00) {
-       case LIDENT:    /* initialization complete */
-               if (xp->v_state & V_RESETTING) {
-                       vxfnreset(n,cp);
-                       vinthandl(n,((V_BSY | RSPquals) << 8) | V_INTR);
+vxxint(vx, cp)
+       register int vx;
+       register struct vxcmd *cp;
+{
+       register struct vxmit *vp;
+       register struct tty *tp, *tp0;
+       register struct vx_softc *vs;
+
+       vs = &vx_softc[vx];
+       cp = (struct vxcmd *)((long *)cp-1);
+
+       switch (cp->cmd&0xff00) {
+
+       case VXC_LIDENT:        /* initialization complete */
+               if (vs->vs_state == VXS_RESET) {
+                       vxfnreset(vx, cp);
+                       vinthandl(vx, ((V_BSY|RSPquals) << 8)|V_INTR);
                }
                cp->cmd++;
                return;
                }
                cp->cmd++;
                return;
-       case XMITDTA: case XMITIMM:
+
+       case VXC_XMITDTA:
+       case VXC_XMITIMM:
                break;
                break;
-       case LPARAX:
-               wakeup(cp);
-       default:        /* MDMCTL or FDTATOX */
-               vrelease(xp, cp);
-               if (xp->v_state & V_RESETTING) {
-                       vinthandl(n,((V_BSY | RSPquals) << 8) | V_INTR);
-               }
+
+       case VXC_LPARAX:
+               wakeup((caddr_t)cp);
+               /* fall thru... */
+       default:        /* VXC_MDMCTL or VXC_FDTATOX */
+               vrelease(vs, cp);
+               if (vs->vs_state == VXS_RESET)
+                       vinthandl(vx, ((V_BSY|RSPquals) << 8)|V_INTR);
                return;
        }
                return;
        }
-       for(vp = (struct vxmit *)(cp->par + (cp->cmd & 07)*sizvxmit);
-           vp >= (struct vxmit *)cp->par;
-           vp = (struct vxmit *) ((char *)vp - sizvxmit) )
-       {
-               tp = &vx_tty[(vp->line & 017)+n*16];
-/* cjk buffer bug */
-#if NVBSC > 0
-                                       /* bsc change */
-               if (tp->t_line == LDISP) {
-                       vrelease(xp, cp);
-                       bsctxd((vp->line & 017));
-                       return ;
-               }
-                                       /* End of bsc change */
-#endif
-/* cjk */
-               pvp = vp;
+       tp0 = &vx_tty[vx*16];
+       vp = (struct vxmit *)(cp->par + (cp->cmd & 07)*sizeof (struct vxmit));
+       for (; vp >= (struct vxmit *)cp->par; vp--) {
+               tp = tp0 + (vp->line & 017);
                tp->t_state &= ~TS_BUSY;
                tp->t_state &= ~TS_BUSY;
-               if(tp->t_state & TS_FLUSH) {
+               if (tp->t_state & TS_FLUSH) {
                        tp->t_state &= ~TS_FLUSH;
                        tp->t_state &= ~TS_FLUSH;
-                       wakeup( (caddr_t)&tp->t_state ) ;
-               }
-               else
+                       wakeup((caddr_t)&tp->t_state);
+               } else
                        ndflush(&tp->t_outq, vp->bcount+1);
        }
                        ndflush(&tp->t_outq, vp->bcount+1);
        }
-       xp->v_xmtcnt--;
-       vrelease(xp,cp);
-       if(xp->v_vers == V_NEW) {
-               vp = pvp;
-               xp->v_actport[(vp->line & 017) - xp->v_loport] |= 1 ;
-               if(vxstart(tp) && (cp = nextcmd(xp)) != NULL)
-               {
-                       xp->v_xmtcnt++;
-                       vcmd(n, &cp->cmd);
-                       return ;
+       vrelease(vs, cp);
+       if (vs->vs_vers == VXV_NEW)
+               (*linesw[tp->t_line].l_start)(tp);
+       else {
+               tp0 = &vx_tty[vx*16 + vs->vs_hiport];
+               for(tp = &vx_tty[vx*16 + vs->vs_loport]; tp <= tp0; tp++)
+                       (*linesw[tp->t_line].l_start)(tp);
+               if ((cp = nextcmd(vs)) != NULL) {       /* command to send? */
+                       vs->vs_xmtcnt++;
+                       (void) vcmd(vx, (caddr_t)&cp->cmd);
                }
                }
-               xp->v_actport[(vp->line & 017) - xp->v_loport] = 0 ;
-               return ;
-       }
-       xp->v_actflg = 1;
-       hp = &vx_tty[xp->v_hiport+n*16];
-       for(tp = &vx_tty[xp->v_loport+n*16];tp <= hp;tp++)
-               if(vxstart(tp) && (cp = nextcmd(xp)) != NULL)
-               {
-                       xp->v_xmtcnt++;
-                       vcmd(n, &cp->cmd);
-               }
-       if( (cp = nextcmd(xp)) != NULL )                /* command to send ? */
-       {
-               xp->v_xmtcnt++;
-               vcmd(n,&cp->cmd);
        }
        }
-       xp->v_actflg = 0;
+       vs->vs_xmtcnt--;
 }
 
 /*
  * Force out partial XMIT command after timeout
  */
 }
 
 /*
  * Force out partial XMIT command after timeout
  */
-vxforce(xp)
-register struct vcx    *xp;
+vxforce(vs)
+       register struct vx_softc *vs;
 {
 {
-       register struct vxcmd   *cp;
-       register int s;
+       register struct vxcmd *cp;
+       int s;
 
        s = spl8();
 
        s = spl8();
-       if((cp = nextcmd(xp)) != NULL) {
-               xp->v_xmtcnt++;
-               vcmd(xp->v_nbr, &cp->cmd);
+       if ((cp = nextcmd(vs)) != NULL) {
+               vs->vs_xmtcnt++;
+               (void) vcmd((int)vs->vs_nbr, (caddr_t)&cp->cmd);
        }
        splx(s);
 }
        }
        splx(s);
 }
@@ -475,19 +578,17 @@ register struct vcx       *xp;
  * Start (restart) transmission on the given VX line.
  */
 vxstart(tp)
  * Start (restart) transmission on the given VX line.
  */
 vxstart(tp)
-register struct tty *tp;
+       register struct tty *tp;
 {
 {
-       register short nch;
-       register struct vcx     *xp;
-       register char *outb;
-       register full = 0;
-       int k, s, port;
+       register short n;
+       register struct vx_softc *vs;
+       int s, port;
 
        s = spl8();
 
        s = spl8();
-       port = minor(tp->t_dev) & 017;
-       xp = (struct vcx *)tp->t_addr;
-       if (!(tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))) {
-               if (tp->t_outq.c_cc<=TTLOWAT(tp)) {
+       port = VXPORT(minor(tp->t_dev));
+       vs = (struct vx_softc *)tp->t_addr;
+       if ((tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) == 0) {
+               if (tp->t_outq.c_cc <= tp->t_lowat) {
                        if (tp->t_state&TS_ASLEEP) {
                                tp->t_state &= ~TS_ASLEEP;
                                wakeup((caddr_t)&tp->t_outq);
                        if (tp->t_state&TS_ASLEEP) {
                                tp->t_state &= ~TS_ASLEEP;
                                wakeup((caddr_t)&tp->t_outq);
@@ -498,301 +599,801 @@ register struct tty *tp;
                                tp->t_state &= ~TS_WCOLL;
                        }
                }
                                tp->t_state &= ~TS_WCOLL;
                        }
                }
-               if(tp->t_outq.c_cc == 0) {
+               if (tp->t_outq.c_cc == 0) {
                        splx(s);
                        splx(s);
-                       return(0);
+                       return;
                }
                }
-#ifdef VXPERF
-       scope_out(3);
-#endif VXPERF
-               if(!(tp->t_flags&(RAW|LITOUT)))  
-                       full = 0200;
-               if((nch = ndqb(&tp->t_outq, full)) == 0)   {
-                       if(full) {
-                               nch = getc(&tp->t_outq);
-                               timeout(ttrstrt, (caddr_t)tp, (nch&0177) +6);
+               scope_out(3);
+               if (1 || !(tp->t_oflag&OPOST))  /* XXX */
+                       n = ndqb(&tp->t_outq, 0);
+               else {
+                       n = ndqb(&tp->t_outq, 0200);
+                       if (n == 0) {
+                               n = getc(&tp->t_outq);
+                               timeout(ttrstrt, (caddr_t)tp, (n&0177)+6);
                                tp->t_state |= TS_TIMEOUT;
                                tp->t_state |= TS_TIMEOUT;
-                               full = 0;
+                               n = 0;
                        }
                        }
-               } else {
-                       outb = (char *)tp->t_outq.c_cf;
+               }
+               if (n) {
                        tp->t_state |= TS_BUSY;
                        tp->t_state |= TS_BUSY;
-                       if(xp->v_vers == V_NEW)
-                               k = xp->v_actport[port - xp->v_loport] ;
-                       else
-                               k = xp->v_actflg ;
-
-                       full = vsetq(xp, port, outb, nch);
-
-                       if( (k&1) == 0 ) {      /* not called from vxxint */
-                               if(full || xp->v_xmtcnt == 0) {
-                                       outb = (char *)(&nextcmd(xp)->cmd);
-                                       xp->v_xmtcnt++;
-                                       vcmd(xp->v_nbr, outb );
-                               } else
-                                       timeout(vxforce,xp,3);
-                       }
+                       vsetq(vs, port, (char *)tp->t_outq.c_cf, n);
                }
        }
        splx(s);
                }
        }
        splx(s);
-       return(full);   /* indicate if max commands or not */
 }
 
 /*
  * Stop output on a line.
  */
 vxstop(tp)
 }
 
 /*
  * Stop output on a line.
  */
 vxstop(tp)
-register struct tty *tp;
+       register struct tty *tp;
 {
 {
-       register  s;
+       int s;
 
        s = spl8();
 
        s = spl8();
-       if (tp->t_state & TS_BUSY) {
-               if ((tp->t_state&TS_TTSTOP)==0) {
+       if (tp->t_state&TS_BUSY)
+               if ((tp->t_state&TS_TTSTOP) == 0)
                        tp->t_state |= TS_FLUSH;
                        tp->t_state |= TS_FLUSH;
-               }
-       }
        splx(s);
 }
 
        splx(s);
 }
 
+static int vxbbno = -1;
 /*
  * VIOCX Initialization.  Makes free lists of command buffers.
  * Resets all viocx's.  Issues a LIDENT command to each
 /*
  * VIOCX Initialization.  Makes free lists of command buffers.
  * Resets all viocx's.  Issues a LIDENT command to each
- * viocx which establishes interrupt vectors and logical
- * port numbers
+ * viocx to establish interrupt vectors and logical port numbers.
  */
  */
-vxinit(i,wait) 
-register int   i;
-long wait;
-{
-       register struct vcx     *xp;    /* ptr to VIOC-X info/cmd buffer */
-       register struct vblok   *kp;    /* pointer to VIOC-X control block */
-       register struct vxcmd   *cp;    /* pointer to a command buffer */
-       register char   *resp;          /* pointer to response buffer */
-       register int    j;
-       register struct vcmds   *cpp;
-       char type;
-       register struct bsc     *bp;    /* bsc change */
-       extern   struct bsc     bsc[];
-
-
-       kp = VBAS(i);           /* get base adr of cntl blok for VIOC */
-
-       xp = &vcx[i];           /* index info/command buffers */
-       cpp = &v_cmds[i];
-       type = kp->v_ident;
-       vxtype[i] =  0;         /* Type is Viox-x */
-       switch(type) {
-       case VIOCX:
-               {
-               xp->v_vers = V_OLD ;
-               /* set DCD for printer ports */
-               for(j = 0;j < 16;j++)
-                       if (kp->v_portyp[j] == 4 )
-                               kp->v_dcd |= 1 << j ;
-               }
-               break ;
-       case NWVIOCX:
-               {
-               xp->v_vers = V_NEW ;
-               xp->v_silosiz = kp->v_maxsilo ;
-               /* set DCD for printer ports */
-               for(j = 0;j < 16;j++)
-                       if (kp->v_portyp[j] == 4 )
-                               kp->v_dcd |= 1 << j ;
-               }
-               break ;
-       case PVIOCX:
-               xp->v_vers = V_OLD ;
-               break ;
-       case NPVIOCX:
-               xp->v_vers = V_NEW ;
-               xp->v_silosiz = kp->v_maxsilo ;
-               break ;
-#if NVBSC > 0
-       case VIOCB:     /* old f/w, Bisync board */
-               printf("%X: %x%x OLD VIOC-B, ",
-                                       (long)kp, (int)kp->v_ident,
-                                       (int)kp->v_fault);
-               xp->v_vers = V_OLD ;
-               /* save device specific info */
-               for(bp = &bsc[0]; bp <= &bsc[NBSC]; bp++)
-                       bp->b_devregs = (caddr_t)xp ;
-               printf("%d BSC Ports initialized.\n",NBSC);
-               break ;
-
-       case NWVIOCB:   /* new f/w, Bisync board */
-               printf("%X: %x%x 16K VIOC-B, ",
-                                       (long)kp, (int)kp->v_ident,
-                                       (int)kp->v_fault);
-               xp->v_vers = V_NEW ;
-               xp->v_silosiz = kp->v_maxsilo ;
-               /* save device specific info */
-               for(bp = &bsc[0]; bp <= &bsc[NBSC]; bp++)
-                       bp->b_devregs = (caddr_t)xp ;
-               printf("%d BSC Ports initialized.\n",NBSC);
-               if(CBSIZE > kp->v_maxxmt)
-                       printf("vxinit: Warning CBSIZE > maxxmt\n") ;
-               break ;
-#endif
-       case VBOPID:            /* VIOC-BOP */
-               vxbbno++;
-               vxtype[i] = 1;
-               vxbopno[i] = vxbbno;
-               printf("VIOC-BOP no. %d at %lx\n",vxbopno[i],VIOCBAS[i]);
+vxinit(vx, wait)
+       register int vx;
+       int wait;
+{
+       register struct vx_softc *vs;
+       register struct vxdevice *addr;
+       register struct vxcmd *cp;
+       register char *resp;
+       register int j;
+       char type, *typestring;
+
+       vs = &vx_softc[vx];
+       addr = vs->vs_addr;
+       type = addr->v_ident;
+       vs->vs_vers = (type&VXT_NEW) ? VXV_NEW : VXV_OLD;
+       if (vs->vs_vers == VXV_NEW)
+               vs->vs_silosiz = addr->v_maxsilo;
+       switch (type) {
+
+       case VXT_VIOCX:
+       case VXT_VIOCX|VXT_NEW:
+               typestring = "VIOC-X";
+               /* set soft carrier for printer ports */
+               for (j = 0; j < 16; j++)
+                       if (vs->vs_softCAR & (1 << j) ||
+                           addr->v_portyp[j] == VXT_PARALLEL) {
+                               vs->vs_softCAR |= 1 << j;
+                               addr->v_dcd |= 1 << j;
+                       }
+               break;
+
+       case VXT_PVIOCX:
+       case VXT_PVIOCX|VXT_NEW:
+               typestring = "VIOC-X (old connector panel)";
+               break;
+       case VXT_VIOCBOP:               /* VIOC-BOP */
+               vs->vs_type = 1;
+               vs->vs_bop = ++vxbbno;
+               printf("VIOC-BOP no. %d at %x\n", vs->vs_bop, addr);
+               goto unsup;
        default:
        default:
-               return ;        /* Not a viocx type */
+               printf("vx%d: unknown type %x\n", vx, type);
+       unsup:
+               vxinfo[vx]->ui_alive = 0;
+               return;
        }
        }
-       xp->v_nbr = -1;         /* no number for it yet */
-       xp->v_maxcmd = xp->v_vers == V_NEW ? 24 : 4;
-
-       for(j=0; j<NVCXBUFS; j++)       /* init all cmd buffers */
-       {
-               cp = &xp->vx_lst[j];    /* index a buffer */
-               cp->c_fwd = &xp->vx_lst[j+1];   /* point to next buf */
+       vs->vs_nbr = vx;                /* assign board number */
+       vs->vs_maxcmd = (vs->vs_vers == VXV_NEW) ? 24 : 4;
+       /*
+        * Initialize all cmd buffers by linking them
+        * into a free list.
+        */
+       for (j = 0; j < NVCXBUFS; j++) {
+               cp = &vs->vs_lst[j];
+               cp->c_fwd = &vs->vs_lst[j+1];
        }
        }
-       xp->vx_avail = &xp->vx_lst[0];  /* set idx to 1st free buf */
+       vs->vs_avail = &vs->vs_lst[0];  /* set idx to 1st free buf */
        cp->c_fwd = (struct vxcmd *)0;  /* mark last buf in free list */
 
        cp->c_fwd = (struct vxcmd *)0;  /* mark last buf in free list */
 
-       cp = vobtain(xp);       /* grap the control block */
-       cp->cmd = LIDENT;       /* set command type */
-       cp->par[0] = i * 4 + VCVECT;    /* ack vector */
-       cp->par[1] = cp->par[0] + 1;    /* cmd resp vector */
-       cp->par[3] = cp->par[0] + 2;    /* unsol intr vector */
-       cp->par[4] = 15;        /* max ports, no longer used */
-       cp->par[5] = 0;         /* set 1st port number */
-       vcmd(i, &cp->cmd);      /* initialize the VIOC-X */
+       /*
+        * Establish the interrupt vectors and define the port numbers.
+        */
+       cp = vobtain(vs);
+       cp->cmd = VXC_LIDENT;
+       cp->par[0] = vs->vs_ivec;       /* ack vector */
+       cp->par[1] = cp->par[0]+1;      /* cmd resp vector */
+       cp->par[3] = cp->par[0]+2;      /* unsol intr vector */
+       cp->par[4] = 15;                /* max ports, no longer used */
+       cp->par[5] = 0;                 /* set 1st port number */
+       (void) vcmd(vx, (caddr_t)&cp->cmd);
+       if (!wait)
+               return;
 
 
-       if (!wait) return;
-       while(cp->cmd == LIDENT);    /* wait for command completion */
+       for (j = 0; cp->cmd == VXC_LIDENT && j < 4000000; j++)
+               ;
+       if (j >= 4000000)
+               printf("vx%d: didn't respond to LIDENT\n", vx); 
 
        /* calculate address of response buffer */
 
        /* calculate address of response buffer */
-       resp = (char *)kp;
-       resp += kp->v_rspoff & 0x3FFF;
-       if(resp[0] != 0 && (resp[0]&0177) != 3) /* did init work? */
-       {
-               vrelease(xp,cp);        /* init failed */
-               return;                 /* try next VIOC-X */
+       resp = (char *)addr + (addr->v_rspoff&0x3fff);
+       if (resp[0] != 0 && (resp[0]&0177) != 3) {
+               vrelease(vs, cp);       /* init failed */
+               return;
        }
        }
-
-       xp->v_loport = cp->par[5];      /* save low port number */
-       xp->v_hiport = cp->par[7];/* VIOC knows high port numbr */
-       vrelease(xp,cp);        /* done with this control block */
-       xp->v_nbr = i;          /* assign VIOC-X board number */
+       vs->vs_loport = cp->par[5];
+       vs->vs_hiport = cp->par[7];
+       printf("vx%d: %s%s, ports %d-%d\n", vx,
+           (vs->vs_vers == VXV_NEW) ? "" : "old ", typestring,
+           vs->vs_loport, vs->vs_hiport);
+       vrelease(vs, cp);
 }
 
 /*
  * Obtain a command buffer
  */
 }
 
 /*
  * Obtain a command buffer
  */
-struct vxcmd *
-vobtain(xp)
-register struct        vcx     *xp;
+struct vxcmd *
+vobtain(vs)
+       register struct vx_softc *vs;
 {
 {
-
-       register struct vxcmd   *p;
-       register s;
+       register struct vxcmd *p;
+       int s;
 
        s = spl8();
 
        s = spl8();
-       p = xp->vx_avail;
-       if(p == (struct vxcmd *)0) {
+       p = vs->vs_avail;
+       if (p == (struct vxcmd *)0) {
 #ifdef VX_DEBUG
 #ifdef VX_DEBUG
-               if (vxintr4 & VXNOBUF) vxintr4 &= ~VXNOBUF;
+               if (vxintr4&VXNOBUF)
+                       vxintr4 &= ~VXNOBUF;
 #endif
 #endif
-               vpanic("vx: no buffs");
-               vxstreset(xp - vcx);
+               printf("vx%d: no buffers\n", vs->vs_nbr);
+               vxstreset(vs->vs_nbr);
                splx(s);
                splx(s);
-               return(vobtain(xp));
+               return (vobtain(vs));
        }
        }
-       xp->vx_avail = (xp->vx_avail)->c_fwd;
+       vs->vs_avail = p->c_fwd;
        splx(s);
        splx(s);
-       return(struct vxcmd *)p);
+       return ((struct vxcmd *)p);
 }
 
 /*
  * Release a command buffer
  */
 }
 
 /*
  * Release a command buffer
  */
-vrelease(xp,cp)
-register struct        vcx     *xp;
-register struct        vxcmd   *cp;
+vrelease(vs, cp)
+       register struct vx_softc *vs;
+       register struct vxcmd *cp;
 {
 {
-
-       register s;
+       int s;
 
 #ifdef VX_DEBUG
 
 #ifdef VX_DEBUG
-       if (vxintr4 & VXNOBUF) return;
+       if (vxintr4&VXNOBUF)
+               return;
 #endif
        s = spl8();
 #endif
        s = spl8();
-       cp->c_fwd = xp->vx_avail;
-       xp->vx_avail = cp;
+       cp->c_fwd = vs->vs_avail;
+       vs->vs_avail = cp;
        splx(s);
 }
 
        splx(s);
 }
 
+struct vxcmd *
+nextcmd(vs)
+       register struct vx_softc *vs;
+{
+       register struct vxcmd *cp;
+       int s;
+
+       s = spl8();
+       cp = vs->vs_build;
+       vs->vs_build = (struct vxcmd *)0;
+       splx(s);
+       return (cp);
+}
+
 /*
 /*
- * vxcmd - 
- *
+ * Assemble transmits into a multiple command;
+ * up to 8 transmits to 8 lines can be assembled together
+ * (on PVIOCX only).
+ */
+vsetq(vs, line, addr, n)
+       register struct vx_softc *vs;
+       caddr_t addr;
+{
+       register struct vxcmd *cp;
+       register struct vxmit *mp;
+
+       /*
+        * Grab a new command buffer or append
+        * to the current one being built.
+        */
+       cp = vs->vs_build;
+       if (cp == (struct vxcmd *)0) {
+               cp = vobtain(vs);
+               vs->vs_build = cp;
+               cp->cmd = VXC_XMITDTA;
+       } else {
+               if ((cp->cmd & 07) == 07 || vs->vs_vers == VXV_NEW) {
+                       printf("vx%d: setq overflow\n", vs-vx_softc);
+                       vxstreset((int)vs->vs_nbr);
+                       return;
+               }
+               cp->cmd++;
+       }
+       /*
+        * Select the next vxmit buffer and copy the
+        * characters into the buffer (if there's room
+        * and the device supports ``immediate mode'',
+        * or store an indirect pointer to the data.
+        */
+       mp = (struct vxmit *)(cp->par + (cp->cmd & 07)*sizeof (struct vxmit));
+       mp->bcount = n-1;
+       mp->line = line;
+       if (vs->vs_vers == VXV_NEW && n <= sizeof (mp->ostream)) {
+               cp->cmd = VXC_XMITIMM;
+               bcopy(addr, mp->ostream, (unsigned)n);
+       } else {
+               /* get system address of clist block */
+               addr = (caddr_t)vtoph((struct proc *)0, (unsigned)addr);
+               bcopy((caddr_t)&addr, mp->ostream, sizeof (addr));
+       }
+       /*
+        * We send the data immediately if a VIOCX,
+        * the command buffer is full, or if we've nothing
+        * currently outstanding.  If we don't send it,
+        * set a timeout to force the data to be sent soon.
+        */
+       if (vs->vs_vers == VXV_NEW || (cp->cmd & 07) == 7 ||
+           vs->vs_xmtcnt == 0) {
+               vs->vs_xmtcnt++;
+               (void) vcmd((int)vs->vs_nbr, (char *)&cp->cmd);
+               vs->vs_build = 0;
+       } else
+               timeout(vxforce, (caddr_t)vs, 3);
+}
+
+/*
+ * Write a command out to the VIOC
  */
  */
-struct vxcmd   *
-nextcmd(xp)
-register struct        vcx     *xp;
+vcmd(vx, cmdad)
+       register int vx;
+       register caddr_t cmdad;
 {
 {
-       register struct vxcmd   *cp;
-       register int    s;
+       register struct vcmds *cp;
+       register struct vx_softc *vs = &vx_softc[vx];
+       int s;
 
        s = spl8();
 
        s = spl8();
-       cp = xp->vx_build;
-       xp->vx_build = (struct vxcmd *)0;
+       /*
+        * When the vioc is resetting, don't process
+        * anything other than VXC_LIDENT commands.
+        */
+       if (vs->vs_state == VXS_RESET && cmdad != NULL) {
+               struct vxcmd *vcp = (struct vxcmd *)(cmdad-sizeof (vcp->c_fwd));
+
+               if (vcp->cmd != VXC_LIDENT) {
+                       vrelease(vs, vcp);
+                       return (0);
+               }
+       }
+       cp = &vs->vs_cmds;
+       if (cmdad != (caddr_t)0) {
+               cp->cmdbuf[cp->v_fill] = cmdad;
+               if (++cp->v_fill >= VC_CMDBUFL)
+                       cp->v_fill = 0;
+               if (cp->v_fill == cp->v_empty) {
+                       printf("vx%d: cmd q overflow\n", vx);
+                       vxstreset(vx);
+                       splx(s);
+                       return (0);
+               }
+               cp->v_cmdsem++;
+       }
+       if (cp->v_cmdsem && cp->v_curcnt < vs->vs_maxcmd) {
+               cp->v_cmdsem--;
+               cp->v_curcnt++;
+               vinthandl(vx, ((V_BSY|CMDquals) << 8)|V_INTR);
+       }
        splx(s);
        splx(s);
-       return(cp);
+       return (1);
 }
 
 /*
 }
 
 /*
- * assemble transmits into a multiple command.
- * up to 8 transmits to 8 lines can be assembled together
+ * VIOC acknowledge interrupt.  The VIOC has received the new
+ * command.  If no errors, the new command becomes one of 16 (max)
+ * current commands being executed.
+ */
+vackint(vx)
+       register vx;
+{
+       register struct vxdevice *vp;
+       register struct vcmds *cp;
+       struct vx_softc *vs;
+       int s;
+
+       scope_out(5);
+       vs = &vx_softc[vx];
+       if (vs->vs_type)        /* Its a BOP */
+               return;
+       s = spl8();
+       vp = vs->vs_addr;
+       cp = &vs->vs_cmds;
+       if (vp->v_vcid&V_ERR) {
+               register char *resp;
+               register i;
+
+               printf("vx%d: ackint error type %x v_dcd %x\n", vx,
+                   vp->v_vcid & 07, vp->v_dcd & 0xff);
+               resp = (char *)vs->vs_mricmd;
+               for (i = 0; i < 16; i++)
+                       printf("%x ", resp[i]&0xff);
+               printf("\n");
+               splx(s);
+               vxstreset(vx);
+               return;
+       }
+       if ((vp->v_hdwre&017) == CMDquals) {
+#ifdef VX_DEBUG
+               if (vxintr4 & VXERR4) { /* causes VIOC INTR ERR 4 */
+                       struct vxcmd *cp1, *cp0;
+
+                       cp0 = (struct vxcmd *)
+                           ((caddr_t)cp->cmdbuf[cp->v_empty]-sizeof (cp0->c_fwd));
+                       if (cp0->cmd == VXC_XMITDTA || cp0->cmd == VXC_XMITIMM) {
+                               cp1 = vobtain(vs);
+                               *cp1 = *cp0;
+                               vxintr4 &= ~VXERR4;
+                               (void) vcmd(vx, &cp1->cmd);
+                       }
+               }
+#endif
+               cp->v_curcmd[vp->v_vcid & VCMDLEN-1] = cp->cmdbuf[cp->v_empty];
+               if (++cp->v_empty >= VC_CMDBUFL)
+                       cp->v_empty = 0;
+       }
+       if (++cp->v_itrempt >= VC_IQLEN)
+               cp->v_itrempt = 0;
+       vintempt(vx);
+       splx(s);
+       (void) vcmd(vx, (caddr_t)0);    /* queue next cmd, if any */
+}
+
+/*
+ * Command Response interrupt.  The Vioc has completed
+ * a command.  The command may now be returned to
+ * the appropriate device driver.
  */
  */
-vsetq(xp ,d ,addr, cnt)
-register struct        vcx     *xp;
-caddr_t        addr;
+vcmdrsp(vx)
+       register vx;
 {
 {
+       register struct vxdevice *vp;
+       register struct vcmds *cp;
+       register caddr_t cmd;
+       register struct vx_softc *vs;
+       register char *resp;
+       register k;
+       register int s;
 
 
-       register struct vxcmd   *cp;
-       register struct vxmit   *mp;
-       register char   *p;
-       register i;
+       scope_out(6);
+       vs = &vx_softc[vx];
+       if (vs->vs_type) {      /* Its a BOP */
+               printf("vx%d: vcmdrsp interrupt\n", vx);
+               return;
+       }
+       s = spl8();
+       vp = vs->vs_addr;
+       cp = &vs->vs_cmds;
+       resp = (char *)vp + (vp->v_rspoff&0x7fff);
+       if (((k = resp[1])&V_UNBSY) == 0) {
+               printf("vx%d: cmdresp debug\n", vx);
+               splx(s);
+               vxstreset(vx);
+               return;
+       }
+       k &= VCMDLEN-1;
+       cmd = cp->v_curcmd[k];
+       cp->v_curcmd[k] = (caddr_t)0;
+       cp->v_curcnt--;
+       k = *((short *)&resp[4]);       /* cmd operation code */
+       if ((k&0xff00) == VXC_LIDENT)   /* want hiport number */
+               for (k = 0; k < VRESPLEN; k++)
+                       cmd[k] = resp[k+4];
+       resp[1] = 0;
+       vxxint(vx, (struct vxcmd *)cmd);
+       if (vs->vs_state == VXS_READY)
+               vinthandl(vx, ((V_BSY|RSPquals) << 8)|V_INTR);
+       splx(s);
+}
 
 
-       cp = xp->vx_build;
-       if(cp == (struct vxcmd *)0) {
-               cp = vobtain(xp);
-               xp->vx_build = cp;
-               cp->cmd = XMITDTA;
+/*
+ * Unsolicited interrupt.
+ */
+vunsol(vx)
+       register vx;
+{
+       register struct vxdevice *vp;
+       struct vx_softc *vs;
+       int s;
+
+       scope_out(1);
+       vs = &vx_softc[vx];
+       if (vs->vs_type) {      /* Its a BOP */
+               printf("vx%d: vunsol from BOP\n", vx);
+               return;
+       }
+       s = spl8();
+       vp = vs->vs_addr;
+       if (vp->v_uqual&V_UNBSY) {
+               vxrint(vx);
+               vinthandl(vx, ((V_BSY|UNSquals) << 8)|V_INTR);
+#ifdef notdef
        } else {
        } else {
-               if((cp->cmd & 07) == 07) {
-                       vpanic("vx: vsetq overflow");
-                       vxstreset(xp->v_nbr);
-                       return(0);
+               printf("vx%d: unsolicited interrupt error\n", vx);
+               splx(s);
+               vxstreset(vx);
+#endif
+       }
+       splx(s);
+}
+
+/*
+ * Enqueue an interrupt.
+ */
+vinthandl(vx, item)
+       register int vx;
+       register item;
+{
+       register struct vcmds *cp;
+       int empty;
+
+       cp = &vx_softc[vx].vs_cmds;
+       empty = (cp->v_itrfill == cp->v_itrempt);
+       cp->v_itrqueu[cp->v_itrfill] = item;
+       if (++cp->v_itrfill >= VC_IQLEN)
+               cp->v_itrfill = 0;
+       if (cp->v_itrfill == cp->v_itrempt) {
+               printf("vx%d: interrupt q overflow\n", vx);
+               vxstreset(vx);
+       } else if (empty)
+               vintempt(vx);
+}
+
+vintempt(vx)
+       int vx;
+{
+       register struct vcmds *cp;
+       register struct vxdevice *vp;
+       register struct vx_softc *vs;
+       register short item;
+       register short *intr;
+
+       vs = &vx_softc[vx];
+       vp = vs->vs_addr;
+       if (vp->v_vioc&V_BSY)
+               return;
+       cp = &vs->vs_cmds;
+       if (cp->v_itrempt == cp->v_itrfill)
+               return;
+       item = cp->v_itrqueu[cp->v_itrempt];
+       intr = (short *)&vp->v_vioc;
+       switch ((item >> 8)&03) {
+
+       case CMDquals: {                /* command */
+               int phys;
+
+               if (cp->v_empty == cp->v_fill || vp->v_vcbsy&V_BSY)
+                       break;
+               vs->vs_mricmd = (caddr_t)cp->cmdbuf[cp->v_empty];
+               phys = vtoph((struct proc *)0, 
+                   (unsigned)cp->cmdbuf[cp->v_empty]);
+               vp->v_vcp[0] = ((short *)&phys)[0];
+               vp->v_vcp[1] = ((short *)&phys)[1];
+               vp->v_vcbsy = V_BSY;
+               *intr = item;
+               scope_out(4);
+               break;
+       }
+
+       case RSPquals:          /* command response */
+               *intr = item;
+               scope_out(7);
+               break;
+
+       case UNSquals:          /* unsolicited interrupt */
+               vp->v_uqual = 0;
+               *intr = item;
+               scope_out(2);
+               break;
+       }
+}
+
+/*
+ * Start a reset on a vioc after error (hopefully)
+ */
+vxstreset(vx)
+       register int vx;
+{
+       register struct vx_softc *vs;
+       register struct vxdevice *vp;
+       register struct vxcmd *cp;
+       register int j;
+       extern int vxinreset();
+       int s;
+
+       vs = &vx_softc[vx];
+       s = spl8();
+       if (vs->vs_state == VXS_RESET) {        /* avoid recursion */
+               splx(s);
+               return;
+       }
+       vp = vs->vs_addr;
+       /*
+        * Zero out the vioc structures, mark the vioc as being
+        * reset, reinitialize the free command list, reset the vioc
+        * and start a timer to check on the progress of the reset.
+        */
+       bzero((caddr_t)&vs->vs_zero,
+           (unsigned)((caddr_t)(vs + 1) - (caddr_t)&vs->vs_zero));
+
+       /*
+        * Setting VXS_RESET prevents others from issuing
+        * commands while allowing currently queued commands to
+        * be passed to the VIOC.
+        */
+       vs->vs_state = VXS_RESET;
+       /* init all cmd buffers */
+       for (j = 0; j < NVCXBUFS; j++) {
+               cp = &vs->vs_lst[j];
+               cp->c_fwd = &vs->vs_lst[j+1];
+       }
+       vs->vs_avail = &vs->vs_lst[0];
+       cp->c_fwd = (struct vxcmd *)0;
+       printf("vx%d: reset...", vx);
+       vp->v_fault = 0;
+       vp->v_vioc = V_BSY;
+       vp->v_hdwre = V_RESET;          /* generate reset interrupt */
+       timeout(vxinreset, (caddr_t)vx, hz*5);
+       splx(s);
+}
+
+/* continue processing a reset on a vioc after an error (hopefully) */
+vxinreset(vx)
+       int vx;
+{
+       register struct vxdevice *vp;
+       int s = spl8();
+
+       vp = vx_softc[vx].vs_addr;
+       /*
+        * See if the vioc has reset.
+        */
+       if (vp->v_fault != VXF_READY) {
+               printf(" vxreset failed\n");
+               splx(s);
+               return;
+       }
+       /*
+        * Send a LIDENT to the vioc and mess with carrier flags
+        * on parallel printer ports.
+        */
+       vxinit(vx, 0);
+       splx(s);
+}
+
+/*
+ * Finish the reset on the vioc after an error (hopefully).
+ *
+ * Restore modem control, parameters and restart output.
+ * Since the vioc can handle no more then 24 commands at a time
+ * and we could generate as many as 48 commands, we must do this in
+ * phases, issuing no more then 16 commands at a time.
+ */
+vxfnreset(vx, cp)
+       register int vx;
+       register struct vxcmd *cp;
+{
+       register struct vx_softc *vs;
+       register struct vxdevice *vp;
+       register struct tty *tp, *tp0;
+       register int i;
+#ifdef notdef
+       register int on;
+#endif
+       extern int vxrestart();
+       int s = spl8();
+
+       vs = &vx_softc[vx];
+       vrelease(vs, cp);
+       vs->vs_state = VXS_READY;
+
+       vp = vs->vs_addr;
+       vp->v_vcid = 0;
+
+       /*
+        * Restore modem information and control.
+        */
+       tp0 = &vx_tty[vx*16];
+       for (i = vs->vs_loport; i <= vs->vs_hiport; i++) {
+               tp = tp0 + i;
+               if (tp->t_state&(TS_ISOPEN|TS_WOPEN)) {
+                       tp->t_state &= ~TS_CARR_ON;
+                       vcmodem(tp->t_dev, VMOD_ON);
+                       if (tp->t_state&TS_CARR_ON)
+                               (void)(*linesw[tp->t_line].l_modem)(tp, 1);
+                       else if (tp->t_state & TS_ISOPEN)
+                               (void)(*linesw[tp->t_line].l_modem)(tp, 0);
                }
                }
-               cp->cmd++;
+#ifdef notdef
+               /*
+                * If carrier has changed while we were resetting,
+                * take appropriate action.
+                */
+               on = vp->v_dcd & 1<<i;
+               if (on && (tp->t_state&TS_CARR_ON) == 0)
+                       (void)(*linesw[tp->t_line].l_modem)(tp, 1);
+               else if (!on && tp->t_state&TS_CARR_ON)
+                       (void)(*linesw[tp->t_line].l_modem)(tp, 0);
+#endif
        }
        }
+       vs->vs_state = VXS_RESET;
+       timeout(vxrestart, (caddr_t)vx, hz);
+       splx(s);
+}
 
 
-       mp = (struct vxmit *)(cp->par + (cp->cmd & 07)*sizvxmit);
-       mp->bcount = cnt-1;
+/*
+ * Restore a particular aspect of the VIOC.
+ */
+vxrestart(vx)
+       int vx;
+{
+       register struct tty *tp, *tp0;
+       register struct vx_softc *vs;
+       register int i, count;
+       int s = spl8();
+
+       count = vx >> 8;
+       vx &= 0xff;
+       vs = &vx_softc[vx];
+       vs->vs_state = VXS_READY;
+       tp0 = &vx_tty[vx*16];
+       for (i = vs->vs_loport; i <= vs->vs_hiport; i++) {
+               tp = tp0 + i;
+               if (count != 0) {
+                       tp->t_state &= ~(TS_BUSY|TS_TIMEOUT);
+                       if (tp->t_state&(TS_ISOPEN|TS_WOPEN))
+                               vxstart(tp);    /* restart pending output */
+               } else {
+                       if (tp->t_state&(TS_WOPEN|TS_ISOPEN))
+                               vxcparam(tp, &tp->t_termios, 0);
+               }
+       }
+       if (count == 0) {
+               vs->vs_state = VXS_RESET;
+               timeout(vxrestart, (caddr_t)(vx + 1*256), hz);
+       } else
+               printf(" vx reset done\n");
+       splx(s);
+}
 
 
-       mp->line = d;
-       if((xp->v_vers == V_NEW) && (cnt <= 6)) {
-               cp->cmd = XMITIMM ;
-               p = addr;
-               /* bcopy(addr, &(char *)mp->ostream, cnt) ; */
-       } else {
-               addr = vtoph(0, (caddr_t)addr) ; /* should be a sys address */
-               p = (char *)&addr;
-               cnt = sizeof addr;
-               /* mp->ostream = addr ; */
-       }
-       for(i=0; i<cnt; i++)
-               mp->ostream[i] = *p++;
-       if(xp->v_vers == V_NEW)
-               return(1) ;
-       else
-               return((cp->cmd&07) == 7) ;     /* Indicate if full */
+vxreset(dev)
+       dev_t dev;
+{
+
+       vxstreset((int)VXUNIT(minor(dev)));     /* completes asynchronously */
+}
+
+#ifdef VX_DEBUG
+vxfreset(vx)
+       register int vx;
+{
+       struct vba_device *vi;
+
+       if ((unsigned)vx > NVX || (vi = vxinfo[vx]) == 0 || vi->ui_addr == 0)
+               return (ENODEV);
+       vx_softc[vx].vs_state = VXS_READY;
+       vxstreset(vx);
+       return (0);             /* completes asynchronously */
+}
+#endif
+
+vcmodem(dev, flag)
+       dev_t dev;
+{
+       struct tty *tp;
+       register struct vxcmd *cp;
+       register struct vx_softc *vs;
+       register struct vxdevice *kp;
+       register port;
+       int unit;
+
+       unit = minor(dev);
+       tp = &vx_tty[unit];
+       vs = (struct vx_softc *)tp->t_addr;
+       if (vs->vs_state != VXS_READY)
+               return;
+       cp = vobtain(vs);
+       kp = vs->vs_addr;
+
+       port = VXPORT(unit);
+       /*
+        * Issue MODEM command
+        */
+       cp->cmd = VXC_MDMCTL;
+       if (flag == VMOD_ON) {
+               if (vs->vs_softCAR & (1 << port)) {
+                       cp->par[0] = V_MANUAL | V_DTR_ON | V_RTS;
+                       kp->v_dcd |= (1 << port);
+               } else
+                       cp->par[0] = V_AUTO | V_DTR_ON;
+       } else
+               cp->par[0] = V_DTR_OFF;
+       cp->par[1] = port;
+       (void) vcmd((int)vs->vs_nbr, (caddr_t)&cp->cmd);
+       if ((kp->v_dcd | vs->vs_softCAR) & (1 << port) && flag == VMOD_ON)
+               tp->t_state |= TS_CARR_ON;
+}
+
+/*
+ * VCMINTR called when an unsolicited interrupt occurs signaling
+ * some change of modem control state.
+ */
+vcmintr(vx)
+       register vx;
+{
+       register struct vxdevice *kp;
+       register struct tty *tp;
+       register port;
+       register struct vx_softc *vs;
+
+       vs = &vx_softc[vx];
+       kp = vs->vs_addr;
+       port = kp->v_usdata[0] & 017;
+       tp = &vx_tty[vx*16+port];
+
+       if (kp->v_ustat & DCD_ON)
+               (void)(*linesw[tp->t_line].l_modem)(tp, 1);
+       else if ((kp->v_ustat & DCD_OFF) &&
+           ((vs->vs_softCAR & (1 << port))) == 0 &&
+           (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
+               register struct vcmds *cp;
+               register struct vxcmd *cmdp;
+
+               /* clear all pending transmits */
+               if (tp->t_state&(TS_BUSY|TS_FLUSH) &&
+                   vs->vs_vers == VXV_NEW) {
+                       int i, cmdfound = 0;
+
+                       cp = &vs->vs_cmds;
+                       for (i = cp->v_empty; i != cp->v_fill; ) {
+                               cmdp = (struct vxcmd *)((long *)cp->cmdbuf[i]-1);
+                               if ((cmdp->cmd == VXC_XMITDTA ||
+                                   cmdp->cmd == VXC_XMITIMM) &&
+                                   ((struct vxmit *)cmdp->par)->line == port) {
+                                       cmdfound++;
+                                       cmdp->cmd = VXC_FDTATOX;
+                                       cmdp->par[1] = port;
+                               }
+                               if (++i >= VC_CMDBUFL)
+                                       i = 0;
+                       }
+                       if (cmdfound)
+                               tp->t_state &= ~(TS_BUSY|TS_FLUSH);
+                       /* cmd is already in vioc, have to flush it */
+                       else {
+                               cmdp = vobtain(vs);
+                               cmdp->cmd = VXC_FDTATOX;
+                               cmdp->par[1] = port;
+                               (void) vcmd(vx, (caddr_t)&cmdp->cmd);
+                       }
+               }
+       } else if ((kp->v_ustat&BRK_CHR) && (tp->t_state&TS_ISOPEN)) {
+               (*linesw[tp->t_line].l_rint)(TTY_FE, tp);
+               return;
+       }
 }
 #endif
 }
 #endif