V7M/sys/dev/dz.c

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

/*
 *	DZ11 driver
 *
 *	Modified for local/remote terminal operation.
 *	The tty_lt[] array (see tty.h & tty.c)
 *	controls local/remote operation of the tty.
 *
 *	Fred Canter 8/16/81
 */

#include "../h/param.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/tty.h"

#define	DZADDR	0160100	/* CSR address for first DZ11 */
#define	NDZ11	8	/* number of dz11 lines */
			/* MUST BE A MULTIPLE OF 8 */

struct device *dz_addr[] =
{
	(struct device *)(DZADDR),
	(struct device *)(DZADDR+010),
	(struct device *)(DZADDR+020),
	(struct device *)(DZADDR+030),
	(struct device *)(DZADDR+040),
	(struct device *)(DZADDR+050),
	(struct device *)(DZADDR+060),
	(struct device *)(DZADDR+070),
};
int	dz_cnt = NDZ11;
struct tty dz_tty[NDZ11];
char	dz_stat;

char	dz_speeds[] = {
	0, 020, 021, 022, 023, 024, 0, 025,
	026, 027, 030, 032, 034, 036, 0, 0,
	};

#define	BITS7	020
#define	BITS8	030
#define	TWOSB	040
#define	PENABLE	0100
#define	OPAR	0200
#define	RCVENA	010000

#define	IE	040140
#define	PERROR	010000
#define	FRERROR	020000
#define	SSPEED	7	/* standard speed: 300 baud */

struct device {
	int	dzcsr, dzrbuf;
	char	dztcr, dzdtr;
	char	dztbuf, dzbrk;
};
#define	dzlpr	dzrbuf
#define	dzmsr	dzbrk

#define	ON	1
#define	OFF	0


dzopen(dev, flag)
{
	register struct tty *tp;
	int x;
	extern dzstart(), dzscan();

	x = dev;
	dev = minor(dev);
	if (dev >= dz_cnt) {
		u.u_error = ENXIO;
		return;
	}
	tp = &dz_tty[dev];
	tp->t_addr = dz_addr[(dev >> 3) & 7];
	if ((tp->t_state&(ISOPEN|WOPEN)) == 0) {
		tp->t_oproc = dzstart;
		tp->t_iproc = NULL;
		ttychars(tp);
		tp->t_ispeed = SSPEED;
		tp->t_ospeed = SSPEED;
		tp->t_flags = ODDP|EVENP|ECHO;
		dzparam(dev);
	}
	dzmodem(dev, ON);
	spl6();
	while ((tp->t_state&CARR_ON)==0) {
		tp->t_state |= WOPEN;
		sleep((caddr_t)&tp->t_rawq, TTIPRI);
	}
	ttyopen(x,tp);
	spl0();
}

dzclose(dev)
{
	register struct tty *tp;

	dev = minor(dev);
	tp = &dz_tty[dev];
	wflushtty(tp);
	if (tp->t_state&HUPCLS) {
		dzmodem(dev, OFF);
	}
	tp->t_state &= CARR_ON;
}

dzread(dev)
{
	dev = minor(dev);
	ttread(&dz_tty[dev]);
}

dzwrite(dev)
{
	dev = minor(dev);
	ttwrite(&dz_tty[dev]);
}

dzioctl(dev, cmd, addr, flag)
{
	register struct tty *tp;

	dev = minor(dev);
	tp = &dz_tty[dev];
	if (ttioccomm(cmd, tp, (caddr_t)addr, dev)) {
		if (cmd==TIOCSETP||cmd==TIOCSETN)
			dzparam(dev);
	} else {
		u.u_error = ENOTTY;
	}
}

dzparam(dev)
{
	register struct tty *tp;
	register struct device *dzaddr;
	register lpr;

	tp = &dz_tty[dev];
	dzaddr= dz_addr[dev>>3];
	dzaddr->dzcsr = IE;
	if (dz_stat==0) {
		dzscan();
		dz_stat++;
	}
	if (tp->t_ispeed==0) {	/* Hang up line */
		dzmodem(dev, OFF);
		return;
	}
	lpr = (dz_speeds[tp->t_ispeed]<<8)|(dev&07);
	if (tp->t_flags&RAW)
		lpr |= BITS8;
	else
		lpr |= BITS7|PENABLE;
	if ((tp->t_flags&EVENP)==0)
		lpr |= OPAR;
	if (tp->t_ispeed == 3)	/* 110 baud */
		lpr |= TWOSB;
	dzaddr->dzlpr = lpr;
}

dzrint(dev)
{
	register struct tty *tp;
	register c;
	register struct device *dzaddr;

	dzaddr = dz_addr[dev];
	while ((c = dzaddr->dzrbuf) < 0) {	/* char. present */
		tp = &dz_tty[((c>>8)&07)|(dev<<3)];
		if (tp >= &dz_tty[dz_cnt])
			continue;
		if((tp->t_state&ISOPEN)==0) {
			wakeup((caddr_t)&tp->t_rawq);
			continue;
		}
		if (c&FRERROR)		/* break */
			if (tp->t_flags&RAW)
				c = 0;		/* null (for getty) */
			else
				c = 0177;	/* DEL (intr) */
		if (c&PERROR)
			if ((tp->t_flags&(EVENP|ODDP))==EVENP
			 || (tp->t_flags&(EVENP|ODDP))==ODDP )
				continue;
		ttyinput(c, tp);
	}
}

dzxint(dev)
{
	register struct tty *tp;
	register struct device *dzaddr;

	dzaddr = dz_addr[dev];
	while(dzaddr->dzcsr<0) {	/* TX rdy */
		tp = &dz_tty[((dev<<3)|(dzaddr->dzcsr>>8)&07)];
		dzaddr->dztbuf = tp->t_char;
		tp->t_state &= ~BUSY;
		dzstart(tp);
	}
}

dzstart(tp)
register struct tty *tp;
{
	register unit, c;
	int s;
	struct device *dzaddr;
	extern ttrstrt();

	unit = tp - dz_tty;
	dzaddr = dz_addr[unit>>3];
	unit = 1<<(unit&07);
	s = spl5();
	if (tp->t_state&(TIMEOUT|BUSY)) {
		splx(s);
		return;
	}
	if (tp->t_state&TTSTOP) {
		dzaddr->dztcr &= ~unit;
		splx(s);
		return;
	}
	if ((c=getc(&tp->t_outq)) >= 0) {
		if (c>=0200 && (tp->t_flags&RAW)==0) {
			dzaddr->dztcr &= ~unit;
			tp->t_state |= TIMEOUT;
			timeout(ttrstrt, (caddr_t)tp, (c&0177)+6);
		} else {
			tp->t_char = c;
			tp->t_state |= BUSY;
			dzaddr->dztcr |= unit;
		}
		if (tp->t_outq.c_cc<=TTLOWAT && tp->t_state&ASLEEP) {
			tp->t_state &= ~ASLEEP;
#ifdef	MX
			if (tp->t_chan)
				mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
			else
#endif	MX
				wakeup((caddr_t)&tp->t_outq);
		}
	} else
		dzaddr->dztcr &= ~unit;
	splx(s);
}

dzmodem(dev, flag)
{
	register struct device *dzaddr;
	register bit;

	dzaddr = dz_addr[dev>>3];
	bit = 1<<(dev&07);
	if (flag==OFF)
		dzaddr->dzdtr &= ~bit;
	else	dzaddr->dzdtr |= bit;
}

dzscan()
{
	register i;
	register struct device *dzaddr;
	register struct tty *tp;
	char	bit;
	short	bit1;

	for (i=0; i<dz_cnt; i++) {
		dzaddr = dz_addr[i>>3];
		tp = &dz_tty[i];
		bit = 1 << (i&07);
		bit1 = 1 << (i&017);
		if (dzaddr->dzmsr&bit || (tty_lt[i>>4] & bit1)) {
			if ((tp->t_state&CARR_ON)==0) {
				wakeup((caddr_t)&tp->t_rawq);
				tp->t_state |= CARR_ON;
			}
		} else {
			if (tp->t_state&CARR_ON) {
				if (tp->t_state&ISOPEN) {
					signal(tp->t_pgrp, SIGHUP);
					dzaddr->dzdtr &= ~bit;
					flushtty(tp);
				}
				tp->t_state &= ~CARR_ON;
			}
		}
	}
	timeout(dzscan, (caddr_t)0, 120);
}