#
/*
 */

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

#define	DMADDR	0170500

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

#define	IENABLE	0100	/* interrupt enable */
#define	DMBUSY	020	/* dm cycling */
#define	SCENABL	040
#define	TURNOFF	1	/* line enable only */

struct dmregs {
	int	dmcsr;
	int	dmlstat;
	int	dmfill1;
	int	dmfill2;
};

/*
 * Fetch and set modem control status.
 * Accessed via switch on ctlsw table in conf.c
 */
dhmctl(dev, action)
{
	register svcsr;
	register minor, dmaddr;
	int sps, status;

	minor = dev.d_minor & 0377;
	dmaddr = DMADDR + (minor>>4)*8;
	sps = PS->integ;
	spl5();
	while((svcsr = dmaddr->dmcsr)&DMBUSY)
		dmaddr->dmcsr =& ~SCENABL;
	dmaddr->dmcsr = minor & 017;
	if (action == FSTATUS)
		status = (dmaddr->dmlstat>>4)&07;
	else {
		dmaddr->dmlstat = dmbits(action);
		status = 0;
	}
	dmaddr->dmcsr = svcsr|(IENABLE|SCENABL);
	PS->integ = sps;
	return(status);
}

/*
 * DM11 interrupt. Pass modem status to line discipline routine.
 * Implement specified action.
 */
dmint(dev)
{
	register struct tty *tp;
	register action, dmaddr;
	int status;

	dmaddr = DMADDR + (dev*8);
	if (dmaddr->dmcsr&DONE) {
		tp = &dh11[(dev<<4) + (dmaddr->dmcsr&017)];
		dmaddr->dmcsr =& ~(DONE|SCENABL);
		if (tp < &dh11[ndh11]) {
			status = (dmaddr->dmlstat>>4)&07;
			action = (*linesw[tp->t_discp].l_mt)(tp, status);
			if (action != 0)
				dmaddr->dmlstat = dmbits(action);
		}
		dmaddr->dmcsr =| SCENABL;
	}
}

/*
 * Translate specified action into bits for dm line status register
 */
dmbits(action)
{
	register lstat;

	switch(action&03) {

	case DISABLE:
		lstat = 0;
		break;

	case HUP:
		lstat = TURNOFF;
		break;

	case TURNON:
	/*
	 * Set enable and data terminal ready. Set primary and secondary
	 * carrier status according to bits 2 and 3 of "action"
	 */
		lstat = action;
	}
	return(lstat);
}
