|
|
Power 6/32 Unix version 1.21
#include "vx.h"
#if NVX > 0
/*
* VIOC-X Modem control
*/
#include "../h/param.h"
#include "../h/file.h"
#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"
#include "vbsc.h"
#if NVBSC > 0
#include "../bsc/bscio.h"
#include "../bsc/bsc.h"
extern char bscport[];
#endif
extern struct vcx vcx[];
extern struct tty vx_tty[];
extern struct vcmds v_cmds[];
extern int vxstart();
extern struct vxcmd *vobtain();
unsigned char vcmanual[NVXPORTS];
vcumodem(dev, cmd, arg, mode)
int dev, cmd;
register caddr_t arg;
int mode;
{
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 ;
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<<port)
vcmanual[line] |= VC_DCD;
else
vcmanual[line] &= ~VC_DCD;
if (kp->v_cts&1<<port)
vcmanual[line] |= VC_CTS;
else
vcmanual[line] &= ~VC_CTS;
u.u_r.r_val1 = vcmanual[line]&VC_MASK;
break;
case VCSRS232:
if ((vcmanual[line]&VC_MANUAL) == 0)
/*
* Ok to look at the signals, but
* you can't set them unless you go
* into manual mode.
*/
return(EINVAL);
vcmanual[line] &= ~(VC_DTR|VC_RTS);
vcmanual[line] |= *(int *)arg&(VC_DTR|VC_RTS);
vcmodem(dev, -1);
break;
default:
return(EINVAL);
}
return(0);
}
vcmodem(dev, flag)
register int dev;
int flag;
{
struct tty *tp;
register struct vxcmd *cp;
register struct vcx *xp;
register struct vblok *kp;
register int port, line, mode, carrier = 0;
line = minor(dev)&0xff;
tp = &vx_tty[line];
xp = (struct vcx *)tp->t_addr;
port = line&0xf;
cp = vobtain(xp);
kp = VBAS(xp->v_nbr);
/*
* Issue MODEM command
*/
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;
}
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 int n; /* viocx number */
{
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[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[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
printf("\nvcmintr: CARR_ON, VIOC%d, port%d, state(%lx)",
n, port, tp->t_state);
#endif
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) {
if (tp->t_state&TS_CARR_ON &&
tp->t_state&(TS_WOPEN|TS_ISOPEN)) {
/*
* Carrier transition from high to low.
*/
ttyflush(tp, FREAD|FWRITE);
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;
}
out:
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.