File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / sys / vba / vcm.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Sun Jul 28 12:30:09 2019 UTC (6 years, 11 months ago) by root
Branches: bsd, MAIN
CVS tags: v121, HEAD
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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.