📄 vx.c
字号:
#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); } splx(s); return (error);}/* * VIOCX command response interrupt. * For transmission, restart output to any active port. * For all other commands, just clean up. */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; case VXC_XMITDTA: case VXC_XMITIMM: break; 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; } 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; if (tp->t_state & TS_FLUSH) { tp->t_state &= ~TS_FLUSH; wakeup((caddr_t)&tp->t_state); } else ndflush(&tp->t_outq, vp->bcount+1); } 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); } } vs->vs_xmtcnt--;}/* * Force out partial XMIT command after timeout */vxforce(vs) register struct vx_softc *vs;{ register struct vxcmd *cp; int s; s = spl8(); if ((cp = nextcmd(vs)) != NULL) { vs->vs_xmtcnt++; (void) vcmd((int)vs->vs_nbr, (caddr_t)&cp->cmd); } splx(s);}/* * Start (restart) transmission on the given VX line. */vxstart(tp) register struct tty *tp;{ register short n; register struct vx_softc *vs; int s, port; s = spl8(); 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_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) { splx(s); return; } 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; n = 0; } } if (n) { tp->t_state |= TS_BUSY; vsetq(vs, port, (char *)tp->t_outq.c_cf, n); } } splx(s);}/* * Stop output on a line. */vxstop(tp) register struct tty *tp;{ int s; s = spl8(); if (tp->t_state&TS_BUSY) if ((tp->t_state&TS_TTSTOP) == 0) tp->t_state |= TS_FLUSH; 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 to establish interrupt vectors and logical port numbers. */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: printf("vx%d: unknown type %x\n", vx, type); unsup: vxinfo[vx]->ui_alive = 0; return; } 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]; } 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 */ /* * 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; 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 */ resp = (char *)addr + (addr->v_rspoff&0x3fff); if (resp[0] != 0 && (resp[0]&0177) != 3) { vrelease(vs, cp); /* init failed */ return; } 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 */struct vxcmd *vobtain(vs) register struct vx_softc *vs;{ register struct vxcmd *p; int s; s = spl8(); p = vs->vs_avail; if (p == (struct vxcmd *)0) {#ifdef VX_DEBUG if (vxintr4&VXNOBUF) vxintr4 &= ~VXNOBUF;#endif printf("vx%d: no buffers\n", vs->vs_nbr); vxstreset(vs->vs_nbr); splx(s); return (vobtain(vs)); } vs->vs_avail = p->c_fwd; splx(s); return ((struct vxcmd *)p);}/* * Release a command buffer */vrelease(vs, cp) register struct vx_softc *vs; register struct vxcmd *cp;{ int s;#ifdef VX_DEBUG if (vxintr4&VXNOBUF) return;#endif s = spl8(); cp->c_fwd = vs->vs_avail; vs->vs_avail = cp; 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);}/* * 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 */vcmd(vx, cmdad) register int vx; register caddr_t cmdad;{ register struct vcmds *cp; register struct vx_softc *vs = &vx_softc[vx]; int s; s = spl8(); /* * 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); return (1);}/* * 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -