xref: /csrg-svn/sys/vax/datakit/dkit_dr.c (revision 45800)
138624Skarels /*
238624Skarels  * Datakit driver
338624Skarels  * DR11C version without KMC
438624Skarels  *
538624Skarels  * uses mbufs for transmission
638624Skarels  *
738624Skarels  *	SCCSID[] = "@(#)dkit_dr.c	1.5 Garage 84/04/11"
838624Skarels  */
938624Skarels 
1038624Skarels #include "dkitdr.h"
1138624Skarels #if NDKITDR>0
1238624Skarels #include "datakit.h"
1338624Skarels 
14*45800Sbostic #include "../include/pte.h"
15*45800Sbostic #include "sys/param.h"
16*45800Sbostic #include "sys/time.h"
17*45800Sbostic #include "sys/kernel.h"
18*45800Sbostic #include "sys/buf.h"
19*45800Sbostic #include "sys/mbuf.h"
20*45800Sbostic #include "sys/errno.h"
21*45800Sbostic #include "sys/socket.h"
22*45800Sbostic #include "sys/syslog.h"
23*45800Sbostic #include "net/if.h"
24*45800Sbostic #include "../uba/ubareg.h"
25*45800Sbostic #include "../uba/ubavar.h"
2638624Skarels 
2738624Skarels #include "dk.h"
2838624Skarels #include "dkit.h"
2938624Skarels #include "dkdr.h"
3038624Skarels 
3138624Skarels 
3238624Skarels #define PKBHOG		64		/* max temp buffers per channel	*/
3338624Skarels #define	DKNPKB	(200+4*NDATAKIT)
3438624Skarels #define	DKNSTB	10
3538624Skarels 
3638624Skarels struct dkchan	dkit[NDATAKIT];
3738624Skarels extern int	dk_nchan;
3838624Skarels 
3938624Skarels int	dkdr_npk	= DKNPKB;
4038624Skarels struct dkpkbufr	dk_pkbuf[DKNPKB];
4138624Skarels 
4238624Skarels int	dkdr_nstat	= DKNSTB;
4338624Skarels struct dkstat	dkdr_stat[DKNSTB];
4438624Skarels 
4538624Skarels int	dkattached = 0;			/* Is it really there? */
4638624Skarels 
4738624Skarels #ifdef	KALYPSO
4838624Skarels #define	URPDEBUG	5000
4938624Skarels #else
5038624Skarels #define	URPDEBUG	500
5138624Skarels #endif
5238624Skarels 
5338624Skarels #ifdef	URPDEBUG
5438624Skarels int	dkurpdebug = 0;
5538624Skarels #define	URPTRACE(chan, chr, Dkp)	if (dkurpdebug == (chan)) \
5638624Skarels 	dkurptrace(chr, Dkp);
5738624Skarels #endif
5838624Skarels 
5938624Skarels /*
6038624Skarels  * structure of data in first mbuf on chain (type DKM_HDR)
6138624Skarels  *
6238624Skarels  */
6338624Skarels struct	mpacket {
6438624Skarels 	short	mp_len;		/* Total length left */
6538624Skarels 	char	mp_ctl;		/* Control character */
6638624Skarels 	int	mp_eob;		/* Send end-of-block indicator */
6738624Skarels 	int	(*mp_endfcn)();	/* End-action function */
6838624Skarels 	caddr_t	mp_endparm;	/* Parameter to above function */
6938624Skarels };
7038624Skarels 
7138624Skarels /*
7238624Skarels  *	dr11-c bit definitions
7338624Skarels  */
7438624Skarels #define	DKTENAB	0100	/* transmit interrupt enable */
7538624Skarels #define	DKRENAB	040	/* receiver interrupt enable */
7638624Skarels #define	ENABS	0140	/* both enables */
7738624Skarels #define	DKCOM	03	/* dr11-c command bits */
7838624Skarels #define	DKTDONE	0200	/* transmit done bit */
7938624Skarels #define	DKRDONE	0100000	/* receiver done bit */
8038624Skarels #define	DKMARK	01000	/* start of packet bit */
8138624Skarels #define	DKOVF	040000	/* receiver overflow bit (in drin) */
8238624Skarels #define	DKDATA	0400	/* bit 9 ... indicates non-control */
8338624Skarels 
8438624Skarels #define DKCHUNK	16	/* packet size */
8538624Skarels 
8638624Skarels /*
8738624Skarels  * dr11c commands
8838624Skarels  */
8938624Skarels #define D_OSEQ  0
9038624Skarels #define D_READ  1
9138624Skarels #define D_WRITE 2
9238624Skarels #define D_XPACK 3
9338624Skarels 
9438624Skarels /*
9538624Skarels  *   error control protocol definitions
9638624Skarels  */
9738624Skarels #define	SEQ		0010	/* 8 sequence numbers to end trailers */
9838624Skarels #define	ECHO		0020	/* 8 echoes, data given to host */
9938624Skarels #define	REJ		0030	/* 8 rejections, transmission error */
10038624Skarels #define	ACK		0040	/* first of 8 acks, correct reception */
10138624Skarels #define	BOT		0050	/* normal beginning of trailer */
10238624Skarels #define	BOTM		0051	/* trailer with more data to follow */
10338624Skarels #define	BOTS		0052	/* seq update algorithm on this trailer */
10438624Skarels #define	SOI		0053	/* start of interrupt trailer */
10538624Skarels #define	EOI		0054	/* end of interrupt trailer */
10638624Skarels #define	ENQ		0055	/* xmitter request flow/error status */
10738624Skarels #define	CHECK		0056	/* xmitter request error status */
10838624Skarels #define	INITREQ		0057	/* request initialization */
10938624Skarels #define	INIT0		0060	/* disable trailer processing */
11038624Skarels #define	INIT1		0061	/* enable trailer processing */
11138624Skarels #define	AINIT		0062	/* response to INIT0/INIT1 */
11238624Skarels 
11338624Skarels #define	DKBMASK		03	/* this xmitter has window size of 4,  */
11438624Skarels /* #define	DKBLOCK		60	/* each message is 60 bytes            */
11538624Skarels #define	DKBLOCK		28	/* each message is 60 bytes            */
11638624Skarels 
11738624Skarels 
11838624Skarels /*
11938624Skarels  *   some commonly used macros
12038624Skarels  */
12138624Skarels 
12238624Skarels 
12338624Skarels 
12438624Skarels 	struct dkpkbufr		*dk_Sfree;
12538624Skarels 	extern int		dkdr_npk;
12638624Skarels 	extern struct dkpkbufr	dk_pkbuf[];
12738624Skarels 
12838624Skarels int	dknopkb = 1 ;		/* Counter for 'no dkpkbufr' condition.	*/
12938624Skarels int dkstray;	/* number of stray interrupts since last timeout */
13038624Skarels int	dkdrlostint;	/* Number of lost receiver interrupts */
13138624Skarels int dkdisabled;	/* flag to indicate that DK interface has been disabled
13238624Skarels 			due to stray interrupts, etc. */
13338624Skarels #define MAX_STRAY	10	/* maximum number of stray interrupts
13438624Skarels 				before temporarily disabling DK interrupts */
13538624Skarels 
13638624Skarels /*
13738624Skarels  * dr11c device registers
13838624Skarels  */
13938624Skarels struct rdevice {
14038624Skarels 	short	dkcsr;
14138624Skarels 	short	dko;
14238624Skarels 	short	dki;
14338624Skarels };
14438624Skarels 
14538624Skarels 	extern int		dkdr_nstat;
14638624Skarels 	extern struct dkstat	dkdr_stat[];
14738624Skarels 
14838624Skarels 	static char		Hstat, Tstat;
14938624Skarels 
15038624Skarels #define	DKADDR	((struct rdevice *) dkitdrdinfo[0]->ui_addr)
15138624Skarels 
15238624Skarels 
15338624Skarels /*
15438624Skarels  * Intermediate level command codes
15538624Skarels  */
15638624Skarels #define	KS_SEND		20
15738624Skarels #define	KS_RDB		21
15838624Skarels #define	KS_EOI		22
15938624Skarels #define	KS_CNTL		23
16038624Skarels #define	KS_ERR		24
16138624Skarels 
16238624Skarels 
16338624Skarels 
16438624Skarels int	dkdebug = 512 ;
16538624Skarels int	dkactive ;
16638624Skarels 
16738624Skarels static int	timeron;
16838624Skarels 
16938624Skarels 
17038624Skarels int	dkitdrprobe(), dkitdrattach();
17138624Skarels struct	uba_device *dkitdrdinfo[1];
17238624Skarels u_short	dkitdrstd[] = { 0 };
17338624Skarels struct	uba_driver dkitdrdriver =
17438624Skarels 	{ dkitdrprobe, 0, dkitdrattach, 0, dkitdrstd, "dkitdr", dkitdrdinfo };
17538624Skarels 
dkitdrprobe(reg)17638624Skarels dkitdrprobe(reg)
17738624Skarels caddr_t	reg;
17838624Skarels {
17938624Skarels 	register int	br, cvec;		/* value-result */
18038624Skarels 	register struct rdevice	*draddr = (struct rdevice *) reg;
18138624Skarels 	register int i, c;
18238624Skarels 
18338624Skarels #ifdef lint
18438624Skarels 	br = 0; cvec = br; br = cvec;
18538624Skarels 	dkdrrint(0); dkdrxint(0);
18638624Skarels #endif
18738624Skarels 	draddr->dkcsr = D_READ;
18838624Skarels 	for (i = 0; i < 1024; i++)
18938624Skarels 		if (draddr->dkcsr & DKRDONE) c = draddr->dki;
19038624Skarels 		else break;
19138624Skarels #ifdef lint
19238624Skarels 	c = c;
19338624Skarels #endif
19438624Skarels 	draddr->dkcsr = D_WRITE;
19538624Skarels 	draddr->dko = DKMARK | (dk_nchan-1);	/* pack on 511 */
19638624Skarels 	draddr->dkcsr = D_XPACK + DKTENAB;
19738624Skarels 	draddr->dko = 0;
19838624Skarels 	DELAY(10000);
19938624Skarels 	draddr->dkcsr = 0;
20038624Skarels 	return(sizeof(struct rdevice));
20138624Skarels }
20238624Skarels 
20338624Skarels /*ARGSUSED*/
20438624Skarels dkitdrattach(ui)
20538624Skarels 	struct uba_device	*ui;
20638624Skarels {
20738624Skarels 	dkattached = 1;
20838624Skarels 
20938624Skarels #if	defined(INET) && NDKI>0
21038624Skarels 	dkiattach();
21138624Skarels #endif
21238624Skarels }
21338624Skarels 
21438624Skarels 
21538624Skarels static
dk_init()21638624Skarels dk_init()
21738624Skarels {
21838624Skarels register struct rdevice *raddr = DKADDR;
21938624Skarels register s ;
22038624Skarels 	/*
22138624Skarels 	 *  At attach time for the hardware device
22238624Skarels 	 *  initialize and check things out to the
22338624Skarels 	 *  (grumble) limited extent that is possible.
22438624Skarels 	 */
22538624Skarels 
22638624Skarels 	s = spl5() ;
22738624Skarels 	Hstat = Tstat = 0 ;
22838624Skarels 	dkdisabled = 0;
22938624Skarels 	dkstray = 0;
23038624Skarels 	{
23138624Skarels 		register struct dkchan *dkp ;
23238624Skarels 
23338624Skarels 		for (dkp = &dkit[0]; dkp < &dkit[dk_nchan]; dkp++) {
23438624Skarels 			dkp->dk_rlen = 0 ;
23538624Skarels 			dkp->dk_xlen = 0 ;
23638624Skarels 			dkp->dk_X = XM_OFF;
23738624Skarels 			dkp->dk_rq = NULL ;
23838624Skarels 			dkp->dk_outq.ifq_len = 0;
23938624Skarels 			dkp->dk_outq.ifq_maxlen = 20;
24038624Skarels 			dkp->dk_outq.ifq_drops = 0;
24138624Skarels 			dkp->dk_outq.ifq_head = NULL;
24238624Skarels 			dkp->dk_outq.ifq_tail = NULL;
24338624Skarels 		}
24438624Skarels 	} {	register struct dkpkbufr *pkb ;
24538624Skarels 
24638624Skarels 		for (pkb = &dk_pkbuf[1]; pkb < &dk_pkbuf[dkdr_npk-1]; pkb++) {
24738624Skarels 			pkb->Pnext = pkb + 1 ;
24838624Skarels 		}
24938624Skarels 		dk_pkbuf[dkdr_npk-1].Pnext = NULL ;
25038624Skarels 		dk_Sfree = &dk_pkbuf[1] ;
25138624Skarels 		dk_pkbuf[0].Pnext = NULL ;
25238624Skarels 	} {
25338624Skarels 		register int seq, i, c ;
25438624Skarels 
25538624Skarels 		raddr->dkcsr = D_OSEQ ;
25638624Skarels 		raddr->dko = 0 ;		/* clears all FIFO's */
25738624Skarels 		seq = 0 ;
25838624Skarels 		while (raddr->dkcsr & DKTDONE) {
25938624Skarels 			seq += (((raddr->dki)>>10) & 017) + 2 ;
26038624Skarels 			if (seq > 100) {
26138624Skarels 				dkreport(KS_ERR, 0, 1, 0, 1) ;
26238624Skarels 				splx(s) ;
26338624Skarels 				return -EIO ;
26438624Skarels 			}
26538624Skarels 		}
26638624Skarels 		raddr->dkcsr = D_READ;
26738624Skarels 		for (i = 0; i < 1024; i++)
26838624Skarels 			if (raddr->dkcsr & DKRDONE) c = raddr->dki;
26938624Skarels 			else break;
27038624Skarels #ifdef lint
27138624Skarels 		c = c;
27238624Skarels #endif
27338624Skarels 	}
27438624Skarels 	raddr->dkcsr = ENABS ;
27538624Skarels 	if(!timeron){
27638624Skarels 		dk_timeout();
27738624Skarels 		timeron++;
27838624Skarels 	}
27938624Skarels 
28038624Skarels 	splx(s) ;
28138624Skarels 	dkactive = 1 ;
28238624Skarels 
28338624Skarels 
28438624Skarels 	return 0 ;
28538624Skarels }
28638624Skarels 
28738624Skarels /*ARGSUSED*/
dkitreset(uban)28838624Skarels dkitreset(uban)
28938624Skarels 	int uban;
29038624Skarels {
29138624Skarels register struct rdevice *raddr ;
29238624Skarels 
29338624Skarels 	raddr = DKADDR;
29438624Skarels 	raddr->dkcsr = ENABS;
29538624Skarels 	log(LOG_ERR, " dkit_dr%d", 0);
29638624Skarels }
29738624Skarels 
dk_open(chan,supfcn)29838624Skarels dk_open(chan, supfcn)
29938624Skarels register chan ;
30038624Skarels int (*supfcn)() ;
30138624Skarels {
30238624Skarels 	register struct	dkchan	*dkp;
30338624Skarels 	register	s ;
30438624Skarels 	extern 	dkkint() ;
30538624Skarels 	static	firsttime = 1;
30638624Skarels 	static	init;
30738624Skarels 	extern int commchan;
30838624Skarels 
30938624Skarels 	if (chan >= dk_nchan || !dkattached)
31038624Skarels 		return -ENXIO ;
31138624Skarels 	if (firsttime) {
31238624Skarels 		if ((init = dk_init()) < 0) return init;
31338624Skarels 		firsttime = 0;
31438624Skarels 	}
31538624Skarels 	dkp = &dkit[chan] ;
31638624Skarels 	s = spl5() ;
31738624Skarels 	/*
31838624Skarels 	 * Channel 0 (0-3 in ISN) is reserved for maintenance.
31938624Skarels 	 * An open on channel 0 is interpreted as a request
32038624Skarels 	 * for an unused channel.  Channel 1 (4 in ISN or RADIAN)
32138624Skarels 	 * is the common supervisory channel.
32238624Skarels 	 */
32338624Skarels 	if (chan == 0) {
32438624Skarels 		chan = commchan+1 ;		/* Start above commchan */
32538624Skarels 		while (1) {
32638624Skarels 			dkp = &dkit[chan] ;
32738624Skarels 			if (dkp->dk_state == 0)
32838624Skarels 				break ;
32938624Skarels 			chan++ ;
33038624Skarels 			if (chan >= dk_nchan) {
33138624Skarels 				splx(s) ;
33238624Skarels 				return -EADDRNOTAVAIL ;
33338624Skarels 			}
33438624Skarels 		}
33538624Skarels 	}
33638624Skarels 
33738624Skarels 
33838624Skarels 	/*
33938624Skarels 	 * Finish setting up dkp struct.
34038624Skarels 	 */
34138624Skarels 	if ((dkp->dk_state & DK_OPEN) ==0) {
34238624Skarels 		if (chan > dkdebug)
34338624Skarels 			log(LOG_ERR, "dkopen %d: %x\n", chan, supfcn) ;
34438624Skarels 		dkp->dk_S = 1 ;
34538624Skarels 		dkp->dk_R = 0 ;
34638624Skarels 		dkp->dk_X = 0 ;
34738624Skarels 		dkp->dk_A = 0 ;
34838624Skarels 		dkp->dk_rejcnt = 0;
34938624Skarels 		dkp->dk_srejcnt = 0;
35038624Skarels 		dkp->dk_ackrejcnt = 0;
35138624Skarels 		dkp->dk_enqcnt = 0;
35238624Skarels 		dksend(chan, INIT1) ;
35338624Skarels 		flushall(dkp, 0);
35438624Skarels 		dkp->dk_state &= ~DK_LINGR ;
35538624Skarels 		dkp->dk_state |= DK_OPEN;
35638624Skarels 	}
35738624Skarels 	dkp->dk_supfcn = supfcn ;
35838624Skarels 	splx(s) ;
35938624Skarels 	return chan ;
36038624Skarels }
36138624Skarels 
36238624Skarels 
36338624Skarels /*
36438624Skarels  * Close a channel:
36538624Skarels  */
36638624Skarels 
dk_close(chan)36738624Skarels dk_close(chan)
36838624Skarels {
36938624Skarels register struct	dkchan	*dkp;
37038624Skarels register s ;
37138624Skarels 
37238624Skarels 	s = spl5() ;
37338624Skarels 	if (chan > dkdebug)
37438624Skarels 		log(LOG_ERR, "dkclose %d\n", chan) ;
37538624Skarels 	dkp = &dkit[chan] ;
37638624Skarels 	if (chan == 0) {
37738624Skarels 		if (!dkattached) return -ENXIO;
37838624Skarels 		for (dkp = &dkit[1]; dkp < &dkit[dk_nchan]; dkp++) {
37938624Skarels 			if (dkp->dk_state & (DK_OPEN|DK_BUSY|DK_RCV)) {
38038624Skarels 				dkp->dk_state |= DK_RESET ;
38138624Skarels 				flushall(dkp, 0) ;
38238624Skarels 			}
38338624Skarels 		}
38438624Skarels 		dkactive = 0 ;
38538624Skarels 		splx(s);
38638624Skarels 		return dk_init() ;
38738624Skarels 	} else {
38838624Skarels 		dkp->dk_state |= DK_OPEN ;
38938624Skarels 		flushall(dkp, 0) ;
39038624Skarels 		dkp->dk_state = DK_LINGR ;
39138624Skarels 		dkp->dk_X = XM_OFF;
39238624Skarels 		dkp->dk_trmode = 0 ;
39338624Skarels 	}
39438624Skarels 	splx(s) ;
39538624Skarels 	return 0;
39638624Skarels }
39738624Skarels 
39838624Skarels /*
39938624Skarels  *	Close phase 2 - mark available for reassignment
40038624Skarels  */
dk_free(chan)40138624Skarels dk_free(chan)
40238624Skarels {
40338624Skarels 	if (chan > dkdebug)
40438624Skarels 		log(LOG_ERR, "dkfree %d\n", chan) ;
40538624Skarels 	dkit[chan].dk_state &= ~DK_LINGR ;
40638624Skarels }
40738624Skarels 
40838624Skarels 
40938624Skarels /*
41038624Skarels  *	Reset a channel
41138624Skarels  *	 prevents further I/O until close
41238624Skarels  */
dk_reset(chan)41338624Skarels dk_reset(chan)
41438624Skarels {
41538624Skarels register struct dkchan *dkp ;
41638624Skarels register s ;
41738624Skarels 
41838624Skarels 	if (chan > dkdebug)
41938624Skarels 		log(LOG_ERR, "dkreset %d\n", chan) ;
42038624Skarels 	s = spl5() ;
42138624Skarels 	dkp = &dkit[chan] ;
42238624Skarels 	dkp->dk_state |= DK_RESET ;
42338624Skarels 	flushall(dkp, 0) ;
42438624Skarels 	splx(s) ;
42538624Skarels }
42638624Skarels 
42738624Skarels 
42838624Skarels 
42938624Skarels /*
43038624Skarels  *	Xmit a short control (interrupt) packet
43138624Skarels  */
dk_xint(chan,intr)43238624Skarels dk_xint(chan, intr)
43338624Skarels {
43438624Skarels register struct rdevice *raddr ;
43538624Skarels register s ;
43638624Skarels register struct dkchan *dkp ;
43738624Skarels 
43838624Skarels 	dkp = &dkit[chan] ;
43938624Skarels 	if (chan == 0 || dkp->dk_X < XM_INIT)
44038624Skarels 		return -1 ;
44138624Skarels 	s = spl5() ;
44238624Skarels 	if (chan > dkdebug)
44338624Skarels 		log(LOG_ERR, "dkxint %d: %o %o\n", chan, (intr & 0377), ((intr >>8)&0377)) ;
44438624Skarels 	raddr = DKADDR ;
44538624Skarels 	raddr->dkcsr = D_WRITE ;
44638624Skarels 	raddr->dko = chan | DKMARK ;
44738624Skarels 	raddr->dko = SOI ;
44838624Skarels 	raddr->dko = (intr & 0377) | DKDATA ;
44938624Skarels 	raddr->dko = ((intr >> 8) & 0377) | DKDATA ;
45038624Skarels 	raddr->dko = EOI ;
45138624Skarels 	raddr->dkcsr = D_XPACK ;
45238624Skarels 	raddr->dko = 0 ;
45338624Skarels 	if(dkdisabled)
45438624Skarels 		raddr->dko = 0;
45538624Skarels 	else
45638624Skarels 		raddr->dko = ENABS;
45738624Skarels 	splx(s) ;
45838624Skarels 	return 0 ;
45938624Skarels }
46038624Skarels 
46138624Skarels 
46238624Skarels /*
46338624Skarels  * Adjust window size
46438624Skarels  */
46538624Skarels dk_winsize(chan, win)
46638624Skarels 	struct diocxwin win;
46738624Skarels {
46838624Skarels 	return EINVAL;		/* For now... */
46938624Skarels }
47038624Skarels 
47138624Skarels 
47238624Skarels /*
47338624Skarels  * Xmit data on a channel
47438624Skarels  *   NOTE * * * * *
47538624Skarels  *	Although it is never checked here, buffer addresses
47638624Skarels  *    in this version of the driver must be kernel addressable.
47738624Skarels  */
47838624Skarels dk_xmit(chan, m, eob, ctlchar, endfcn, endparm)
47938624Skarels struct mbuf *m ;
48038624Skarels int (*endfcn)() ;
48138624Skarels caddr_t endparm ;
48238624Skarels {
48338624Skarels 	register struct dkchan *dkp ;
48438624Skarels 	register struct mpacket *mbp ;
48538624Skarels 	register struct mbuf *mb;
48638624Skarels 	int s ;
48738624Skarels 
48838624Skarels 	s = spl5() ;
48938624Skarels 	dkp = &dkit[chan] ;
49038624Skarels 	if ((dkp->dk_state & DK_RESET) || (mb = m_get(M_DONTWAIT,DKMT_HDR)) == NULL) {
49138624Skarels 		m_freem(m);
49238624Skarels 		splx(s) ;
49338624Skarels 		return 0 ;
49438624Skarels 	}
49538624Skarels 
49638624Skarels 	if (ctlchar == '\001') eob = 0;
49738624Skarels 	mb->m_len = 0;
49838624Skarels 	mbp = mtod(mb, struct mpacket *);
49938624Skarels 	mbp->mp_endfcn = endfcn ;
50038624Skarels 	mbp->mp_endparm = endparm ;
50138624Skarels 	mbp->mp_eob = eob;
50238624Skarels 	mb->m_next = m;
50338624Skarels 
50438624Skarels 	mbp->mp_len = 0;
50538624Skarels 	while (m) {
50638624Skarels #ifdef notdef
50738624Skarels 		if (m->m_type != DKMT_DATA && m->m_type != DKMT_CTL) {
50838624Skarels 			log(LOG_ERR, "dk_xmit %d: got type %x\n", chan, m->m_type);
50938624Skarels 			m_freem(mb);
51038624Skarels 			return 0;
51138624Skarels 		}
51238624Skarels #endif
51338624Skarels 		mbp->mp_len += m->m_len;
51438624Skarels 		m = m->m_next;
51538624Skarels 	}
51638624Skarels 
51738624Skarels 	if ((ctlchar & 0300) == 0100) {
51838624Skarels 		register struct mbuf *n = mb, *mc;
51938624Skarels 
52038624Skarels 		mc = m_get(M_DONTWAIT, DKMT_CTL);
52138624Skarels 		if (mc == NULL) {
52238624Skarels 			m_freem(mb);
52338624Skarels 			splx(s);
52438624Skarels 			return 0;
52538624Skarels 		}
52638624Skarels 		*mtod(mc, char *) = ctlchar;
52738624Skarels 		mc->m_len = 1;
52838624Skarels 
52938624Skarels 		/* Append it -- can't use m_cat because type field counts */
53038624Skarels 		while (n->m_next) n = n->m_next;
53138624Skarels 		n->m_next = mc;
53238624Skarels 		mbp->mp_len++;
53338624Skarels 		ctlchar = 0;
53438624Skarels 	}
53538624Skarels 	mbp->mp_ctl = ctlchar;
53638624Skarels 
53738624Skarels 	if ((dkp->dk_state & DK_BUSY) == 0) {
53838624Skarels 		dkp->dk_state |= DK_BUSY ;
53938624Skarels 		dkp->dk_curout = mb;
54038624Skarels 		dkp->dk_xlen = mbp->mp_len ;
54138624Skarels 		if (chan > dkdebug)
54238624Skarels 			log(LOG_ERR, "xmit %d: %x len %d\n", chan,
54338624Skarels 			   mb->m_next, mbp->mp_len) ;
54438624Skarels 		dkxmit(dkp, chan, 2) ;
54538624Skarels 		splx(s) ;
54638624Skarels 		return dkp->dk_state ;
54738624Skarels 	}
54838624Skarels 	if (IF_QFULL(&dkp->dk_outq)) {
54938624Skarels 		IF_DROP(&dkp->dk_outq);
55038624Skarels 		m_freem(mb);
55138624Skarels 	}
55238624Skarels 	else
55338624Skarels 		IF_ENQUEUE(&dkp->dk_outq, mb);
55438624Skarels 	splx(s) ;
55538624Skarels 	return dkp->dk_state ;
55638624Skarels }
55738624Skarels 
55838624Skarels /*
55938624Skarels  * Receive into a block buffer
56038624Skarels  */
dk_recv(chan,addr,len,mode,endfcn,endparm)56138624Skarels dk_recv(chan, addr, len, mode, endfcn, endparm)
56238624Skarels caddr_t addr ;
56338624Skarels int (*endfcn)() ;
56438624Skarels caddr_t endparm ;
56538624Skarels {
56638624Skarels register struct dkchan *dkp ;
56738624Skarels register s ;
56838624Skarels 
56938624Skarels 	if (addr == 0) {
57038624Skarels 		log(LOG_ERR, "dk_recv: channel %d endfcn %x: invalid address specification\n", chan, endfcn);
57138624Skarels 		return 0;
57238624Skarels 	}
57338624Skarels 
57438624Skarels 	s = spl5() ;
57538624Skarels 	dkp = &dkit[chan] ;
57638624Skarels 	if (dkp->dk_state & (DK_RCV | DK_RESET)) {
57738624Skarels 		splx(s) ;
57838624Skarels 		return 0 ;
57938624Skarels 	}
58038624Skarels 	dkp->dk_state |= DK_RCV ;
58138624Skarels 	dkp->dk_endfcn = endfcn ;
58238624Skarels 	dkp->dk_endparm = endparm ;
58338624Skarels 	dkp->dk_rmode = mode ;
58438624Skarels 	dkp->dk_rlen = len ;
58538624Skarels 	dkp->dk_raddr = (caddr_t)addr ;
58638624Skarels 	if (chan > dkdebug)
58738624Skarels 		log(LOG_ERR, "dkrecv %d: %x len %d mode %o\n", chan, (caddr_t)addr, len, mode) ;
58838624Skarels 	dkrcv(dkp, chan, 2) ;
58938624Skarels 	splx(s) ;
59038624Skarels 	return dkp->dk_state ;
59138624Skarels }
59238624Skarels 
59338624Skarels 
59438624Skarels dk_rabort(chan, nendfcn, nendparm)
59538624Skarels int (*nendfcn)() ;
59638624Skarels caddr_t nendparm ;
59738624Skarels {
59838624Skarels register struct dkchan *dkp ;
59938624Skarels register s ;
60038624Skarels 
60138624Skarels 	dkp = &dkit[chan] ;
60238624Skarels 	s = spl5() ;
60338624Skarels 	if (dkp->dk_state & DK_RCV) {
60438624Skarels 		dkp->dk_state &= ~DK_RCV ;
60538624Skarels 		if (dkp->dk_rlen) {
60638624Skarels 			if (chan > dkdebug)
60738624Skarels 				log(LOG_ERR, "rcvabo %d: rlen %d\n", chan, dkp->dk_rlen) ;
60838624Skarels 			(*nendfcn)(nendparm, chan, dkp->dk_rlen, DKR_ABORT, 0) ;
60938624Skarels 		}
61038624Skarels 		dkp->dk_rlen = 0 ;
61138624Skarels 	}
61238624Skarels 	splx(s) ;
61338624Skarels 	return dkp->dk_state ;
61438624Skarels }
61538624Skarels 
61638624Skarels 
61738624Skarels 
dk_status(chan)61838624Skarels dk_status(chan)
61938624Skarels {
62038624Skarels 	if (chan >= dk_nchan)
62138624Skarels 		return 0 ;
62238624Skarels 	return dkit[chan].dk_state ;
62338624Skarels }
62438624Skarels 
62538624Skarels 
dk_timeout()62638624Skarels dk_timeout()
62738624Skarels {
62838624Skarels 	register struct rdevice *raddr;
62938624Skarels 	register struct	dkchan	*dkp;
63038624Skarels 	register chan ;
63138624Skarels 	int s = spl5();
63238624Skarels 
63338624Skarels 	chan = 0 ;
63438624Skarels 	for (dkp = &dkit[0]; dkp < &dkit[dk_nchan]; dkp++) {
63538624Skarels 		if (dkp->dk_X != XM_OFF) {
63638624Skarels 			if (dkp->dk_X == 0)
63738624Skarels 				dksend(chan, INIT1) ;
63838624Skarels 			else
63938624Skarels 			if (dkp->dk_S != ((dkp->dk_R + 1) & 07)) {
64038624Skarels 				if (dkp->dk_X & XM_ENQ) {
64138624Skarels 					dksend(chan, ENQ) ;
64238624Skarels 					dkp->dk_X &= ~XM_REJ ;
64338624Skarels 					dkp->dk_enqcnt++;
64438624Skarels 					URPTRACE(chan, ENQ, dkp);
64538624Skarels 				}
64638624Skarels 				else dkp->dk_X |= XM_ENQ;
64738624Skarels 			}
64838624Skarels 		}
64938624Skarels 		chan++ ;
65038624Skarels 	}
65138624Skarels 
65238624Skarels 	dkstray = 0;
65338624Skarels 	if(dkdisabled){
65438624Skarels 		if(dkdisabled++ > 10){
65538624Skarels 			/* try re-enabling interrupts */
65638624Skarels 			dkdisabled = 0;
65738624Skarels 			log(LOG_ERR, "re-enabling DK interface\n");
65838624Skarels 			raddr = DKADDR;
65938624Skarels 			raddr->dkcsr = ENABS;
66038624Skarels 		}
66138624Skarels 	}
66238624Skarels 	else {
66338624Skarels 		/* Look for lost interrupts */
66438624Skarels 		if (raddr->dkcsr < 0) {
66538624Skarels 			dkdrlostint++;
66638624Skarels 			dkdrxint(0);
66738624Skarels 		}
66838624Skarels 	}
66938624Skarels 
67038624Skarels 	timeout(dk_timeout, (caddr_t) 0, 1*hz);
67138624Skarels 	splx(s);
67238624Skarels }
67338624Skarels 
dk_cmd(chan,cmd)67438624Skarels dk_cmd(chan, cmd)
67538624Skarels {
67638624Skarels 	register struct dkchan *dkp ;
67738624Skarels 	int s = spl5();
67838624Skarels 
67938624Skarels 	if (chan > dkdebug)
68038624Skarels 		log(LOG_ERR, "dkcmd %d: %o\n", chan, cmd) ;
68138624Skarels 	dkp = &dkit[chan] ;
68238624Skarels 	if (cmd & DKC_XINIT) {
68338624Skarels 		dkp->dk_X = dkp->dk_R = dkp->dk_A = 0 ;
68438624Skarels 		dkp->dk_S = 1 ;
68538624Skarels 		dksend(chan, INIT1) ;
68638624Skarels 	}
68738624Skarels 	if (cmd & DKC_FLUSH) {
68838624Skarels 		flushall(dkp, -1) ;
68938624Skarels 	}
69038624Skarels 	if (cmd & DKC_SPND)
69138624Skarels 		dkp->dk_state |= DK_SPND ;
69238624Skarels 	if (cmd & DKC_RSME) {
69338624Skarels 		dkp->dk_state &= ~DK_SPND ;
69438624Skarels 		dkxmit(dkp, chan, 2) ;
69538624Skarels 	}
69638624Skarels 	splx(s);
69738624Skarels }
69838624Skarels 
69938624Skarels 
70038624Skarels static
flushall(dkp,rwflag)70138624Skarels flushall(dkp, rwflag)
70238624Skarels register struct dkchan *dkp ;
70338624Skarels {
70438624Skarels register s ;
70538624Skarels struct mpacket *mbp;
70638624Skarels 
70738624Skarels 	s = spl5() ;
70838624Skarels 	if ((dkp->dk_state & DK_RCV) && (rwflag >= 0)) {
70938624Skarels 		dkp->dk_state &= ~DK_RCV ;
71038624Skarels 		if (dkp->dk_endfcn)
71138624Skarels 			(*dkp->dk_endfcn)(dkp->dk_endparm, dkp-dkit, dkp->dk_rlen, DKR_ABORT, 0) ;
71238624Skarels 		dkp->dk_rlen = 0 ;
71338624Skarels 	}
71438624Skarels 	if ((dkp->dk_state & DK_BUSY) && (rwflag <= 0)) {
71538624Skarels 		register struct mbuf *m ;
71638624Skarels 
71738624Skarels 		dkp->dk_xlen = 0;
71838624Skarels 		if (dkp->dk_curout) {
71938624Skarels 			mbp = mtod(dkp->dk_curout, struct mpacket *);
72038624Skarels 			if (mbp->mp_endfcn)
72138624Skarels 				(mbp->mp_endfcn)(mbp->mp_endparm, dkp-dkit);
72238624Skarels 			m_freem(dkp->dk_curout);
72338624Skarels 			dkp->dk_curout = NULL;
72438624Skarels 		}
72538624Skarels 		while (1) {
72638624Skarels 			IF_DEQUEUE(&dkp->dk_outq, m);
72738624Skarels 			if (!m) break;
72838624Skarels 			mbp = mtod(m, struct mpacket *);
72938624Skarels 			if (mbp->mp_endfcn)
73038624Skarels 				(mbp->mp_endfcn)(mbp->mp_endparm, dkp-dkit);
73138624Skarels 			m_freem(m);
73238624Skarels 		}
73338624Skarels 		dkp->dk_state &= ~DK_BUSY ;
73438624Skarels 	}
73538624Skarels 	if ((dkp->dk_state & DK_OPEN) && (rwflag >= 0)) {
73638624Skarels 		register struct dkpkbufr *dbp ;
73738624Skarels 
73838624Skarels 		dkp->dk_rlen = 0 ;
73938624Skarels 		dkp->dk_xlen = 0 ;
74038624Skarels 		dkp->dk_C = 0 ;
74138624Skarels 		while (dbp = dkp->dk_rq) {
74238624Skarels 			dkp->dk_rq = dbp->Pnext ;
74338624Skarels 			dbp->Pnext = dk_Sfree ;
74438624Skarels 			dk_Sfree = dbp ;
74538624Skarels 		}
74638624Skarels 		while (dbp = dkp->dk_rb) {
74738624Skarels 			dkp->dk_rb = dbp->Pnext ;
74838624Skarels 			dbp->Pnext = dk_Sfree ;
74938624Skarels 			dk_Sfree = dbp ;
75038624Skarels 		}
75138624Skarels 	}
75238624Skarels 	splx(s) ;
75338624Skarels }
75438624Skarels 
75538624Skarels 
75638624Skarels /*
75738624Skarels  * Routine to handle completion status
75838624Skarels  */
75938624Skarels static
dkkint()76038624Skarels dkkint()
76138624Skarels {
76238624Skarels register struct dkchan *dkp;
76338624Skarels register struct dkstat *sp;
76438624Skarels register chan;
76538624Skarels struct mbuf *m ,*om;
76638624Skarels struct mpacket *mbp;
76738624Skarels static char *cmpltype[] = {"send", "rdb", "eoi", "cntl", "err"};
76838624Skarels 
76938624Skarels 	while (Tstat != Hstat) {
77038624Skarels 		sp = &dkdr_stat[Hstat];
77138624Skarels 		chan = sp->k_chan;
77238624Skarels 		dkp = &dkit[chan];
77338624Skarels 		if (sp->k_chan > dkdebug) {
77438624Skarels 			if (sp->k_type >= KS_SEND && sp->k_type <= KS_ERR)
77538624Skarels 				log(LOG_ERR, "dkdone:  type %s chan %d info %o-%o\n",
77638624Skarels 				    cmpltype[sp->k_type-KS_SEND],
77738624Skarels 				    sp->k_chan, sp->k_info1, sp->k_info2) ;
77838624Skarels 			else log(LOG_ERR, "dkdone:  type %d chan %d info %o-%o\n",
77938624Skarels 			    sp->k_type, sp->k_chan, sp->k_info1, sp->k_info2) ;
78038624Skarels 		}
78138624Skarels 		if (Hstat==dkdr_nstat-1)  Hstat=0; else Hstat++;
78238624Skarels 		switch(sp->k_type) {
78338624Skarels 		case KS_CNTL:
78438624Skarels 			if (dkp->dk_supfcn)
78538624Skarels 				(*dkp->dk_supfcn)(chan, sp->k_info1) ;
78638624Skarels 			break ;
78738624Skarels 		case KS_EOI:
78838624Skarels 			break ;
78938624Skarels 		case KS_SEND:
79038624Skarels 			om = dkp->dk_curout ;
79138624Skarels 			if (om == NULL) {
79238624Skarels 				log(LOG_ERR, "dkk: xbufout\n");
79338624Skarels 				break;
79438624Skarels 			}
79538624Skarels 			IF_DEQUEUE(&dkp->dk_outq, m);
79638624Skarels 			if (m == NULL) {
79738624Skarels 				dkp->dk_state &= ~DK_BUSY;
79838624Skarels 				dkp->dk_curout = NULL;
79938624Skarels 			} else {
80038624Skarels 				dkp->dk_curout = m;
80138624Skarels 				mbp = mtod(m, struct mpacket *);
80238624Skarels 				dkp->dk_xlen = mbp->mp_len ;
80338624Skarels 				if (chan > dkdebug)
80438624Skarels 					log(LOG_ERR, "xmiti %d: %x len %d\n", chan,
80538624Skarels 					   m->m_next, mbp->mp_len) ;
80638624Skarels 				dkxmit(dkp, chan, 0) ;
80738624Skarels 			}
80838624Skarels 			mbp = mtod(om, struct mpacket *);
80938624Skarels 			if (mbp->mp_endfcn != NULL)
81038624Skarels 				(mbp->mp_endfcn)(mbp->mp_endparm, chan) ;
81138624Skarels 			m_freem(om);
81238624Skarels 			break;
81338624Skarels 		case KS_RDB:
81438624Skarels 			dkp->dk_state &= ~(DK_RCV|DK_RCVQ) ;
81538624Skarels 			if (sp->k_info2 == DKR_TIME && dkp->dk_rlen == 0)
81638624Skarels 				break ;		/* another coming later */
81738624Skarels 			if (dkp->dk_rlen) {
81838624Skarels 				sp->k_info1 = dkp->dk_rlen ;
81938624Skarels 				dkp->dk_rlen = 0 ;
82038624Skarels 			}
82138624Skarels 			if (dkp->dk_endfcn != NULL)
82238624Skarels 				(*dkp->dk_endfcn)(dkp->dk_endparm, dkp-dkit, sp->k_info1, sp->k_info2&0377,
82338624Skarels 						(sp->k_info2>>8)&0377) ;
82438624Skarels 			break;
82538624Skarels 		case KS_ERR:
82638624Skarels 			log(LOG_ERR, "err in dkit.c: chan - %d, code - %o\n",
82738624Skarels 				chan, sp->k_info1);
82838624Skarels 			break;
82938624Skarels 		}	/* end switch */
83038624Skarels 
83138624Skarels 	}	/* end while */
83238624Skarels }
83338624Skarels 
83438624Skarels 
83538624Skarels 
83638624Skarels 
83738624Skarels 
83838624Skarels 
83938624Skarels 
84038624Skarels /* static */
84138624Skarels int	dkxmitpanic = 0;
84238624Skarels 
84338624Skarels dkxmit(dkp, stechan, intrpt)
84438624Skarels 	struct dkchan *dkp ;
84538624Skarels {
84638624Skarels 	register struct rdevice *raddr ;
84738624Skarels 	register char *ptr ;
84838624Skarels 	register struct mbuf *m;
84938624Skarels 	register int wtype;
85038624Skarels 	short pklen ;
85138624Skarels 	short mlen, unacked ;
85238624Skarels 	short blklen ;
85338624Skarels 	unsigned short totlen ;
85438624Skarels 	struct mpacket *mbp ;
85538624Skarels #ifdef notdef
85638624Skarels 	short scheck ;
85738624Skarels #endif
85838624Skarels 
85938624Skarels 	if( dkp->dk_curout == NULL || stechan ==0 )
86038624Skarels 		return ;
86138624Skarels 	mbp = mtod(dkp->dk_curout, struct mpacket *);
86238624Skarels 	raddr = DKADDR ;
86338624Skarels 	if ((dkp->dk_S & DKBMASK) == (dkp->dk_R & DKBMASK) || (dkp->dk_state & DK_SPND))
86438624Skarels 		goto ctlchk ;
86538624Skarels 	if ((dkp->dk_xlen || ((mbp->mp_ctl & 0200) == 0)) && dkp->dk_X < XM_INIT)
86638624Skarels 		goto ctlchk ;
86738624Skarels #ifdef notdef
86838624Skarels 	if ((dkp->dk_S & DKBMASK) == ((dkp->dk_R + 1) & DKBMASK))
86938624Skarels 		scheck = 0 ;
87038624Skarels 	else
87138624Skarels 		scheck = 1 ;
87238624Skarels #endif
87338624Skarels 
87438624Skarels 	unacked = ((dkp->dk_S - dkp->dk_A - 1) & 07) * DKBLOCK ;
87538624Skarels 	mlen = MIN(unacked, dkp->dk_xlen) ;
87638624Skarels 	totlen = dkp->dk_xlen - mlen;
87738624Skarels 	if (totlen == 0)
87838624Skarels 		goto ctlchk ;
87938624Skarels 
88038624Skarels 	/* Skip over stuff sent but not acked */
88138624Skarels 	for (m = dkp->dk_curout->m_next; m && (mlen > 0); m = m->m_next)
88238624Skarels 		if (mlen > m->m_len) mlen -= m->m_len;
88338624Skarels 		else break;
88438624Skarels 
88538624Skarels 	while (totlen && ((dkp->dk_S ^ dkp->dk_R) & DKBMASK)) {
88638624Skarels 		if (dkxmitpanic) panic("dkxmit -- panic 1");
88738624Skarels 		blklen = MIN (totlen, DKBLOCK) ;
88838624Skarels 		pklen = 0 ;
88938624Skarels 		raddr->dkcsr = D_WRITE ;
89038624Skarels 		raddr->dko = stechan | DKMARK ;
89138624Skarels 		while (blklen) {
89238624Skarels 			if (dkxmitpanic) panic("dkxmit -- panic 2");
89338624Skarels 			if (m == NULL) panic("dkxmit mlen");
89438624Skarels 			ptr = mtod(m, char *) + mlen;
89538624Skarels 			mlen = MIN(blklen, m->m_len - mlen);
89638624Skarels 			blklen -= mlen;
89738624Skarels 			wtype = (m->m_type == DKMT_CTL ? 0 : DKDATA);
89838624Skarels 			while (mlen--) {
89938624Skarels 				if (dkxmitpanic) panic("dkxmit -- panic 3");
90038624Skarels 				raddr->dko = (*ptr++ & 0377) | wtype ;
90138624Skarels 				pklen++ ;
90238624Skarels 				if ((pklen & (DKCHUNK-1)) == 0) {
90338624Skarels 					raddr->dkcsr = D_XPACK ;
90438624Skarels 					raddr->dko = 0 ;
90538624Skarels 					raddr->dkcsr = D_WRITE ;
90638624Skarels 					raddr->dko = stechan|DKMARK ;
90738624Skarels 				}
90838624Skarels 			}
90938624Skarels 			if (ptr == (mtod(m, char *) + m->m_len)) {
91038624Skarels 				m = m->m_next;
91138624Skarels 				mlen = 0;
91238624Skarels 			}
91338624Skarels 			else mlen = ptr - mtod(m, char *);
91438624Skarels 		}
91538624Skarels 		blklen = MIN (totlen, DKBLOCK) ;
91638624Skarels 		if ((pklen & (DKCHUNK-1)) > (DKCHUNK-4)) {
91738624Skarels 			raddr->dkcsr = D_XPACK ;
91838624Skarels 			raddr->dko = 0 ;
91938624Skarels 			raddr->dkcsr = D_WRITE ;
92038624Skarels 			raddr->dko = stechan|DKMARK ;
92138624Skarels 		}
92238624Skarels 		if (blklen == totlen && mbp->mp_eob)
92338624Skarels 			raddr->dko = BOT ;
92438624Skarels 		else
92538624Skarels 			raddr->dko = BOTM ;
92638624Skarels 		raddr->dko = (blklen & 0377) | DKDATA ;
92738624Skarels 		raddr->dko = ((blklen>>8) & 0377) | DKDATA ;
92838624Skarels 		raddr->dko = SEQ + dkp->dk_S ;
92938624Skarels 		raddr->dkcsr = D_XPACK ;
93038624Skarels 		raddr->dko = 0 ;
93138624Skarels 		URPTRACE(stechan, SEQ + dkp->dk_S, dkp);
93238624Skarels 		dkp->dk_S++ ;
93338624Skarels 		dkp->dk_S &= 07 ;
93438624Skarels 		totlen -= blklen ;
93538624Skarels 	}
93638624Skarels #ifdef notdef
93738624Skarels 	if (totlen == 0 && dkp->dk_xlen && scheck) {
93838624Skarels 		raddr->dkcsr = D_WRITE ;
93938624Skarels 		raddr->dko = stechan|DKMARK ;
94038624Skarels 		raddr->dko = CHECK ;
94138624Skarels 		raddr->dkcsr = D_XPACK ;
94238624Skarels 		raddr->dko = 0 ;
94338624Skarels 		URPTRACE(stechan, CHECK, dkp);
94438624Skarels 	}
94538624Skarels #endif
94638624Skarels ctlchk:
94738624Skarels 	if (mbp->mp_ctl & 0200) {
94838624Skarels 		raddr->dkcsr = D_WRITE ;
94938624Skarels 		raddr->dko = stechan|DKMARK ;
95038624Skarels 		raddr->dko = mbp->mp_ctl & 0377 ;
95138624Skarels 		raddr->dkcsr = D_XPACK ;
95238624Skarels 		raddr->dko = 0 ;
95338624Skarels 		mbp->mp_ctl = 0 ;
95438624Skarels 		if (dkp->dk_xlen == 0)
95538624Skarels 			dkreport(KS_SEND, stechan, 0, 0, intrpt) ;
95638624Skarels 	}
95738624Skarels 	if(dkdisabled)
95838624Skarels 		raddr->dkcsr = 0;
95938624Skarels 	else
96038624Skarels 		raddr->dkcsr = ENABS ;
96138624Skarels }
96238624Skarels 
96338624Skarels 
96438624Skarels static
96538624Skarels dkrcv(dkp, stechan, intrpt)
96638624Skarels struct dkchan *dkp ;
96738624Skarels {
96838624Skarels register char *ptr1 ;
96938624Skarels register char *ptr2 ;
97038624Skarels register len ;
97138624Skarels short final ;
97238624Skarels short hibits ;
97338624Skarels struct dkpkbufr *pkb ;
97438624Skarels short tlen ;
97538624Skarels 
97638624Skarels 	if ((dkp->dk_rlen == 0) || (dkp->dk_rq == NULL))
97738624Skarels 		return ;
97838624Skarels 	final = 0 ;
97938624Skarels 	tlen = 0 ;
98038624Skarels 	while (final == 0 && (pkb = dkp->dk_rq)) {
98138624Skarels 		if (dkp->dk_rlen == 0)
98238624Skarels 			final |= DKR_FULL ;
98338624Skarels 		ptr1 = &pkb->Pdata[0] ;
98438624Skarels 		ptr2 = dkp->dk_raddr ;
98538624Skarels 		len = MIN(pkb->Plen, dkp->dk_rlen) ;
98638624Skarels 		hibits = pkb->Phibits ;
98738624Skarels 		while (len--) {
98838624Skarels 			if (hibits < 0)
98938624Skarels 				break ;
99038624Skarels 			hibits <<= 1 ;
99138624Skarels 			*ptr2++ = *ptr1++ ;
99238624Skarels 		}
99338624Skarels 		len = ptr2 - dkp->dk_raddr ;
99438624Skarels 		tlen += len ;
99538624Skarels 		dkp->dk_rlen -= len ;
99638624Skarels 		dkp->dk_raddr = ptr2 ;
99738624Skarels 		if ((pkb->Plen -= len) && hibits < 0) {
99838624Skarels 			final |= ((*ptr1++ & 0377) << 8) | DKR_CNTL ;
99938624Skarels 			hibits <<= 1 ;
100038624Skarels 			pkb->Plen-- ;
100138624Skarels 		}
100238624Skarels 		if (len = pkb->Plen) {
100338624Skarels 			ptr2 = &pkb->Pdata[0] ;
100438624Skarels 			while (len--)
100538624Skarels 				*ptr2++ = *ptr1++ ;
100638624Skarels 			pkb->Phibits = hibits ;
100738624Skarels 		}
100838624Skarels 		while (pkb && (pkb->Plen == 0)) {
100938624Skarels 			if ((pkb->Pseq & 0370) == ACK) {
101038624Skarels 				pkb->Pseq += ECHO - ACK ;
101138624Skarels 				final |= dkp->dk_rmode & DKR_BLOCK ;
101238624Skarels 			}
101338624Skarels 			if (pkb->Pseq) {
101438624Skarels 				dksend(stechan, pkb->Pseq) ;
101538624Skarels 				dkp->dk_C = pkb->Pseq ;
101638624Skarels 			}
101738624Skarels 			dkp->dk_rq = pkb->Pnext ;
101838624Skarels 			pkb->Pnext = dk_Sfree ;
101938624Skarels 			dk_Sfree = pkb ;
102038624Skarels 			pkb = dkp->dk_rq ;
102138624Skarels 		}
102238624Skarels 	}
102338624Skarels 	if (tlen && (dkp->dk_rmode & DKR_TIME))
102438624Skarels 		final |= DKR_TIME ;
102538624Skarels 	if (dkp->dk_rlen == 0)
102638624Skarels 		final |= DKR_FULL ;
102738624Skarels 	if (final && (final != DKR_TIME || ((dkp->dk_state & DK_RCVQ) == 0))) {
102838624Skarels 		dkp->dk_state |= DK_RCVQ ;
102938624Skarels 		len = dkp->dk_rlen ;
103038624Skarels 		if (final != DKR_TIME)
103138624Skarels 			dkp->dk_rlen = 0 ;
103238624Skarels 		dkreport(KS_RDB, stechan, len, final, (final == DKR_TIME)?2:intrpt) ;
103338624Skarels 	}
103438624Skarels }
103538624Skarels 
103638624Skarels 
103738624Skarels 
103838624Skarels static
dksend(stechan,val)103938624Skarels dksend(stechan, val)
104038624Skarels {
104138624Skarels register struct rdevice *raddr ;
104238624Skarels register savcsr ;
104338624Skarels 
104438624Skarels 	if(stechan == 0)
104538624Skarels 		return;
104638624Skarels 
104738624Skarels 	raddr = DKADDR ;
104838624Skarels 	savcsr = raddr->dkcsr ;
104938624Skarels 	raddr->dkcsr = D_WRITE ;
105038624Skarels 	raddr->dko = stechan| DKMARK ;
105138624Skarels 	raddr->dko = val ;
105238624Skarels 	raddr->dkcsr = D_XPACK ;
105338624Skarels 	raddr->dko = 0 ;
105438624Skarels 	raddr->dkcsr = savcsr ;
105538624Skarels }
105638624Skarels 
105738624Skarels 
105838624Skarels /*ARGSUSED*/
dkdrrint(dev)105938624Skarels dkdrrint(dev)	/* ?? */		/* needed for UNIX OS */
106038624Skarels {
106138624Skarels register struct rdevice *raddr ;
106238624Skarels register c ;
106338624Skarels register cnt;
106438624Skarels 
106538624Skarels #ifdef lint
106638624Skarels 	c = 0; cnt = c;
106738624Skarels #endif
106838624Skarels 	cnt = 0;
106938624Skarels 	raddr = DKADDR ;
107038624Skarels 	raddr->dkcsr = D_OSEQ ;
107138624Skarels 	if((raddr->dkcsr & DKTDONE) == 0){
107238624Skarels 		if(dkstray++ >= MAX_STRAY){
107338624Skarels 			log(LOG_ERR, "DK err 1 (Cabling?)\n");
107438624Skarels 			raddr->dkcsr = 0;
107538624Skarels 			dkdisabled = 1;
107638624Skarels 			return;
107738624Skarels 		}
107838624Skarels 	}
107938624Skarels 	while (raddr->dkcsr & DKTDONE){
108038624Skarels 		c = raddr->dki ;
108138624Skarels 		if(cnt++ > 65){
108238624Skarels 			log(LOG_ERR, "DK err 2 (Cabling?)\n");
108338624Skarels 			raddr->dkcsr = 0;
108438624Skarels 			dkdisabled = 1;
108538624Skarels 			return;
108638624Skarels 		}
108738624Skarels 	}
108838624Skarels 	raddr->dkcsr = ENABS ;
108938624Skarels 	if (Hstat != Tstat)
109038624Skarels 		dkkint() ;
109138624Skarels }
109238624Skarels 
109338624Skarels /*ARGSUSED*/
dkdrxint(dev)109438624Skarels dkdrxint(dev)	/* ?? */
109538624Skarels {
109638624Skarels register struct rdevice *raddr ;
109738624Skarels register char *ptr ;
109838624Skarels struct dkchan  *dkp ;
109938624Skarels register c ;
110038624Skarels short badpacks ;
110138624Skarels struct dkpkbufr *pkb ;
110238624Skarels short stechan ;
110338624Skarels short	len, xlen ;
110438624Skarels unsigned short bitloc ;
110538624Skarels 
110638624Skarels 	badpacks = 0 ;
110738624Skarels 	raddr = DKADDR ;
110838624Skarels 	pkb = NULL ;
110938624Skarels 	if(raddr->dkcsr >= 0){
111038624Skarels 		if(dkstray++ > MAX_STRAY){
111138624Skarels 			log(LOG_ERR, "DK err 3 (Cabling?)\n");
111238624Skarels 			goto disable;
111338624Skarels 		}
111438624Skarels 	}
111538624Skarels 	while (raddr->dkcsr < 0) {
111638624Skarels 		raddr->dkcsr = D_READ ;
111738624Skarels 		c = raddr->dki ;
111838624Skarels 		while (raddr->dkcsr < 0 && (c & DKMARK)) {
111938624Skarels 			c &= 0777 ;
112038624Skarels 			if (c >= dk_nchan) {
112138624Skarels 				if (++badpacks > 20) {
112238624Skarels 					log(LOG_ERR, "DK err 4 (Cabling?)\n");
112338624Skarels 					dkreport(KS_ERR, 0, 2, 0, 1) ;
112438624Skarels 					goto disable ;
112538624Skarels 				}
112638624Skarels 				break ;
112738624Skarels 			}
112838624Skarels  			/* discard all chl 0 packets;
112938624Skarels 			 * the LDI version of the CPM-DR and CPM-422
113038624Skarels 			 * puts out packets on chl 0 occasionally.
113138624Skarels 			 */
113238624Skarels 			if(c == 0) break;
113338624Skarels 
113438624Skarels 			dkp = &dkit[c] ;
113538624Skarels 			stechan = c ;
113638624Skarels qpkb:
113738624Skarels 			if (pkb && pkb->Plen) {
113838624Skarels 				dkrcvq(stechan, dkp, pkb, 0) ;
113938624Skarels 				pkb = NULL ;
114038624Skarels 			}
114138624Skarels 			if (pkb == NULL) {
114238624Skarels 				if ((pkb = dk_Sfree) != NULL) {
114338624Skarels 					dk_Sfree = pkb->Pnext ;
114438624Skarels 					pkb->Pseq = 0 ;
114538624Skarels 					pkb->Plen = 0 ;
114638624Skarels 					pkb->Pnext = NULL ;
114738624Skarels 					pkb->Phibits = 0 ;
114838624Skarels 				} else {
114938624Skarels 					/*
115038624Skarels 					** Oops, no more dkpkbufr's.
115138624Skarels 					** Let outer loop gobble up
115238624Skarels 					** the entire packet.
115338624Skarels 					** Report to the console
115438624Skarels 					** every 100th occurrence.
115538624Skarels 					*/
115638624Skarels 					if ( dknopkb++ >= 100 ) {
115738624Skarels 						dknopkb = 1 ;
115838624Skarels 						dkreport(KS_ERR, 0, 3, 0, 1) ;
115938624Skarels 					}
116038624Skarels 					break ;
116138624Skarels 				}
116238624Skarels 			}
116338624Skarels 			raddr->dkcsr = D_READ ;
116438624Skarels 			ptr = &pkb->Pdata[0] ;
116538624Skarels 			bitloc = 0100000 ;
116638624Skarels 			while (raddr->dkcsr < 0 && ((c = raddr->dki) & DKMARK) == 0)
116738624Skarels 			switch (c = c & 0777) {
116838624Skarels 			case NULL:
116938624Skarels 				break ;
117038624Skarels 			case AINIT:
117138624Skarels 				dkp->dk_X = XM_INIT ;
117238624Skarels 				dkp->dk_R = 0 ;
117338624Skarels 				dkp->dk_S = 1 ;
117438624Skarels 				dkp->dk_A = 0 ;
117538624Skarels 				dkxmit(dkp, stechan, 1) ;
117638624Skarels 				raddr->dkcsr = D_READ ;
117738624Skarels 				break ;
117838624Skarels 			case INIT0:
117938624Skarels 				dksend(stechan, AINIT) ;
118038624Skarels 				dkp->dk_trmode = 0 ;
118138624Skarels 				dkp->dk_C = dkp->dk_rseq = 0 ;
118238624Skarels 				break ;
118338624Skarels 			case INIT1:
118438624Skarels 				dksend(stechan, AINIT) ;
118538624Skarels 				dkp->dk_trmode = 1 ;
118638624Skarels 				dkp->dk_C = dkp->dk_tail1 = dkp->dk_tail2 = dkp->dk_rseq = 0 ;
118738624Skarels 				while (pkb) {
118838624Skarels 					pkb->Pnext = dk_Sfree ;
118938624Skarels 					dk_Sfree = pkb ;
119038624Skarels 					if (pkb = dkp->dk_rq)
119138624Skarels 						dkp->dk_rq = pkb->Pnext ;
119238624Skarels 					if (pkb == NULL)
119338624Skarels 						if (pkb = dkp->dk_rb)
119438624Skarels 							dkp->dk_rb = pkb->Pnext ;
119538624Skarels 				}
119638624Skarels 				goto qpkb ;
119738624Skarels 			case INITREQ:
119838624Skarels 				dksend(stechan, INIT1) ;
119938624Skarels 				dkp->dk_X = 0 ;
120038624Skarels 				break ;
120138624Skarels 			case ENQ:
120238624Skarels 				dksend(stechan, dkp->dk_C) ;
120338624Skarels 			case CHECK:
120438624Skarels 				dksend(stechan, ACK+dkp->dk_rseq) ;
120538624Skarels 				while (pkb) {
120638624Skarels 					pkb->Pnext = dk_Sfree ;
120738624Skarels 					dk_Sfree = pkb ;
120838624Skarels 					if (pkb = dkp->dk_rb)
120938624Skarels 						dkp->dk_rb = pkb->Pnext ;
121038624Skarels 				}
121138624Skarels 				dkp->dk_rblen = 0 ;
121238624Skarels 				goto qpkb ;
121338624Skarels 			case EOI:
121438624Skarels 				if (dkp->dk_tail1 == ((SOI<<8)|2))
121538624Skarels 					dkreport(KS_EOI, stechan, dkp->dk_tail2, 0, 1) ;
121638624Skarels 				dkp->dk_tail1 = 0 ;
121738624Skarels 				break ;
121838624Skarels 			default:
121938624Skarels 				if (c & DKDATA) {
122038624Skarels 					if (dkp->dk_tail1) {
122138624Skarels 						dkp->dk_tail2 = ((dkp->dk_tail2 >> 8) & 0377) | (c<<8) ;
122238624Skarels 						dkp->dk_tail1++ ;
122338624Skarels 						if ((dkp->dk_tail1 & 0377) > 3)
122438624Skarels 							dkp->dk_tail1 = 0 ;
122538624Skarels 					} else {
122638624Skarels 						*ptr++ = c & 0377 ;
122738624Skarels 						pkb->Plen++ ;
122838624Skarels 						bitloc >>= 1 ;
122938624Skarels 					}
123038624Skarels 					break ;
123138624Skarels 				}
123238624Skarels 				if (((c & 0770) == ECHO) || ((c & 0770) == REJ)) {
123338624Skarels 					URPTRACE(stechan, c, dkp);
123438624Skarels 					dkp->dk_R = c & 07 ;
123538624Skarels 					if (((dkp->dk_S - dkp->dk_R - 1) & 07) <
123638624Skarels 					    ((dkp->dk_S - dkp->dk_A - 1) & 07)) {
123738624Skarels gotack:
123838624Skarels 						dkp->dk_X &= ~(XM_REJ | XM_ENQ);
123938624Skarels 						xlen = dkp->dk_xlen ;
124038624Skarels 						len = ((c - dkp->dk_A) & 07) * DKBLOCK ;
124138624Skarels 						len = MIN(len, xlen);
124238624Skarels 						dkp->dk_xlen -= len;
124338624Skarels 						if (dkp->dk_curout)
124438624Skarels 							m_adj(dkp->dk_curout->m_next, len) ;
124538624Skarels 						dkp->dk_A = c & 07 ;
124638624Skarels 						if (len || xlen)
124738624Skarels 							if ((dkp->dk_xlen) == 0)
124838624Skarels 								dkreport(KS_SEND, stechan, 0, 0, 1) ;
124938624Skarels 					}
125038624Skarels 					dkxmit(dkp, stechan, 1) ;
125138624Skarels 					raddr->dkcsr = D_READ ;
125238624Skarels 					if ((c & 0770) == REJ && ((dkp->dk_X & XM_REJ) == 0)) {
125338624Skarels 						dkp->dk_rejcnt++;
125438624Skarels gotrej:
125538624Skarels 						dkp->dk_S = (c+1) & 07 ;
125638624Skarels 						dkxmit(dkp, stechan, 1) ;
125738624Skarels 						raddr->dkcsr = D_READ ;
125838624Skarels 						dkp->dk_X |= XM_REJ ;
125938624Skarels 					}
126038624Skarels 					break ;
126138624Skarels 				}
126238624Skarels 				if ((c & 0770) == ACK) {
126338624Skarels 					URPTRACE(stechan, c, dkp);
126438624Skarels 					if (dkp->dk_A != (c & 07))
126538624Skarels 						goto gotack ;
126638624Skarels 					if ((dkp->dk_X & XM_REJ) == 0) {
126738624Skarels 						dkp->dk_ackrejcnt++;
126838624Skarels 						goto gotrej ;
126938624Skarels 					}
127038624Skarels 					break ;
127138624Skarels 				}
127238624Skarels 				if ((c & 0774) == BOT) {
127338624Skarels 					dkp->dk_tail1 = c << 8 ;
127438624Skarels 					break ;
127538624Skarels 				}
127638624Skarels 				if ((c & 0770) == SEQ) {
127738624Skarels 					pkb->Pseq = c - SEQ + ECHO ;
127838624Skarels 					dkrcvq(stechan, dkp, pkb, 0) ;
127938624Skarels 					if (dkp->dk_trmode) {
128038624Skarels 						if (dkp->dk_rblen == dkp->dk_tail2 &&
128138624Skarels 						    (dkp->dk_tail1 & 0377) == 2 &&
128238624Skarels 						    ((dkp->dk_tail1 >> 8) & 0377) != SOI &&
128338624Skarels 						    ((dkp->dk_rseq+1) & 07) == (c & 07)) {
128438624Skarels 							dkp->dk_rseq = c & 07 ;
128538624Skarels 							if (((dkp->dk_tail1>>8) & 0377) != BOTM)
128638624Skarels 								pkb->Pseq += ACK - ECHO ;
128738624Skarels 							dkrcvq(stechan, dkp, dkp->dk_rb, 1) ;
128838624Skarels 						} else {
128938624Skarels 							while (pkb = dkp->dk_rb) {
129038624Skarels 								dkp->dk_rb = pkb->Pnext ;
129138624Skarels 								pkb->Pnext = dk_Sfree ;
129238624Skarels 								dk_Sfree = pkb ;
129338624Skarels 							}
129438624Skarels 							pkb = dk_Sfree ;
129538624Skarels 							dk_Sfree = pkb->Pnext ;
129638624Skarels 							pkb->Plen = 0 ;
129738624Skarels 							pkb->Pnext = NULL ;
129838624Skarels 							pkb->Pseq = REJ + dkp->dk_rseq ;
129938624Skarels 							dkp->dk_srejcnt++;
130038624Skarels 							if (((dkp->dk_tail1>>8) & 0377) == BOTS)  {
130138624Skarels 								dkp->dk_rseq = c & 07 ;
130238624Skarels 								pkb->Pseq = ECHO + dkp->dk_rseq ;
130338624Skarels 							}
130438624Skarels 							dkrcvq(stechan, dkp, pkb, 1) ;
130538624Skarels 						}
130638624Skarels 						dkp->dk_rb = NULL ;
130738624Skarels 						dkp->dk_rblen = 0 ;
130838624Skarels 						dkp->dk_tail1 = 0 ;
130938624Skarels 					} else
131038624Skarels 						/* always keep seq no up to date */
131138624Skarels 						dkp->dk_rseq = c & 07;
131238624Skarels 					pkb = NULL ;
131338624Skarels 					goto qpkb ;
131438624Skarels 				}
131538624Skarels 				if (c & 0200) {
131638624Skarels 					dkreport(KS_CNTL, stechan, c, 0, 1) ;
131738624Skarels 					raddr->dkcsr = D_READ ;
131838624Skarels 				} else {
131938624Skarels 					*ptr++ = c & 0377 ;
132038624Skarels 					pkb->Plen++ ;
132138624Skarels 					pkb->Phibits |= bitloc ;
132238624Skarels 					bitloc >>= 1 ;
132338624Skarels 				}
132438624Skarels 			}
132538624Skarels 			if (pkb && pkb->Plen) {
132638624Skarels 				dkrcvq(stechan, dkp, pkb, 0) ;
132738624Skarels 				pkb = NULL ;
132838624Skarels 			}
132938624Skarels 		}
133038624Skarels 	}
133138624Skarels 
133238624Skarels 	if (pkb) {
133338624Skarels 		if (pkb->Plen)
133438624Skarels 			dkrcvq(stechan, dkp, pkb, 0) ;
133538624Skarels 		else {
133638624Skarels 			pkb->Pnext = dk_Sfree ;
133738624Skarels 			dk_Sfree = pkb ;
133838624Skarels 		}
133938624Skarels 	}
134038624Skarels 	raddr->dkcsr = ENABS ;
134138624Skarels 	return;
134238624Skarels 
134338624Skarels disable:
134438624Skarels 	if(pkb){
134538624Skarels 		pkb->Pnext = dk_Sfree;
134638624Skarels 		dk_Sfree = pkb;
134738624Skarels 	}
134838624Skarels 	raddr->dkcsr = 0;
134938624Skarels 	dkdisabled = 1;
135038624Skarels }
135138624Skarels 
dkrcvq(stechan,dkp,npkb,where)135238624Skarels dkrcvq(stechan, dkp, npkb, where)
135338624Skarels register struct dkchan *dkp ;
135438624Skarels struct dkpkbufr *npkb ;
135538624Skarels {
135638624Skarels register struct dkpkbufr *pkb ;
135738624Skarels 	int	i ;
135838624Skarels 
135938624Skarels 	i = 0 ;
136038624Skarels 	if (dkp->dk_trmode && where == 0)
136138624Skarels 		pkb = (struct dkpkbufr *)&dkp->dk_rb ;
136238624Skarels 	else
136338624Skarels 		pkb = (struct dkpkbufr *)&dkp->dk_rq ;
136438624Skarels 
136538624Skarels 	while (pkb->Pnext) {
136638624Skarels 		pkb = pkb->Pnext ;
136738624Skarels 		i++ ;
136838624Skarels 	}
136938624Skarels 	if ( i >= PKBHOG ) {
137038624Skarels 		/*
137138624Skarels 		** This channel has too many buffers.
137238624Skarels 		** Do not queue any more.
137338624Skarels 		** Return the new buffer to the free list.
137438624Skarels 		*/
137538624Skarels 		npkb->Pnext = dk_Sfree ;
137638624Skarels 		dk_Sfree = npkb ;
137738624Skarels 		return ;
137838624Skarels 	}
137938624Skarels 	pkb->Pnext = npkb ;
138038624Skarels 
138138624Skarels 	if (dkp->dk_trmode && where == 0)
138238624Skarels 		dkp->dk_rblen += npkb->Plen ;
138338624Skarels 	else
138438624Skarels 		dkrcv(dkp, stechan, 1) ;
138538624Skarels }
138638624Skarels 
138738624Skarels 
138838624Skarels 
dkreport(type,chan,info1,info2,intrpt)138938624Skarels dkreport(type, chan, info1, info2, intrpt)
139038624Skarels /*  intrpt parameter controlls whether the pdp-11 interrupt is called.
139138624Skarels  *  Value 0 says no (means dkxint queued already)
139238624Skarels  *  Value 1 says call it immediately (like from dr11c interrupt)
139338624Skarels  *  Value 2 says to queue a call as soon as processor priority lowers
139438624Skarels  *       (by sending a dummy packet on a channel and getting dkxint)
139538624Skarels  */
139638624Skarels {
139738624Skarels 	register struct dkstat	*sp;
139838624Skarels 
139938624Skarels 	if ((Tstat + 1) % dkdr_nstat == Hstat) {	/* room in queue? */
140038624Skarels 		log(LOG_ERR, "dkit_dr: No room in status queue, Channel %d\n", chan);
140138624Skarels 		return;
140238624Skarels 	}
140338624Skarels 
140438624Skarels 	sp = &dkdr_stat[Tstat] ;
140538624Skarels 	sp->k_chan = chan ;
140638624Skarels 	sp->k_type = type ;
140738624Skarels 	sp->k_info1 = info1 ;
140838624Skarels 	sp->k_info2 = info2 ;
140938624Skarels 	if (Tstat == dkdr_nstat-1)  Tstat = 0 ;  else Tstat++ ;
141038624Skarels 	if (intrpt==1) {
141138624Skarels 		dkkint() ;
141238624Skarels 	} else if (intrpt==2) {
141338624Skarels 		register struct rdevice *raddr ;
141438624Skarels 		raddr = DKADDR ;
141538624Skarels 		raddr->dkcsr = D_WRITE ;
141638624Skarels 
141738624Skarels 		/* Chl (dk_nchan-1) is used instead of 511 because
141838624Skarels 		 * the LDI switch module will complain if we use
141938624Skarels 		 * a chl outside the range set up in its route tables.
142038624Skarels 		 */
142138624Skarels 		raddr->dko = (dk_nchan-1) | DKMARK ;
142238624Skarels 
142338624Skarels 		/*
142438624Skarels 		 * A null is used here because it should always
142538624Skarels 		 * be ignored by the far end of the circuit.
142638624Skarels 		 */
142738624Skarels 		raddr->dko = 0 ;
142838624Skarels 
142938624Skarels 		raddr->dkcsr = D_XPACK ;
143038624Skarels 		raddr->dko = 0 ;
143138624Skarels 		raddr->dkcsr = ENABS ;
143238624Skarels 	}
143338624Skarels }
143438624Skarels 
143538624Skarels #ifdef	URPDEBUG
143638624Skarels struct	dkurps {
143738624Skarels 	char	dku_ctl;
143838624Skarels 	char	dku_S;
143938624Skarels 	char	dku_R;
144038624Skarels 	char	dku_A;
144138624Skarels } dkurps[URPDEBUG];
144238624Skarels int	dkurpsize = URPDEBUG;
144338624Skarels 
144438624Skarels struct	dkurps	*dkurpsp = dkurps;
144538624Skarels int	dkurpreset;
144638624Skarels 
dkurptrace(ctl,dkp)144738624Skarels dkurptrace(ctl, dkp) char ctl; register struct dkchan *dkp;
144838624Skarels {
144938624Skarels #ifdef lint
145038624Skarels 	dkurpsize = dkurpsize;
145138624Skarels #endif
145238624Skarels 	if (dkurpreset) {
145338624Skarels 		dkurpsp = dkurps;
145438624Skarels 		dkurpreset = 0;
145538624Skarels 	}
145638624Skarels 	dkurpsp->dku_ctl = ctl;
145738624Skarels 	dkurpsp->dku_S = dkp->dk_S;
145838624Skarels 	dkurpsp->dku_R = dkp->dk_R;
145938624Skarels 	dkurpsp->dku_A = dkp->dk_A;
146038624Skarels 	if (++dkurpsp == dkurps+URPDEBUG)
146138624Skarels 		dkurpsp = dkurps;
146238624Skarels }
146338624Skarels #endif	URPDEBUG
146438624Skarels #endif
1465