#

/*
 * DN-11 ACU interface
 */

#include "../head/param.h"
#include "../head/conf.h"
#include "../head/user.h"
#include "../head/userx.h"

struct {
	struct dnreg {
		int	dn_reg;
	} dnline[][4];
};

/*
 * This structure overlays the dnreg structure
 * 	dn_stat is unreferenced
 * 	dn_datum used to output the next digit to be dialed
 */

struct {
	char	dn_stat;
	char	dn_datum;
};

	int	ndn11	4;	/*number of dn11s...multiple of 4 */

#define	DNADDR	0175200
#define DN0MOD4	~3

#define	PWI	0100000
#define	ACR	040000
#define	DLO	010000
#define	DONE	0200
#define	IENABLE	0100
#define	DSS	040
#define	PND	020
#define	MENABLE	04
#define	DPR	02
#define	CRQ	01

#define	DNPRI	5

dnopen(dev, flag)
{
	register struct dnreg *dnadr;
	register int dn;

	dn = dev.d_minor;
	dnadr = DNADDR->dnline[0] + dn;

	if (dn >= ndn11 || dnadr->dn_reg&(PWI|DLO))
		u.u_error = ENXIO;
	else {
		(dnadr&DN0MOD4)->dn_reg =| MENABLE;
		dnadr->dn_reg = IENABLE|MENABLE|CRQ;
	}
}

dnclose(dev)
{
	DNADDR->dnline[0][dev.d_minor].dn_reg =& MENABLE;
}

dnwrite(dev)
{
	register struct dnreg *dnadr;
	register c;
	extern lbolt;

	dnadr = DNADDR->dnline[0] + dev.d_minor;
	while((dnadr->dn_reg & (PWI|ACR|DSS)) == 0) {
		if((dnadr->dn_reg&PND) == 0 || u.u_count == 0 || (c=cpass()) < 0)
			sleep(dnadr,DNPRI);
		else if(c == '-') {
			sleep(&lbolt,DNPRI);
			sleep(&lbolt,DNPRI);
		} else {
			dnadr->dn_datum = c;
			dnadr->dn_reg =| DPR;
			sleep(dnadr,DNPRI);
		}
	}
	if(dnadr->dn_reg&(PWI|ACR))
		u.u_error = EIO;
}

dnint(dev)
{
	register struct dnreg *dnadr;
	register count;

	dnadr = DNADDR->dnline[dev.d_minor];

	(dnadr&DN0MOD4)->dn_reg =& ~(MENABLE);
	(dnadr&DN0MOD4)->dn_reg =| MENABLE;
	count = 4;
	do {
		if(dnadr->dn_reg & DONE) {
			dnadr->dn_reg =& ~(DONE);
			wakeup(dnadr);
		}
	} while(dnadr++, --count);
}
