Interdata732/usr/sys/cli.c

Compare this file to the similar file:
Show the results in this format:

#

/*
 *	Current Loop Interface Driver
 *
 */

#include "param.h"
#include "conf.h"
#include "proc.h"
#include "tty.h"
#include "user.h"

#define NCLI	1	/* number of terminals */

char	cliaddr[NCLI] {		/* cli addresses */
	02
};

struct tty cli[NCLI];	/* common tty structure */

#define devmap(addr)	&cli[addr-02]	/* map phys addr => tty */

/* Current Loop Interface Command and Status Bits */

	/* commands */

#define	DISABLE	0200
#define	ENABLE	0100
#define	UNBLOCK	0040
#define	BLOCK	0020
#define	WRITE	0010
#define	READ	0004

	/* status */

#define	OV	0200
#define	BRK	0040
#define	BSY	0010
#define	EX	0004
#define	DU	0001

#define	WINIT	WOPEN		/* waiting to change mode read->write */

/*
 * open routine:
 *	called each time a process opens a terminal as a character file
 *
 *	- if the terminal was previously inactive, set up the initial status
 *	  and arm interrupts
 */
cliopen(dev,flag)
{
	register struct tty *tp;
	int clistart();

	if (dev.d_minor >= NCLI) {	/* minor device number too large ? */
		u.u_error = ENXIO;	/* yes, return error */
		return;
	}
	tp = &cli[dev.d_minor];		/* get tty struct for terminal */
	tp->t_dev = dev;		/* set device number in tty struct */
	if ((tp->t_state & ISOPEN) == 0) {
		tp->t_state = ISOPEN | CARR_ON | SSTART;
		if (tp->t_flags == 0)
			tp->t_flags = XTABS | LCASE | CRMOD | ECHO;
		tp->t_erase = CERASE;
		tp->t_kill = CKILL;
         	tp->t_addr = &clistart;  /* special output start routine */

		cliparam(tp);		/* enable read and set parms */
		trace(0x1000,"cliopen rd:",rd(cliaddr[dev.d_minor]));
	}
	if (u.u_procp->p_ttyp == 0)	/* give a process to the tty */
		u.u_procp->p_ttyp = tp;
}


/*
 * close routine:
 *	- called only when last process using terminal releases it
 */
cliclose (dev)
{
	register struct tty *tp;

	tp = &cli[dev.d_minor];		/* find tty struct for terminal */
	wflushtty(tp);			/* flush queues */
	tp->t_state = 0;		/* clear status */
	oc(cliaddr[dev.d_minor], DISABLE | READ | BLOCK);	/* disable read */
}

/*
 * read, write, stty, gtty routines:
 *	- call standard tty routines
 */
cliread(dev)
{
	ttread(&cli[dev.d_minor]);
}

cliwrite(dev)
{
	ttwrite(&cli[dev.d_minor]);
}

clisgtty(dev, v)
{

	register struct tty *tp;
	tp = &cli[dev.d_minor];
	ttystty(tp, v);
	if ( (v==0) && !(tp->t_state & BUSY))  /* if read and if ECHO, set hardware echo */
		cliparam(tp);
}


/* 
 *	set device parameters
 *      enable read; if ECHO, enable hardware echo.
 *
 */
cliparam(tp)
struct tty *tp;
{
/***
	oc(cliaddr[tp->t_dev.d_minor], ENABLE | READ | ((tp->t_flag & ECHO) ?
		    UNBLOCK : BLOCK));
***/	oc(cliaddr[tp->t_dev.d_minor], ENABLE | READ | BLOCK);
	return;
}

/*
 *
 *	When the interface changes from read to write, an interrupt
 *	is generated.  This is where we enable the transmit side.
 *	If busy is set , then a write is in progress and there is
 *	nothing to do.
 *
 */
clistart(atp)
struct	tty	*atp;
{
	register struct	tty	*tp;

	tp = atp;
	if ( !(tp->t_state & BUSY)) {
		tp->t_state =| (WINIT | BUSY);		/* set winit flag */
		oc(cliaddr[tp->t_dev.d_minor], ENABLE | WRITE | BLOCK );	/* enable write */
	}
}

/*
 *	second level output start routine
 *
 *	This routine is called from  cliint on write interrupt
 *	to send a character.
 *
 */

clistrto(atp)
struct tty *atp;
{
	int ttrstrt();
	register struct tty *tp;
	register c;

	tp = atp;

	/* get character to output  */

	c = getc(&tp->t_outq);
	if (c < 0)	/* no more chars on outq, start reading */
	{
		cliparam(tp);		/* enable read */
		return;
	}
	if (c > 0177) {
		/* timeout delay */
		tp->t_state =| TIMEOUT;
		timeout(&ttrstrt, tp, c&0177);
	} else {
		/* write character to device */
		tp->t_state =| BUSY;
		wd(cliaddr[tp->t_dev.d_minor], c);
		trace(0x1000, "wrt", ss(cliaddr[tp->t_dev.d_minor]));
	}
}

/*	interrupt handler
 */
cliint(addr,stat)
int	addr;
int	stat;
{
	register struct tty *tp;
	register c;

	tp = devmap(addr);
	if ( !(tp->t_state & ISOPEN))	/* return if device not open */
		return;
	if (tp->t_state & BUSY)  	/* if write enable or write complete */
	{
		if (stat & BRK)  		/* if BRK key hit */
		{
			trace(0x1000,"brk :",0);
			c = CINTR;	/* set character to del */
			tp->t_state =& ~(BUSY | WINIT);	/* reset flags */
			cliparam(tp);		/* reset to read mode */
			ttyinput(c, tp);
		}
		else
		if (tp->t_state & WINIT)  
		{
			/* if WINIT, interrupt was write enable */
         		trace(0x1000, "WINIT", stat);
         		tp->t_state =& ~(BUSY | WINIT);
         		clistrto(tp);
		}
		else 
		{
         		/* else interrupt was write complete */
         		trace(0x1000, "wint", stat);
         		tp->t_state =& ~BUSY;
         		clistrto(tp);
         
         		if (tp->t_outq.c_cc <= TTLOWAT && (tp->t_state&ASLEEP))
         		{
         			tp->t_state =& ~ASLEEP;
         			wakeup(&tp->t_outq);
         		}
		}
	}
	else	/*  read complete interrupt */
	{
		trace(0x1000, "rint", stat);
		c = rd(addr) & 0177;
		trace(0x1000, "c = ", c);
		ttyinput(c, tp);
	}
	trace(0x1000,"int exit ss:",ss(addr));
	trace(0x1000,"t_state",tp->t_state);
	trace(0x1000,"addr",addr);
}