📄 vx.c
字号:
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. */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; 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);}/* * 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 { 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); }#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);}/* * 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);}vxreset(dev) dev_t dev;{ vxstreset((int)VXUNIT(minor(dev))); /* completes asynchronously */}#ifdef VX_DEBUGvxfreset(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 */}#endifvcmodem(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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -