+ 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);