
/* stick this in the LSI-11 */

#define DRC_ADDR	(struct drcdevice *) 0176670
#define DRC_TIMEOUT     3000

#define	DRC_CSR0	01	/* CSR bit 0 (to user dev) */
#define	DRC_CSR1	02	/* CSR bit 1 (to user dev) */
#define	DRC_IEB		040	/* INTER Enable B */
#define	DRC_IEA		0100	/* INTER Enable A */
#define	DRC_REQA	0200	/* REQ A line from user dev */
#define	DRC_REQB	0100000	/* REQ B line from user dev */

struct drcdevice {
	short	drccsr;
	short	drcobuf;
	short	drcibuf;
};

/*
 * Called from LSI-11 clock inter routine..
 * ib is a pointer for input buffer (short)
 * ob is a pointer for output buffer (short)
 * obwc is # of words to output.
 * this routine
 * 1) Interrupts VAX.
 * 2) writes "obwc" words from ob to it (16 bit words)
 * 3) reads words back from vax to "ib".
 * 4) returns count of words read if successful
 *    or "-1" for error (Vax or interface hung)
 */

dr11(ib,ob,obwc)
short *ib, *ob;
register obwc;
{
	register struct drcdevice *dp;
	register short ctr;
	register short *bp;

	dp = DRC_ADDR;
	dp->drccsr = 0;
	dp->drccsr = DRC_CSR1;	/* interrupt VAX (on his REQB) */
	ctr = DRC_TIMEOUT;
	while ((dp->drccsr & DRC_REQB) == 0) {
		if (--ctr == 0) {
			dp->drccsr = 0;
			return(-1);
		}
	}
	dp->drccsr = 0;
/*      ctr = DRC_TIMEOUT;      */
	while (dp->drccsr & DRC_REQB) {
		if (--ctr == 0) {
			dp->drccsr = 0;
			return(-2);
		}
	}
	dp->drccsr = 0;
	bp = ob;
	/*
	 * write obwc words to VAX from ob.
	 */
	while (obwc--) {
		dp->drcobuf = *bp++;
		dp->drccsr = DRC_CSR0;	/* set VAX REQA to say word rdy */
	/*      ctr = DRC_TIMEOUT;      */
		while ((dp->drccsr & DRC_REQA) == 0) {
			if (--ctr == 0) {
				dp->drccsr = 0;
				return(-3);
			}
		}
		dp->drccsr = 0;		/* Drop VAX REQA */
	 /*     ctr = DRC_TIMEOUT;      */
		while (dp->drccsr & DRC_REQA) {
			if (--ctr == 0) {
				dp->drccsr = 0;
				return(-4);
			}
		}
	}
	dp->drccsr = DRC_CSR1;	/* set VAX REQB to say EOF */

/*      ctr = DRC_TIMEOUT;      */
	while ((dp->drccsr & DRC_REQB) == 0) {
		if (--ctr == 0) {
			dp->drccsr = 0;
			return(-5);
		}
	}
	dp->drccsr = 0;	/* drop VAX REQB */
/*      ctr = DRC_TIMEOUT;      */
	while (dp->drccsr & DRC_REQB) {
		if (--ctr == 0) {
			dp->drccsr = 0;
			return(-6);
		}
	}

	/*
	 * read words from the VAX
	 */
	bp = ib;
	obwc = 0;

	while (1) {
		/*
		 * wait for REQA to set (when VAX loads buffer)
		 */
/*              ctr = DRC_TIMEOUT;      */
		while ((dp->drccsr & (DRC_REQA|DRC_REQB)) == 0) {
			if (--ctr == 0) {
				dp->drccsr = 0;
				return(-7);
			}
		}

		if (dp->drccsr & DRC_REQB) {	/* EOF read */
			dp->drccsr = DRC_CSR1;
	/*              ctr = DRC_TIMEOUT;      */
			while (dp->drccsr & DRC_REQB) {
				if (--ctr == 0) {
					dp->drccsr = 0;
					return(-8);
				}
			}
			dp->drccsr = 0;
			return(obwc);
		}
		*bp++ = dp->drcibuf;
		dp->drccsr = DRC_CSR0;	/* Tell the VAX the word was read */
		
		obwc++;
	/*      ctr = DRC_TIMEOUT;      */
		while (dp->drccsr & DRC_REQA) {
			if (--ctr == 0) {
				dp->drccsr = 0;
				return(-9);
			}
		}
		dp->drccsr = 0;
	}
}
