--- cci/sys/vba/vcm.c 2019/07/28 12:24:19 1.1.1.1 +++ cci/sys/vba/vcm.c 2019/07/28 12:30:09 1.1.1.2 @@ -9,6 +9,8 @@ #include "../h/ioctl.h" #include "../h/tty.h" #include "../h/conf.h" +#include "../h/dir.h" +#include "../h/user.h" #include "../vba/vioc.h" #include "../vba/vxdebug.h" @@ -19,140 +21,291 @@ extern char bscport[]; #endif - -extern struct vcx vcx[] ; +extern struct vcx vcx[]; extern struct tty vx_tty[]; -extern struct vcmds v_cmds[] ; +extern struct vcmds v_cmds[]; -extern int vxstart() ; -extern struct vxcmd *vobtain() ; -extern struct vxcmd *nextcmd() ; +extern int vxstart(); +extern struct vxcmd *vobtain(); -long viocPC = 0; +unsigned char vcmanual[NVXPORTS]; -vcmodem(dev,flag) -dev_t dev ; +vcumodem(dev, cmd, arg, mode) +int dev, cmd; +register caddr_t arg; +int mode; { - struct tty *tp ; - register struct vxcmd *cp ; + register int line = minor(dev)&0xff; + register struct tty *tp = &vx_tty[line]; + register int port = line&0xf; register struct vcx *xp ; register struct vblok *kp ; - register port ; - port = minor(dev) ; - tp = &vx_tty[port] ; - port &= 017 ; - xp = (struct vcx *)tp->t_addr ; - cp = vobtain(xp) ; - kp = VBAS(xp->v_nbr) ; + xp = &vcx[line>>4]; + kp = VBAS(xp->v_nbr); + + switch (cmd) { + case VCMANUAL: + if (*(int *)arg == VC_OFF) { + ttywait(tp); + vcmanual[line] &= ~VC_RTS; /* make sure RTS gets turned off */ + vcmodem(line, -1); + vcmanual[line] &= ~VC_MANUAL; + if (vcmanual[line]&VC_DCD) + tp->t_state |= TS_CARR_ON; + else /* XXX.jds should hangup and flush */ + tp->t_state &= ~TS_CARR_ON; + } else { + vcmanual[line] = VC_MANUAL; + if (tp->t_state&TS_CARR_ON) + vcmanual[line] |= VC_DCD; + if (tp->t_state&TS_ISOPEN) + vcmanual[line] |= VC_DTR; + } + vcmodem(dev, VMOD_ON); + break; + + case VCGRS232: + port -= xp->v_loport; + if (kp->v_dcd&1<v_cts&1<t_addr; + port = line&0xf; + cp = vobtain(xp); + kp = VBAS(xp->v_nbr); /* * Issue MODEM command */ - cp->cmd = MDMCTL ; - cp->par[0] = (flag == VMOD_ON) ? V_ENAB : V_DISAB ; - cp->par[1] = port; - vcmd(xp->v_nbr, &cp->cmd) ; - port -= xp->v_loport ; - if((kp->v_dcd >> port) & 1) { - if(flag == VMOD_ON) - tp->t_state |= TS_CARR_ON ; - return(1) ; + cp->cmd = MDMCTL; + if (vcmanual[line]&VC_MANUAL) { + /* + * We're in manual mode. + */ + mode = V_MANUAL; + if (vcmanual[line]&VC_RTS) + mode |= V_RTS; + if (vcmanual[line]&VC_DTR) + mode |= V_DTR; + carrier++; + } else { + /* + * We're in "auto" mode. + */ + mode = V_AUTO; + if (flag == VMOD_ON) + mode |= V_DTR; } - return(0) ; -} + cp->par[0] = mode; + cp->par[1] = port; + vcmd(xp->v_nbr, &cp->cmd); + + port -= xp->v_loport; +#ifdef VX_DEBUG + if (flag == VMOD_ON) + printf("\nvcmodem:ON, port%d, dcd(%lx)", + port, kp->v_dcd&0xffff); + else + printf("\nvcmodem:OFF, port%d, dcd(%lx)", + port, kp->v_dcd&0xffff); +#endif + if (kp->v_dcd>>port&1) { + tp->t_state |= TS_CARR_ON; + vcmanual[line] |= VC_DCD; + carrier++; + } else + vcmanual[line] &= ~VC_DCD; + + if (kp->v_cts>>port&1) + vcmanual[line] |= VC_CTS; + else + vcmanual[line] &= ~VC_CTS; + return(carrier != 0); +} /* * VCMINTR called when an unsolicited interrup occurs signaling * some change of modem control state. */ vcmintr(n) -register n ; /* viocx number */ +register int n; /* viocx number */ { - register struct vblok *kp ; - register struct tty *tp ; - register port ; - - kp = VBAS( n ) ; - port = kp->v_usdata[0] & 017 ; - tp = &vx_tty[port+n*16] ; + register struct vblok *kp; + register struct tty *tp; + register int port, line; + + kp = VBAS(n); + port = kp->v_usdata[0]&017; + line = port + (n<<4); + tp = &vx_tty[line]; #if NVBSC > 0 - /* - * Check for change in DSR for BISYNC port. - */ - if ((kp->v_ustat & DSR_CHG) && (bscport[port+n*16] & BISYNC)) { - register struct vcx *xp ; - register struct bsc *bp ; - extern struct bsc bsc[] ; - - bp = &bsc[((minor(tp->t_dev)) >> 4) & 0xf] ; - bp->b_hlflgs &= ~BSC_DSR ; - if (kp->v_ustat & DSR_ON) - bp->b_hlflgs |= BSC_DSR ; + /* + * Check for change in DSR for BISYNC port. + */ + if ((kp->v_ustat&DSR_CHG) && (bscport[line]&BISYNC)) { + register struct bsc *bp; + extern struct bsc bsc[]; + + bp = &bsc[(minor(tp->t_dev) >> 4)&0xf]; + bp->b_hlflgs &= ~BSC_DSR; + if (kp->v_ustat&DSR_ON) + bp->b_hlflgs |= BSC_DSR; } - if (bscport[port+n*16] & BISYNC) return; + if (bscport[line]&BISYNC) + return; #endif + if (vcmanual[port]&VC_MANUAL) { + register int ustat = kp->v_ustat; + /* + * Update our modem status. + */ + if (ustat&DCD_ON) + vcmanual[line] |= VC_DCD; + else + vcmanual[line] &= ~VC_DCD; + if (ustat&CTS_ON) + vcmanual[line] |= VC_CTS; + else + vcmanual[line] &= ~VC_CTS; + goto out; + } + + if (kp->v_ustat&DCD_ON) { #ifdef VX_DEBUG - if (vxdebug & VXVCM) - printf("vcmintr: VX%d, port%lx, v_ustat: %lx, t_state: %lx\n", - n,port,kp->v_ustat&0xff,tp->t_state); + printf("\nvcmintr: CARR_ON, VIOC%d, port%d, state(%lx)", + n, port, tp->t_state); #endif - if((kp->v_ustat & DCD_ON) && ((tp->t_state & TS_CARR_ON) == 0) ) { - tp->t_state |= TS_CARR_ON ; - wakeup((caddr_t)&tp->t_canq) ; - return ; + if ((tp->t_state&TS_CARR_ON) == 0 && + tp->t_state&(TS_WOPEN|TS_ISOPEN)) { + /* + * Carrier transition from low to high. + */ + tp->t_state |= TS_CARR_ON; + if (tp->t_state&TS_WOPEN) + wakeup((caddr_t)&tp->t_canq); + } + return; } - if((kp->v_ustat & DCD_OFF) && (tp->t_state & TS_CARR_ON)) { - tp->t_state &= ~TS_CARR_ON ; - if(tp->t_state & TS_ISOPEN) { - register struct vcx *xp ; - register struct vcmds *cp ; - register struct vxcmd *cmdp ; - + if (kp->v_ustat&DCD_OFF) { + if (tp->t_state&TS_CARR_ON && + tp->t_state&(TS_WOPEN|TS_ISOPEN)) { + /* + * Carrier transition from high to low. + */ ttyflush(tp, FREAD|FWRITE); - /* clear all pending trnansmits */ - xp = &vcx[n]; - if(tp->t_state&(TS_BUSY|TS_FLUSH) && xp->v_vers==V_NEW) - { - int i, cmdfound = 0; - cp = &v_cmds[n]; - for(i = cp->v_empty; i!=cp->v_fill; ) { - cmdp = (struct vxcmd *)((long *)cp->cmdbuf[i]-1); - if((cmdp->cmd==XMITDTA || cmdp->cmd==XMITIMM) - && ((struct vxmit *)cmdp->par)->line == port) { - cmdfound++; - cmdp->cmd = 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(xp); - cmdp->cmd = FDTATOX ; - cmdp->par[1] = port ; - vcmd(n, &cmdp->cmd); - } - } - if((tp->t_flags&NOHANG)==0) { - gsignal(tp->t_pgrp, SIGHUP) ; + vxflush(tp); + if ((tp->t_flags&NOHANG)==0) { + gsignal(tp->t_pgrp, SIGHUP); gsignal(tp->t_pgrp, SIGCONT); } + tp->t_state &= ~TS_CARR_ON; } - return ; + return; + } +out: + if (kp->v_ustat&BRK_CHR && tp->t_state&TS_ISOPEN) { + (*linesw[tp->t_line].l_rint)(tp->t_intrc&0377, tp); + return; } +} - if((kp->v_ustat & BRK_CHR) && (tp->t_state & TS_ISOPEN) ) { - (*linesw[tp->t_line].l_rint)(tp->t_intrc & 0377, tp) ; - return ; +/* + * Stop further output on the line. + * Must be called from spltty or higher. + */ +vxflush(tp) +register struct tty *tp; +{ + register int n = minor(tp->t_dev)>>4; + register int port = minor(tp->t_dev)&0xf; + register struct vcx *xp; + register struct vcmds *cp = &v_cmds[n]; + register struct vxcmd *cmdp; + register int i; + + xp = &vcx[n]; + if (((tp->t_state&TS_BUSY) == 0 && (tp->t_state&TS_FLUSH) == 0) || + xp->v_vers == V_OLD) + /* + * Output already stopped. + */ + return; + + /* + * Either output is in progress for this port + * or an output command is queued up for it. + * Check the queue and see if it has gotten to + * the vioc yet. + */ + for (i = cp->v_empty; i!=cp->v_fill;) { + cmdp = (struct vxcmd *)((long *)cp->cmdbuf[i]-1); + if ((cmdp->cmd==XMITDTA || cmdp->cmd==XMITIMM) && + ((struct vxmit *)cmdp->par)->line == port) { + /* + * Found the command on the input queue -- + * turn it into something harmless. + */ + cmdp->cmd = FDTATOX; + cmdp->par[1] = port; + tp->t_state &= ~TS_BUSY; + return; + } + if (++i >= VC_CMDBUFL) + i = 0; } + + /* + * Command has already gotten to the VIOC -- + * tell the VIOC to get rid of it. + */ + cmdp = vobtain(xp); + cmdp->cmd = FDTATOX; + cmdp->par[1] = port; + vcmd(n, &cmdp->cmd); } #endif