SRI-NOSC/dmr/misc/dhdm.c.ill

#
/*
 */

/*
 *	DM-BB driver
 */
#include "/usr/sys/h/param.h"
#include "/usr/sys/h/tty.h"
#include "/usr/sys/h/conf.h"

extern char dial[];
#define	DMADDR	0170500

struct	tty dh11[];
int	ndh11;		/* Set by dh.c to number of lines */

#define	DONE	0200
#define	SCENABL	040
#define SECINT	010000	/* secondary rcv transition */
#define	SECRCV	020	/* secondary rcv status */
#define	CLSCAN	01000
#define	TURNON	07	/* RQ send, CD lead, line enable */
#define	TURNOFF	1	/* line enable only */
#define	CARRIER	0100

struct dmregs {
	int	dmcsr;
	int	dmlstat;
};

/*
 * Turn on the line associated with the (DH) device dev.
 */
dmopen(dev)
{
	register struct tty *tp;
	register int line;

	line = dev.d_minor;
	if (line >= ndh11) line =- 16;
	if (dev.d_minor >= 32) return;
	tp = &dh11[dev.d_minor];
	DMADDR->dmcsr = line;
	DMADDR->dmlstat = TURNON;
	if (dial[line] && (line == dev.d_minor)) {
		if (DMADDR->dmlstat & SECRCV) {
			tp->t_state =| CARR_ON;
		}
	} else {
		if (DMADDR->dmlstat & CARRIER) {
			tp->t_state =| CARR_ON;
		}
	}
	DMADDR->dmcsr = IENABLE|SCENABL;
	spl5();
	while ((tp->t_state&CARR_ON)==0)
		sleep(&tp->t_rawq, TTIPRI);
	spl0();
}

/*
 * If a DH line has the HUPCL mode,
 * turn off carrier when it is closed.
 */
dmclose(dev)
{
	register struct tty *tp;
	register int line;

	line = dev.d_minor;
	if (line >= ndh11) line =- 16;
	if (dev.d_minor >= 32) return;
	tp = &dh11[dev.d_minor];
	if (tp->t_flags&HUPCL) {
		DMADDR->dmcsr = dev.d_minor;
		if (!dial[line]) {
			DMADDR->dmlstat = TURNOFF;
		}
		DMADDR->dmcsr = IENABLE|SCENABL;
	}
}

/*
 * DM11 interrupt.
 * Mainly, deal with carrier transitions.
 */
dmint()
{
	register struct tty *tp;
	register int line,state;

	if (DMADDR->dmcsr&DONE) {
		line = DMADDR->dmcsr&017;
		tp = &dh11[line];
		if (tp < &dh11[ndh11]) {
			state = DMADDR->dmlstat;
			if (dial[line]) {
			tp =+ 16;
				if (DMADDR->dmcsr & SECINT) {
					tp =- 16;
					if (state & SECRCV) {
						state = CARRIER;
					} else {
						state = 0;
					}
				}
			}
			wakeup(tp);
			if (!(state&CARRIER)) {
				if ((tp->t_state&WOPEN)==0) {
					signal(tp->t_pgrp, SIGHUP);
					if (!dial[line])
						DMADDR->dmlstat = 0;
					flushtty(tp);
				}
				tp->t_state =& ~CARR_ON;
			} else {
				tp->t_state =| CARR_ON;
				wakeup(&tp->t_rawq);
			}
		}
		DMADDR->dmcsr = IENABLE|SCENABL;
	}
}