xref: /original-bsd/sys/vax/datakit/dkit_dr.c (revision b3f911e0)
1 /*
2  * Datakit driver
3  * DR11C version without KMC
4  *
5  * uses mbufs for transmission
6  *
7  *	SCCSID[] = "@(#)dkit_dr.c	1.5 Garage 84/04/11"
8  */
9 
10 #include "dkitdr.h"
11 #if NDKITDR>0
12 #include "datakit.h"
13 
14 #include "../machine/pte.h"
15 #include "param.h"
16 #include "time.h"
17 #include "kernel.h"
18 #include "buf.h"
19 #include "mbuf.h"
20 #include "errno.h"
21 #include "socket.h"
22 #include "syslog.h"
23 #include "../net/if.h"
24 #include "../vaxuba/ubareg.h"
25 #include "../vaxuba/ubavar.h"
26 
27 #include "dk.h"
28 #include "dkit.h"
29 #include "dkdr.h"
30 
31 
32 #define PKBHOG		64		/* max temp buffers per channel	*/
33 #define	DKNPKB	(200+4*NDATAKIT)
34 #define	DKNSTB	10
35 
36 struct dkchan	dkit[NDATAKIT];
37 extern int	dk_nchan;
38 
39 int	dkdr_npk	= DKNPKB;
40 struct dkpkbufr	dk_pkbuf[DKNPKB];
41 
42 int	dkdr_nstat	= DKNSTB;
43 struct dkstat	dkdr_stat[DKNSTB];
44 
45 int	dkattached = 0;			/* Is it really there? */
46 
47 #ifdef	KALYPSO
48 #define	URPDEBUG	5000
49 #else
50 #define	URPDEBUG	500
51 #endif
52 
53 #ifdef	URPDEBUG
54 int	dkurpdebug = 0;
55 #define	URPTRACE(chan, chr, Dkp)	if (dkurpdebug == (chan)) \
56 	dkurptrace(chr, Dkp);
57 #endif
58 
59 /*
60  * structure of data in first mbuf on chain (type DKM_HDR)
61  *
62  */
63 struct	mpacket {
64 	short	mp_len;		/* Total length left */
65 	char	mp_ctl;		/* Control character */
66 	int	mp_eob;		/* Send end-of-block indicator */
67 	int	(*mp_endfcn)();	/* End-action function */
68 	caddr_t	mp_endparm;	/* Parameter to above function */
69 };
70 
71 /*
72  *	dr11-c bit definitions
73  */
74 #define	DKTENAB	0100	/* transmit interrupt enable */
75 #define	DKRENAB	040	/* receiver interrupt enable */
76 #define	ENABS	0140	/* both enables */
77 #define	DKCOM	03	/* dr11-c command bits */
78 #define	DKTDONE	0200	/* transmit done bit */
79 #define	DKRDONE	0100000	/* receiver done bit */
80 #define	DKMARK	01000	/* start of packet bit */
81 #define	DKOVF	040000	/* receiver overflow bit (in drin) */
82 #define	DKDATA	0400	/* bit 9 ... indicates non-control */
83 
84 #define DKCHUNK	16	/* packet size */
85 
86 /*
87  * dr11c commands
88  */
89 #define D_OSEQ  0
90 #define D_READ  1
91 #define D_WRITE 2
92 #define D_XPACK 3
93 
94 /*
95  *   error control protocol definitions
96  */
97 #define	SEQ		0010	/* 8 sequence numbers to end trailers */
98 #define	ECHO		0020	/* 8 echoes, data given to host */
99 #define	REJ		0030	/* 8 rejections, transmission error */
100 #define	ACK		0040	/* first of 8 acks, correct reception */
101 #define	BOT		0050	/* normal beginning of trailer */
102 #define	BOTM		0051	/* trailer with more data to follow */
103 #define	BOTS		0052	/* seq update algorithm on this trailer */
104 #define	SOI		0053	/* start of interrupt trailer */
105 #define	EOI		0054	/* end of interrupt trailer */
106 #define	ENQ		0055	/* xmitter request flow/error status */
107 #define	CHECK		0056	/* xmitter request error status */
108 #define	INITREQ		0057	/* request initialization */
109 #define	INIT0		0060	/* disable trailer processing */
110 #define	INIT1		0061	/* enable trailer processing */
111 #define	AINIT		0062	/* response to INIT0/INIT1 */
112 
113 #define	DKBMASK		03	/* this xmitter has window size of 4,  */
114 /* #define	DKBLOCK		60	/* each message is 60 bytes            */
115 #define	DKBLOCK		28	/* each message is 60 bytes            */
116 
117 
118 /*
119  *   some commonly used macros
120  */
121 
122 
123 
124 	struct dkpkbufr		*dk_Sfree;
125 	extern int		dkdr_npk;
126 	extern struct dkpkbufr	dk_pkbuf[];
127 
128 int	dknopkb = 1 ;		/* Counter for 'no dkpkbufr' condition.	*/
129 int dkstray;	/* number of stray interrupts since last timeout */
130 int	dkdrlostint;	/* Number of lost receiver interrupts */
131 int dkdisabled;	/* flag to indicate that DK interface has been disabled
132 			due to stray interrupts, etc. */
133 #define MAX_STRAY	10	/* maximum number of stray interrupts
134 				before temporarily disabling DK interrupts */
135 
136 /*
137  * dr11c device registers
138  */
139 struct rdevice {
140 	short	dkcsr;
141 	short	dko;
142 	short	dki;
143 };
144 
145 	extern int		dkdr_nstat;
146 	extern struct dkstat	dkdr_stat[];
147 
148 	static char		Hstat, Tstat;
149 
150 #define	DKADDR	((struct rdevice *) dkitdrdinfo[0]->ui_addr)
151 
152 
153 /*
154  * Intermediate level command codes
155  */
156 #define	KS_SEND		20
157 #define	KS_RDB		21
158 #define	KS_EOI		22
159 #define	KS_CNTL		23
160 #define	KS_ERR		24
161 
162 
163 
164 int	dkdebug = 512 ;
165 int	dkactive ;
166 
167 static int	timeron;
168 
169 
170 int	dkitdrprobe(), dkitdrattach();
171 struct	uba_device *dkitdrdinfo[1];
172 u_short	dkitdrstd[] = { 0 };
173 struct	uba_driver dkitdrdriver =
174 	{ dkitdrprobe, 0, dkitdrattach, 0, dkitdrstd, "dkitdr", dkitdrdinfo };
175 
176 dkitdrprobe(reg)
177 caddr_t	reg;
178 {
179 	register int	br, cvec;		/* value-result */
180 	register struct rdevice	*draddr = (struct rdevice *) reg;
181 	register int i, c;
182 
183 #ifdef lint
184 	br = 0; cvec = br; br = cvec;
185 	dkdrrint(0); dkdrxint(0);
186 #endif
187 	draddr->dkcsr = D_READ;
188 	for (i = 0; i < 1024; i++)
189 		if (draddr->dkcsr & DKRDONE) c = draddr->dki;
190 		else break;
191 #ifdef lint
192 	c = c;
193 #endif
194 	draddr->dkcsr = D_WRITE;
195 	draddr->dko = DKMARK | (dk_nchan-1);	/* pack on 511 */
196 	draddr->dkcsr = D_XPACK + DKTENAB;
197 	draddr->dko = 0;
198 	DELAY(10000);
199 	draddr->dkcsr = 0;
200 	return(sizeof(struct rdevice));
201 }
202 
203 /*ARGSUSED*/
204 dkitdrattach(ui)
205 	struct uba_device	*ui;
206 {
207 	dkattached = 1;
208 
209 #if	defined(INET) && NDKI>0
210 	dkiattach();
211 #endif
212 }
213 
214 
215 static
216 dk_init()
217 {
218 register struct rdevice *raddr = DKADDR;
219 register s ;
220 	/*
221 	 *  At attach time for the hardware device
222 	 *  initialize and check things out to the
223 	 *  (grumble) limited extent that is possible.
224 	 */
225 
226 	s = spl5() ;
227 	Hstat = Tstat = 0 ;
228 	dkdisabled = 0;
229 	dkstray = 0;
230 	{
231 		register struct dkchan *dkp ;
232 
233 		for (dkp = &dkit[0]; dkp < &dkit[dk_nchan]; dkp++) {
234 			dkp->dk_rlen = 0 ;
235 			dkp->dk_xlen = 0 ;
236 			dkp->dk_X = XM_OFF;
237 			dkp->dk_rq = NULL ;
238 			dkp->dk_outq.ifq_len = 0;
239 			dkp->dk_outq.ifq_maxlen = 20;
240 			dkp->dk_outq.ifq_drops = 0;
241 			dkp->dk_outq.ifq_head = NULL;
242 			dkp->dk_outq.ifq_tail = NULL;
243 		}
244 	} {	register struct dkpkbufr *pkb ;
245 
246 		for (pkb = &dk_pkbuf[1]; pkb < &dk_pkbuf[dkdr_npk-1]; pkb++) {
247 			pkb->Pnext = pkb + 1 ;
248 		}
249 		dk_pkbuf[dkdr_npk-1].Pnext = NULL ;
250 		dk_Sfree = &dk_pkbuf[1] ;
251 		dk_pkbuf[0].Pnext = NULL ;
252 	} {
253 		register int seq, i, c ;
254 
255 		raddr->dkcsr = D_OSEQ ;
256 		raddr->dko = 0 ;		/* clears all FIFO's */
257 		seq = 0 ;
258 		while (raddr->dkcsr & DKTDONE) {
259 			seq += (((raddr->dki)>>10) & 017) + 2 ;
260 			if (seq > 100) {
261 				dkreport(KS_ERR, 0, 1, 0, 1) ;
262 				splx(s) ;
263 				return -EIO ;
264 			}
265 		}
266 		raddr->dkcsr = D_READ;
267 		for (i = 0; i < 1024; i++)
268 			if (raddr->dkcsr & DKRDONE) c = raddr->dki;
269 			else break;
270 #ifdef lint
271 		c = c;
272 #endif
273 	}
274 	raddr->dkcsr = ENABS ;
275 	if(!timeron){
276 		dk_timeout();
277 		timeron++;
278 	}
279 
280 	splx(s) ;
281 	dkactive = 1 ;
282 
283 
284 	return 0 ;
285 }
286 
287 /*ARGSUSED*/
288 dkitreset(uban)
289 	int uban;
290 {
291 register struct rdevice *raddr ;
292 
293 	raddr = DKADDR;
294 	raddr->dkcsr = ENABS;
295 	log(LOG_ERR, " dkit_dr%d", 0);
296 }
297 
298 dk_open(chan, supfcn)
299 register chan ;
300 int (*supfcn)() ;
301 {
302 	register struct	dkchan	*dkp;
303 	register	s ;
304 	extern 	dkkint() ;
305 	static	firsttime = 1;
306 	static	init;
307 	extern int commchan;
308 
309 	if (chan >= dk_nchan || !dkattached)
310 		return -ENXIO ;
311 	if (firsttime) {
312 		if ((init = dk_init()) < 0) return init;
313 		firsttime = 0;
314 	}
315 	dkp = &dkit[chan] ;
316 	s = spl5() ;
317 	/*
318 	 * Channel 0 (0-3 in ISN) is reserved for maintenance.
319 	 * An open on channel 0 is interpreted as a request
320 	 * for an unused channel.  Channel 1 (4 in ISN or RADIAN)
321 	 * is the common supervisory channel.
322 	 */
323 	if (chan == 0) {
324 		chan = commchan+1 ;		/* Start above commchan */
325 		while (1) {
326 			dkp = &dkit[chan] ;
327 			if (dkp->dk_state == 0)
328 				break ;
329 			chan++ ;
330 			if (chan >= dk_nchan) {
331 				splx(s) ;
332 				return -EADDRNOTAVAIL ;
333 			}
334 		}
335 	}
336 
337 
338 	/*
339 	 * Finish setting up dkp struct.
340 	 */
341 	if ((dkp->dk_state & DK_OPEN) ==0) {
342 		if (chan > dkdebug)
343 			log(LOG_ERR, "dkopen %d: %x\n", chan, supfcn) ;
344 		dkp->dk_S = 1 ;
345 		dkp->dk_R = 0 ;
346 		dkp->dk_X = 0 ;
347 		dkp->dk_A = 0 ;
348 		dkp->dk_rejcnt = 0;
349 		dkp->dk_srejcnt = 0;
350 		dkp->dk_ackrejcnt = 0;
351 		dkp->dk_enqcnt = 0;
352 		dksend(chan, INIT1) ;
353 		flushall(dkp, 0);
354 		dkp->dk_state &= ~DK_LINGR ;
355 		dkp->dk_state |= DK_OPEN;
356 	}
357 	dkp->dk_supfcn = supfcn ;
358 	splx(s) ;
359 	return chan ;
360 }
361 
362 
363 /*
364  * Close a channel:
365  */
366 
367 dk_close(chan)
368 {
369 register struct	dkchan	*dkp;
370 register s ;
371 
372 	s = spl5() ;
373 	if (chan > dkdebug)
374 		log(LOG_ERR, "dkclose %d\n", chan) ;
375 	dkp = &dkit[chan] ;
376 	if (chan == 0) {
377 		if (!dkattached) return -ENXIO;
378 		for (dkp = &dkit[1]; dkp < &dkit[dk_nchan]; dkp++) {
379 			if (dkp->dk_state & (DK_OPEN|DK_BUSY|DK_RCV)) {
380 				dkp->dk_state |= DK_RESET ;
381 				flushall(dkp, 0) ;
382 			}
383 		}
384 		dkactive = 0 ;
385 		splx(s);
386 		return dk_init() ;
387 	} else {
388 		dkp->dk_state |= DK_OPEN ;
389 		flushall(dkp, 0) ;
390 		dkp->dk_state = DK_LINGR ;
391 		dkp->dk_X = XM_OFF;
392 		dkp->dk_trmode = 0 ;
393 	}
394 	splx(s) ;
395 	return 0;
396 }
397 
398 /*
399  *	Close phase 2 - mark available for reassignment
400  */
401 dk_free(chan)
402 {
403 	if (chan > dkdebug)
404 		log(LOG_ERR, "dkfree %d\n", chan) ;
405 	dkit[chan].dk_state &= ~DK_LINGR ;
406 }
407 
408 
409 /*
410  *	Reset a channel
411  *	 prevents further I/O until close
412  */
413 dk_reset(chan)
414 {
415 register struct dkchan *dkp ;
416 register s ;
417 
418 	if (chan > dkdebug)
419 		log(LOG_ERR, "dkreset %d\n", chan) ;
420 	s = spl5() ;
421 	dkp = &dkit[chan] ;
422 	dkp->dk_state |= DK_RESET ;
423 	flushall(dkp, 0) ;
424 	splx(s) ;
425 }
426 
427 
428 
429 /*
430  *	Xmit a short control (interrupt) packet
431  */
432 dk_xint(chan, intr)
433 {
434 register struct rdevice *raddr ;
435 register s ;
436 register struct dkchan *dkp ;
437 
438 	dkp = &dkit[chan] ;
439 	if (chan == 0 || dkp->dk_X < XM_INIT)
440 		return -1 ;
441 	s = spl5() ;
442 	if (chan > dkdebug)
443 		log(LOG_ERR, "dkxint %d: %o %o\n", chan, (intr & 0377), ((intr >>8)&0377)) ;
444 	raddr = DKADDR ;
445 	raddr->dkcsr = D_WRITE ;
446 	raddr->dko = chan | DKMARK ;
447 	raddr->dko = SOI ;
448 	raddr->dko = (intr & 0377) | DKDATA ;
449 	raddr->dko = ((intr >> 8) & 0377) | DKDATA ;
450 	raddr->dko = EOI ;
451 	raddr->dkcsr = D_XPACK ;
452 	raddr->dko = 0 ;
453 	if(dkdisabled)
454 		raddr->dko = 0;
455 	else
456 		raddr->dko = ENABS;
457 	splx(s) ;
458 	return 0 ;
459 }
460 
461 
462 /*
463  * Adjust window size
464  */
465 dk_winsize(chan, win)
466 	struct diocxwin win;
467 {
468 	return EINVAL;		/* For now... */
469 }
470 
471 
472 /*
473  * Xmit data on a channel
474  *   NOTE * * * * *
475  *	Although it is never checked here, buffer addresses
476  *    in this version of the driver must be kernel addressable.
477  */
478 dk_xmit(chan, m, eob, ctlchar, endfcn, endparm)
479 struct mbuf *m ;
480 int (*endfcn)() ;
481 caddr_t endparm ;
482 {
483 	register struct dkchan *dkp ;
484 	register struct mpacket *mbp ;
485 	register struct mbuf *mb;
486 	int s ;
487 
488 	s = spl5() ;
489 	dkp = &dkit[chan] ;
490 	if ((dkp->dk_state & DK_RESET) || (mb = m_get(M_DONTWAIT,DKMT_HDR)) == NULL) {
491 		m_freem(m);
492 		splx(s) ;
493 		return 0 ;
494 	}
495 
496 	if (ctlchar == '\001') eob = 0;
497 	mb->m_len = 0;
498 	mbp = mtod(mb, struct mpacket *);
499 	mbp->mp_endfcn = endfcn ;
500 	mbp->mp_endparm = endparm ;
501 	mbp->mp_eob = eob;
502 	mb->m_next = m;
503 
504 	mbp->mp_len = 0;
505 	while (m) {
506 #ifdef notdef
507 		if (m->m_type != DKMT_DATA && m->m_type != DKMT_CTL) {
508 			log(LOG_ERR, "dk_xmit %d: got type %x\n", chan, m->m_type);
509 			m_freem(mb);
510 			return 0;
511 		}
512 #endif
513 		mbp->mp_len += m->m_len;
514 		m = m->m_next;
515 	}
516 
517 	if ((ctlchar & 0300) == 0100) {
518 		register struct mbuf *n = mb, *mc;
519 
520 		mc = m_get(M_DONTWAIT, DKMT_CTL);
521 		if (mc == NULL) {
522 			m_freem(mb);
523 			splx(s);
524 			return 0;
525 		}
526 		*mtod(mc, char *) = ctlchar;
527 		mc->m_len = 1;
528 
529 		/* Append it -- can't use m_cat because type field counts */
530 		while (n->m_next) n = n->m_next;
531 		n->m_next = mc;
532 		mbp->mp_len++;
533 		ctlchar = 0;
534 	}
535 	mbp->mp_ctl = ctlchar;
536 
537 	if ((dkp->dk_state & DK_BUSY) == 0) {
538 		dkp->dk_state |= DK_BUSY ;
539 		dkp->dk_curout = mb;
540 		dkp->dk_xlen = mbp->mp_len ;
541 		if (chan > dkdebug)
542 			log(LOG_ERR, "xmit %d: %x len %d\n", chan,
543 			   mb->m_next, mbp->mp_len) ;
544 		dkxmit(dkp, chan, 2) ;
545 		splx(s) ;
546 		return dkp->dk_state ;
547 	}
548 	if (IF_QFULL(&dkp->dk_outq)) {
549 		IF_DROP(&dkp->dk_outq);
550 		m_freem(mb);
551 	}
552 	else
553 		IF_ENQUEUE(&dkp->dk_outq, mb);
554 	splx(s) ;
555 	return dkp->dk_state ;
556 }
557 
558 /*
559  * Receive into a block buffer
560  */
561 dk_recv(chan, addr, len, mode, endfcn, endparm)
562 caddr_t addr ;
563 int (*endfcn)() ;
564 caddr_t endparm ;
565 {
566 register struct dkchan *dkp ;
567 register s ;
568 
569 	if (addr == 0) {
570 		log(LOG_ERR, "dk_recv: channel %d endfcn %x: invalid address specification\n", chan, endfcn);
571 		return 0;
572 	}
573 
574 	s = spl5() ;
575 	dkp = &dkit[chan] ;
576 	if (dkp->dk_state & (DK_RCV | DK_RESET)) {
577 		splx(s) ;
578 		return 0 ;
579 	}
580 	dkp->dk_state |= DK_RCV ;
581 	dkp->dk_endfcn = endfcn ;
582 	dkp->dk_endparm = endparm ;
583 	dkp->dk_rmode = mode ;
584 	dkp->dk_rlen = len ;
585 	dkp->dk_raddr = (caddr_t)addr ;
586 	if (chan > dkdebug)
587 		log(LOG_ERR, "dkrecv %d: %x len %d mode %o\n", chan, (caddr_t)addr, len, mode) ;
588 	dkrcv(dkp, chan, 2) ;
589 	splx(s) ;
590 	return dkp->dk_state ;
591 }
592 
593 
594 dk_rabort(chan, nendfcn, nendparm)
595 int (*nendfcn)() ;
596 caddr_t nendparm ;
597 {
598 register struct dkchan *dkp ;
599 register s ;
600 
601 	dkp = &dkit[chan] ;
602 	s = spl5() ;
603 	if (dkp->dk_state & DK_RCV) {
604 		dkp->dk_state &= ~DK_RCV ;
605 		if (dkp->dk_rlen) {
606 			if (chan > dkdebug)
607 				log(LOG_ERR, "rcvabo %d: rlen %d\n", chan, dkp->dk_rlen) ;
608 			(*nendfcn)(nendparm, chan, dkp->dk_rlen, DKR_ABORT, 0) ;
609 		}
610 		dkp->dk_rlen = 0 ;
611 	}
612 	splx(s) ;
613 	return dkp->dk_state ;
614 }
615 
616 
617 
618 dk_status(chan)
619 {
620 	if (chan >= dk_nchan)
621 		return 0 ;
622 	return dkit[chan].dk_state ;
623 }
624 
625 
626 dk_timeout()
627 {
628 	register struct rdevice *raddr;
629 	register struct	dkchan	*dkp;
630 	register chan ;
631 	int s = spl5();
632 
633 	chan = 0 ;
634 	for (dkp = &dkit[0]; dkp < &dkit[dk_nchan]; dkp++) {
635 		if (dkp->dk_X != XM_OFF) {
636 			if (dkp->dk_X == 0)
637 				dksend(chan, INIT1) ;
638 			else
639 			if (dkp->dk_S != ((dkp->dk_R + 1) & 07)) {
640 				if (dkp->dk_X & XM_ENQ) {
641 					dksend(chan, ENQ) ;
642 					dkp->dk_X &= ~XM_REJ ;
643 					dkp->dk_enqcnt++;
644 					URPTRACE(chan, ENQ, dkp);
645 				}
646 				else dkp->dk_X |= XM_ENQ;
647 			}
648 		}
649 		chan++ ;
650 	}
651 
652 	dkstray = 0;
653 	if(dkdisabled){
654 		if(dkdisabled++ > 10){
655 			/* try re-enabling interrupts */
656 			dkdisabled = 0;
657 			log(LOG_ERR, "re-enabling DK interface\n");
658 			raddr = DKADDR;
659 			raddr->dkcsr = ENABS;
660 		}
661 	}
662 	else {
663 		/* Look for lost interrupts */
664 		if (raddr->dkcsr < 0) {
665 			dkdrlostint++;
666 			dkdrxint(0);
667 		}
668 	}
669 
670 	timeout(dk_timeout, (caddr_t) 0, 1*hz);
671 	splx(s);
672 }
673 
674 dk_cmd(chan, cmd)
675 {
676 	register struct dkchan *dkp ;
677 	int s = spl5();
678 
679 	if (chan > dkdebug)
680 		log(LOG_ERR, "dkcmd %d: %o\n", chan, cmd) ;
681 	dkp = &dkit[chan] ;
682 	if (cmd & DKC_XINIT) {
683 		dkp->dk_X = dkp->dk_R = dkp->dk_A = 0 ;
684 		dkp->dk_S = 1 ;
685 		dksend(chan, INIT1) ;
686 	}
687 	if (cmd & DKC_FLUSH) {
688 		flushall(dkp, -1) ;
689 	}
690 	if (cmd & DKC_SPND)
691 		dkp->dk_state |= DK_SPND ;
692 	if (cmd & DKC_RSME) {
693 		dkp->dk_state &= ~DK_SPND ;
694 		dkxmit(dkp, chan, 2) ;
695 	}
696 	splx(s);
697 }
698 
699 
700 static
701 flushall(dkp, rwflag)
702 register struct dkchan *dkp ;
703 {
704 register s ;
705 struct mpacket *mbp;
706 
707 	s = spl5() ;
708 	if ((dkp->dk_state & DK_RCV) && (rwflag >= 0)) {
709 		dkp->dk_state &= ~DK_RCV ;
710 		if (dkp->dk_endfcn)
711 			(*dkp->dk_endfcn)(dkp->dk_endparm, dkp-dkit, dkp->dk_rlen, DKR_ABORT, 0) ;
712 		dkp->dk_rlen = 0 ;
713 	}
714 	if ((dkp->dk_state & DK_BUSY) && (rwflag <= 0)) {
715 		register struct mbuf *m ;
716 
717 		dkp->dk_xlen = 0;
718 		if (dkp->dk_curout) {
719 			mbp = mtod(dkp->dk_curout, struct mpacket *);
720 			if (mbp->mp_endfcn)
721 				(mbp->mp_endfcn)(mbp->mp_endparm, dkp-dkit);
722 			m_freem(dkp->dk_curout);
723 			dkp->dk_curout = NULL;
724 		}
725 		while (1) {
726 			IF_DEQUEUE(&dkp->dk_outq, m);
727 			if (!m) break;
728 			mbp = mtod(m, struct mpacket *);
729 			if (mbp->mp_endfcn)
730 				(mbp->mp_endfcn)(mbp->mp_endparm, dkp-dkit);
731 			m_freem(m);
732 		}
733 		dkp->dk_state &= ~DK_BUSY ;
734 	}
735 	if ((dkp->dk_state & DK_OPEN) && (rwflag >= 0)) {
736 		register struct dkpkbufr *dbp ;
737 
738 		dkp->dk_rlen = 0 ;
739 		dkp->dk_xlen = 0 ;
740 		dkp->dk_C = 0 ;
741 		while (dbp = dkp->dk_rq) {
742 			dkp->dk_rq = dbp->Pnext ;
743 			dbp->Pnext = dk_Sfree ;
744 			dk_Sfree = dbp ;
745 		}
746 		while (dbp = dkp->dk_rb) {
747 			dkp->dk_rb = dbp->Pnext ;
748 			dbp->Pnext = dk_Sfree ;
749 			dk_Sfree = dbp ;
750 		}
751 	}
752 	splx(s) ;
753 }
754 
755 
756 /*
757  * Routine to handle completion status
758  */
759 static
760 dkkint()
761 {
762 register struct dkchan *dkp;
763 register struct dkstat *sp;
764 register chan;
765 struct mbuf *m ,*om;
766 struct mpacket *mbp;
767 static char *cmpltype[] = {"send", "rdb", "eoi", "cntl", "err"};
768 
769 	while (Tstat != Hstat) {
770 		sp = &dkdr_stat[Hstat];
771 		chan = sp->k_chan;
772 		dkp = &dkit[chan];
773 		if (sp->k_chan > dkdebug) {
774 			if (sp->k_type >= KS_SEND && sp->k_type <= KS_ERR)
775 				log(LOG_ERR, "dkdone:  type %s chan %d info %o-%o\n",
776 				    cmpltype[sp->k_type-KS_SEND],
777 				    sp->k_chan, sp->k_info1, sp->k_info2) ;
778 			else log(LOG_ERR, "dkdone:  type %d chan %d info %o-%o\n",
779 			    sp->k_type, sp->k_chan, sp->k_info1, sp->k_info2) ;
780 		}
781 		if (Hstat==dkdr_nstat-1)  Hstat=0; else Hstat++;
782 		switch(sp->k_type) {
783 		case KS_CNTL:
784 			if (dkp->dk_supfcn)
785 				(*dkp->dk_supfcn)(chan, sp->k_info1) ;
786 			break ;
787 		case KS_EOI:
788 			break ;
789 		case KS_SEND:
790 			om = dkp->dk_curout ;
791 			if (om == NULL) {
792 				log(LOG_ERR, "dkk: xbufout\n");
793 				break;
794 			}
795 			IF_DEQUEUE(&dkp->dk_outq, m);
796 			if (m == NULL) {
797 				dkp->dk_state &= ~DK_BUSY;
798 				dkp->dk_curout = NULL;
799 			} else {
800 				dkp->dk_curout = m;
801 				mbp = mtod(m, struct mpacket *);
802 				dkp->dk_xlen = mbp->mp_len ;
803 				if (chan > dkdebug)
804 					log(LOG_ERR, "xmiti %d: %x len %d\n", chan,
805 					   m->m_next, mbp->mp_len) ;
806 				dkxmit(dkp, chan, 0) ;
807 			}
808 			mbp = mtod(om, struct mpacket *);
809 			if (mbp->mp_endfcn != NULL)
810 				(mbp->mp_endfcn)(mbp->mp_endparm, chan) ;
811 			m_freem(om);
812 			break;
813 		case KS_RDB:
814 			dkp->dk_state &= ~(DK_RCV|DK_RCVQ) ;
815 			if (sp->k_info2 == DKR_TIME && dkp->dk_rlen == 0)
816 				break ;		/* another coming later */
817 			if (dkp->dk_rlen) {
818 				sp->k_info1 = dkp->dk_rlen ;
819 				dkp->dk_rlen = 0 ;
820 			}
821 			if (dkp->dk_endfcn != NULL)
822 				(*dkp->dk_endfcn)(dkp->dk_endparm, dkp-dkit, sp->k_info1, sp->k_info2&0377,
823 						(sp->k_info2>>8)&0377) ;
824 			break;
825 		case KS_ERR:
826 			log(LOG_ERR, "err in dkit.c: chan - %d, code - %o\n",
827 				chan, sp->k_info1);
828 			break;
829 		}	/* end switch */
830 
831 	}	/* end while */
832 }
833 
834 
835 
836 
837 
838 
839 
840 /* static */
841 int	dkxmitpanic = 0;
842 
843 dkxmit(dkp, stechan, intrpt)
844 	struct dkchan *dkp ;
845 {
846 	register struct rdevice *raddr ;
847 	register char *ptr ;
848 	register struct mbuf *m;
849 	register int wtype;
850 	short pklen ;
851 	short mlen, unacked ;
852 	short blklen ;
853 	unsigned short totlen ;
854 	struct mpacket *mbp ;
855 #ifdef notdef
856 	short scheck ;
857 #endif
858 
859 	if( dkp->dk_curout == NULL || stechan ==0 )
860 		return ;
861 	mbp = mtod(dkp->dk_curout, struct mpacket *);
862 	raddr = DKADDR ;
863 	if ((dkp->dk_S & DKBMASK) == (dkp->dk_R & DKBMASK) || (dkp->dk_state & DK_SPND))
864 		goto ctlchk ;
865 	if ((dkp->dk_xlen || ((mbp->mp_ctl & 0200) == 0)) && dkp->dk_X < XM_INIT)
866 		goto ctlchk ;
867 #ifdef notdef
868 	if ((dkp->dk_S & DKBMASK) == ((dkp->dk_R + 1) & DKBMASK))
869 		scheck = 0 ;
870 	else
871 		scheck = 1 ;
872 #endif
873 
874 	unacked = ((dkp->dk_S - dkp->dk_A - 1) & 07) * DKBLOCK ;
875 	mlen = MIN(unacked, dkp->dk_xlen) ;
876 	totlen = dkp->dk_xlen - mlen;
877 	if (totlen == 0)
878 		goto ctlchk ;
879 
880 	/* Skip over stuff sent but not acked */
881 	for (m = dkp->dk_curout->m_next; m && (mlen > 0); m = m->m_next)
882 		if (mlen > m->m_len) mlen -= m->m_len;
883 		else break;
884 
885 	while (totlen && ((dkp->dk_S ^ dkp->dk_R) & DKBMASK)) {
886 		if (dkxmitpanic) panic("dkxmit -- panic 1");
887 		blklen = MIN (totlen, DKBLOCK) ;
888 		pklen = 0 ;
889 		raddr->dkcsr = D_WRITE ;
890 		raddr->dko = stechan | DKMARK ;
891 		while (blklen) {
892 			if (dkxmitpanic) panic("dkxmit -- panic 2");
893 			if (m == NULL) panic("dkxmit mlen");
894 			ptr = mtod(m, char *) + mlen;
895 			mlen = MIN(blklen, m->m_len - mlen);
896 			blklen -= mlen;
897 			wtype = (m->m_type == DKMT_CTL ? 0 : DKDATA);
898 			while (mlen--) {
899 				if (dkxmitpanic) panic("dkxmit -- panic 3");
900 				raddr->dko = (*ptr++ & 0377) | wtype ;
901 				pklen++ ;
902 				if ((pklen & (DKCHUNK-1)) == 0) {
903 					raddr->dkcsr = D_XPACK ;
904 					raddr->dko = 0 ;
905 					raddr->dkcsr = D_WRITE ;
906 					raddr->dko = stechan|DKMARK ;
907 				}
908 			}
909 			if (ptr == (mtod(m, char *) + m->m_len)) {
910 				m = m->m_next;
911 				mlen = 0;
912 			}
913 			else mlen = ptr - mtod(m, char *);
914 		}
915 		blklen = MIN (totlen, DKBLOCK) ;
916 		if ((pklen & (DKCHUNK-1)) > (DKCHUNK-4)) {
917 			raddr->dkcsr = D_XPACK ;
918 			raddr->dko = 0 ;
919 			raddr->dkcsr = D_WRITE ;
920 			raddr->dko = stechan|DKMARK ;
921 		}
922 		if (blklen == totlen && mbp->mp_eob)
923 			raddr->dko = BOT ;
924 		else
925 			raddr->dko = BOTM ;
926 		raddr->dko = (blklen & 0377) | DKDATA ;
927 		raddr->dko = ((blklen>>8) & 0377) | DKDATA ;
928 		raddr->dko = SEQ + dkp->dk_S ;
929 		raddr->dkcsr = D_XPACK ;
930 		raddr->dko = 0 ;
931 		URPTRACE(stechan, SEQ + dkp->dk_S, dkp);
932 		dkp->dk_S++ ;
933 		dkp->dk_S &= 07 ;
934 		totlen -= blklen ;
935 	}
936 #ifdef notdef
937 	if (totlen == 0 && dkp->dk_xlen && scheck) {
938 		raddr->dkcsr = D_WRITE ;
939 		raddr->dko = stechan|DKMARK ;
940 		raddr->dko = CHECK ;
941 		raddr->dkcsr = D_XPACK ;
942 		raddr->dko = 0 ;
943 		URPTRACE(stechan, CHECK, dkp);
944 	}
945 #endif
946 ctlchk:
947 	if (mbp->mp_ctl & 0200) {
948 		raddr->dkcsr = D_WRITE ;
949 		raddr->dko = stechan|DKMARK ;
950 		raddr->dko = mbp->mp_ctl & 0377 ;
951 		raddr->dkcsr = D_XPACK ;
952 		raddr->dko = 0 ;
953 		mbp->mp_ctl = 0 ;
954 		if (dkp->dk_xlen == 0)
955 			dkreport(KS_SEND, stechan, 0, 0, intrpt) ;
956 	}
957 	if(dkdisabled)
958 		raddr->dkcsr = 0;
959 	else
960 		raddr->dkcsr = ENABS ;
961 }
962 
963 
964 static
965 dkrcv(dkp, stechan, intrpt)
966 struct dkchan *dkp ;
967 {
968 register char *ptr1 ;
969 register char *ptr2 ;
970 register len ;
971 short final ;
972 short hibits ;
973 struct dkpkbufr *pkb ;
974 short tlen ;
975 
976 	if ((dkp->dk_rlen == 0) || (dkp->dk_rq == NULL))
977 		return ;
978 	final = 0 ;
979 	tlen = 0 ;
980 	while (final == 0 && (pkb = dkp->dk_rq)) {
981 		if (dkp->dk_rlen == 0)
982 			final |= DKR_FULL ;
983 		ptr1 = &pkb->Pdata[0] ;
984 		ptr2 = dkp->dk_raddr ;
985 		len = MIN(pkb->Plen, dkp->dk_rlen) ;
986 		hibits = pkb->Phibits ;
987 		while (len--) {
988 			if (hibits < 0)
989 				break ;
990 			hibits <<= 1 ;
991 			*ptr2++ = *ptr1++ ;
992 		}
993 		len = ptr2 - dkp->dk_raddr ;
994 		tlen += len ;
995 		dkp->dk_rlen -= len ;
996 		dkp->dk_raddr = ptr2 ;
997 		if ((pkb->Plen -= len) && hibits < 0) {
998 			final |= ((*ptr1++ & 0377) << 8) | DKR_CNTL ;
999 			hibits <<= 1 ;
1000 			pkb->Plen-- ;
1001 		}
1002 		if (len = pkb->Plen) {
1003 			ptr2 = &pkb->Pdata[0] ;
1004 			while (len--)
1005 				*ptr2++ = *ptr1++ ;
1006 			pkb->Phibits = hibits ;
1007 		}
1008 		while (pkb && (pkb->Plen == 0)) {
1009 			if ((pkb->Pseq & 0370) == ACK) {
1010 				pkb->Pseq += ECHO - ACK ;
1011 				final |= dkp->dk_rmode & DKR_BLOCK ;
1012 			}
1013 			if (pkb->Pseq) {
1014 				dksend(stechan, pkb->Pseq) ;
1015 				dkp->dk_C = pkb->Pseq ;
1016 			}
1017 			dkp->dk_rq = pkb->Pnext ;
1018 			pkb->Pnext = dk_Sfree ;
1019 			dk_Sfree = pkb ;
1020 			pkb = dkp->dk_rq ;
1021 		}
1022 	}
1023 	if (tlen && (dkp->dk_rmode & DKR_TIME))
1024 		final |= DKR_TIME ;
1025 	if (dkp->dk_rlen == 0)
1026 		final |= DKR_FULL ;
1027 	if (final && (final != DKR_TIME || ((dkp->dk_state & DK_RCVQ) == 0))) {
1028 		dkp->dk_state |= DK_RCVQ ;
1029 		len = dkp->dk_rlen ;
1030 		if (final != DKR_TIME)
1031 			dkp->dk_rlen = 0 ;
1032 		dkreport(KS_RDB, stechan, len, final, (final == DKR_TIME)?2:intrpt) ;
1033 	}
1034 }
1035 
1036 
1037 
1038 static
1039 dksend(stechan, val)
1040 {
1041 register struct rdevice *raddr ;
1042 register savcsr ;
1043 
1044 	if(stechan == 0)
1045 		return;
1046 
1047 	raddr = DKADDR ;
1048 	savcsr = raddr->dkcsr ;
1049 	raddr->dkcsr = D_WRITE ;
1050 	raddr->dko = stechan| DKMARK ;
1051 	raddr->dko = val ;
1052 	raddr->dkcsr = D_XPACK ;
1053 	raddr->dko = 0 ;
1054 	raddr->dkcsr = savcsr ;
1055 }
1056 
1057 
1058 /*ARGSUSED*/
1059 dkdrrint(dev)	/* ?? */		/* needed for UNIX OS */
1060 {
1061 register struct rdevice *raddr ;
1062 register c ;
1063 register cnt;
1064 
1065 #ifdef lint
1066 	c = 0; cnt = c;
1067 #endif
1068 	cnt = 0;
1069 	raddr = DKADDR ;
1070 	raddr->dkcsr = D_OSEQ ;
1071 	if((raddr->dkcsr & DKTDONE) == 0){
1072 		if(dkstray++ >= MAX_STRAY){
1073 			log(LOG_ERR, "DK err 1 (Cabling?)\n");
1074 			raddr->dkcsr = 0;
1075 			dkdisabled = 1;
1076 			return;
1077 		}
1078 	}
1079 	while (raddr->dkcsr & DKTDONE){
1080 		c = raddr->dki ;
1081 		if(cnt++ > 65){
1082 			log(LOG_ERR, "DK err 2 (Cabling?)\n");
1083 			raddr->dkcsr = 0;
1084 			dkdisabled = 1;
1085 			return;
1086 		}
1087 	}
1088 	raddr->dkcsr = ENABS ;
1089 	if (Hstat != Tstat)
1090 		dkkint() ;
1091 }
1092 
1093 /*ARGSUSED*/
1094 dkdrxint(dev)	/* ?? */
1095 {
1096 register struct rdevice *raddr ;
1097 register char *ptr ;
1098 struct dkchan  *dkp ;
1099 register c ;
1100 short badpacks ;
1101 struct dkpkbufr *pkb ;
1102 short stechan ;
1103 short	len, xlen ;
1104 unsigned short bitloc ;
1105 
1106 	badpacks = 0 ;
1107 	raddr = DKADDR ;
1108 	pkb = NULL ;
1109 	if(raddr->dkcsr >= 0){
1110 		if(dkstray++ > MAX_STRAY){
1111 			log(LOG_ERR, "DK err 3 (Cabling?)\n");
1112 			goto disable;
1113 		}
1114 	}
1115 	while (raddr->dkcsr < 0) {
1116 		raddr->dkcsr = D_READ ;
1117 		c = raddr->dki ;
1118 		while (raddr->dkcsr < 0 && (c & DKMARK)) {
1119 			c &= 0777 ;
1120 			if (c >= dk_nchan) {
1121 				if (++badpacks > 20) {
1122 					log(LOG_ERR, "DK err 4 (Cabling?)\n");
1123 					dkreport(KS_ERR, 0, 2, 0, 1) ;
1124 					goto disable ;
1125 				}
1126 				break ;
1127 			}
1128  			/* discard all chl 0 packets;
1129 			 * the LDI version of the CPM-DR and CPM-422
1130 			 * puts out packets on chl 0 occasionally.
1131 			 */
1132 			if(c == 0) break;
1133 
1134 			dkp = &dkit[c] ;
1135 			stechan = c ;
1136 qpkb:
1137 			if (pkb && pkb->Plen) {
1138 				dkrcvq(stechan, dkp, pkb, 0) ;
1139 				pkb = NULL ;
1140 			}
1141 			if (pkb == NULL) {
1142 				if ((pkb = dk_Sfree) != NULL) {
1143 					dk_Sfree = pkb->Pnext ;
1144 					pkb->Pseq = 0 ;
1145 					pkb->Plen = 0 ;
1146 					pkb->Pnext = NULL ;
1147 					pkb->Phibits = 0 ;
1148 				} else {
1149 					/*
1150 					** Oops, no more dkpkbufr's.
1151 					** Let outer loop gobble up
1152 					** the entire packet.
1153 					** Report to the console
1154 					** every 100th occurrence.
1155 					*/
1156 					if ( dknopkb++ >= 100 ) {
1157 						dknopkb = 1 ;
1158 						dkreport(KS_ERR, 0, 3, 0, 1) ;
1159 					}
1160 					break ;
1161 				}
1162 			}
1163 			raddr->dkcsr = D_READ ;
1164 			ptr = &pkb->Pdata[0] ;
1165 			bitloc = 0100000 ;
1166 			while (raddr->dkcsr < 0 && ((c = raddr->dki) & DKMARK) == 0)
1167 			switch (c = c & 0777) {
1168 			case NULL:
1169 				break ;
1170 			case AINIT:
1171 				dkp->dk_X = XM_INIT ;
1172 				dkp->dk_R = 0 ;
1173 				dkp->dk_S = 1 ;
1174 				dkp->dk_A = 0 ;
1175 				dkxmit(dkp, stechan, 1) ;
1176 				raddr->dkcsr = D_READ ;
1177 				break ;
1178 			case INIT0:
1179 				dksend(stechan, AINIT) ;
1180 				dkp->dk_trmode = 0 ;
1181 				dkp->dk_C = dkp->dk_rseq = 0 ;
1182 				break ;
1183 			case INIT1:
1184 				dksend(stechan, AINIT) ;
1185 				dkp->dk_trmode = 1 ;
1186 				dkp->dk_C = dkp->dk_tail1 = dkp->dk_tail2 = dkp->dk_rseq = 0 ;
1187 				while (pkb) {
1188 					pkb->Pnext = dk_Sfree ;
1189 					dk_Sfree = pkb ;
1190 					if (pkb = dkp->dk_rq)
1191 						dkp->dk_rq = pkb->Pnext ;
1192 					if (pkb == NULL)
1193 						if (pkb = dkp->dk_rb)
1194 							dkp->dk_rb = pkb->Pnext ;
1195 				}
1196 				goto qpkb ;
1197 			case INITREQ:
1198 				dksend(stechan, INIT1) ;
1199 				dkp->dk_X = 0 ;
1200 				break ;
1201 			case ENQ:
1202 				dksend(stechan, dkp->dk_C) ;
1203 			case CHECK:
1204 				dksend(stechan, ACK+dkp->dk_rseq) ;
1205 				while (pkb) {
1206 					pkb->Pnext = dk_Sfree ;
1207 					dk_Sfree = pkb ;
1208 					if (pkb = dkp->dk_rb)
1209 						dkp->dk_rb = pkb->Pnext ;
1210 				}
1211 				dkp->dk_rblen = 0 ;
1212 				goto qpkb ;
1213 			case EOI:
1214 				if (dkp->dk_tail1 == ((SOI<<8)|2))
1215 					dkreport(KS_EOI, stechan, dkp->dk_tail2, 0, 1) ;
1216 				dkp->dk_tail1 = 0 ;
1217 				break ;
1218 			default:
1219 				if (c & DKDATA) {
1220 					if (dkp->dk_tail1) {
1221 						dkp->dk_tail2 = ((dkp->dk_tail2 >> 8) & 0377) | (c<<8) ;
1222 						dkp->dk_tail1++ ;
1223 						if ((dkp->dk_tail1 & 0377) > 3)
1224 							dkp->dk_tail1 = 0 ;
1225 					} else {
1226 						*ptr++ = c & 0377 ;
1227 						pkb->Plen++ ;
1228 						bitloc >>= 1 ;
1229 					}
1230 					break ;
1231 				}
1232 				if (((c & 0770) == ECHO) || ((c & 0770) == REJ)) {
1233 					URPTRACE(stechan, c, dkp);
1234 					dkp->dk_R = c & 07 ;
1235 					if (((dkp->dk_S - dkp->dk_R - 1) & 07) <
1236 					    ((dkp->dk_S - dkp->dk_A - 1) & 07)) {
1237 gotack:
1238 						dkp->dk_X &= ~(XM_REJ | XM_ENQ);
1239 						xlen = dkp->dk_xlen ;
1240 						len = ((c - dkp->dk_A) & 07) * DKBLOCK ;
1241 						len = MIN(len, xlen);
1242 						dkp->dk_xlen -= len;
1243 						if (dkp->dk_curout)
1244 							m_adj(dkp->dk_curout->m_next, len) ;
1245 						dkp->dk_A = c & 07 ;
1246 						if (len || xlen)
1247 							if ((dkp->dk_xlen) == 0)
1248 								dkreport(KS_SEND, stechan, 0, 0, 1) ;
1249 					}
1250 					dkxmit(dkp, stechan, 1) ;
1251 					raddr->dkcsr = D_READ ;
1252 					if ((c & 0770) == REJ && ((dkp->dk_X & XM_REJ) == 0)) {
1253 						dkp->dk_rejcnt++;
1254 gotrej:
1255 						dkp->dk_S = (c+1) & 07 ;
1256 						dkxmit(dkp, stechan, 1) ;
1257 						raddr->dkcsr = D_READ ;
1258 						dkp->dk_X |= XM_REJ ;
1259 					}
1260 					break ;
1261 				}
1262 				if ((c & 0770) == ACK) {
1263 					URPTRACE(stechan, c, dkp);
1264 					if (dkp->dk_A != (c & 07))
1265 						goto gotack ;
1266 					if ((dkp->dk_X & XM_REJ) == 0) {
1267 						dkp->dk_ackrejcnt++;
1268 						goto gotrej ;
1269 					}
1270 					break ;
1271 				}
1272 				if ((c & 0774) == BOT) {
1273 					dkp->dk_tail1 = c << 8 ;
1274 					break ;
1275 				}
1276 				if ((c & 0770) == SEQ) {
1277 					pkb->Pseq = c - SEQ + ECHO ;
1278 					dkrcvq(stechan, dkp, pkb, 0) ;
1279 					if (dkp->dk_trmode) {
1280 						if (dkp->dk_rblen == dkp->dk_tail2 &&
1281 						    (dkp->dk_tail1 & 0377) == 2 &&
1282 						    ((dkp->dk_tail1 >> 8) & 0377) != SOI &&
1283 						    ((dkp->dk_rseq+1) & 07) == (c & 07)) {
1284 							dkp->dk_rseq = c & 07 ;
1285 							if (((dkp->dk_tail1>>8) & 0377) != BOTM)
1286 								pkb->Pseq += ACK - ECHO ;
1287 							dkrcvq(stechan, dkp, dkp->dk_rb, 1) ;
1288 						} else {
1289 							while (pkb = dkp->dk_rb) {
1290 								dkp->dk_rb = pkb->Pnext ;
1291 								pkb->Pnext = dk_Sfree ;
1292 								dk_Sfree = pkb ;
1293 							}
1294 							pkb = dk_Sfree ;
1295 							dk_Sfree = pkb->Pnext ;
1296 							pkb->Plen = 0 ;
1297 							pkb->Pnext = NULL ;
1298 							pkb->Pseq = REJ + dkp->dk_rseq ;
1299 							dkp->dk_srejcnt++;
1300 							if (((dkp->dk_tail1>>8) & 0377) == BOTS)  {
1301 								dkp->dk_rseq = c & 07 ;
1302 								pkb->Pseq = ECHO + dkp->dk_rseq ;
1303 							}
1304 							dkrcvq(stechan, dkp, pkb, 1) ;
1305 						}
1306 						dkp->dk_rb = NULL ;
1307 						dkp->dk_rblen = 0 ;
1308 						dkp->dk_tail1 = 0 ;
1309 					} else
1310 						/* always keep seq no up to date */
1311 						dkp->dk_rseq = c & 07;
1312 					pkb = NULL ;
1313 					goto qpkb ;
1314 				}
1315 				if (c & 0200) {
1316 					dkreport(KS_CNTL, stechan, c, 0, 1) ;
1317 					raddr->dkcsr = D_READ ;
1318 				} else {
1319 					*ptr++ = c & 0377 ;
1320 					pkb->Plen++ ;
1321 					pkb->Phibits |= bitloc ;
1322 					bitloc >>= 1 ;
1323 				}
1324 			}
1325 			if (pkb && pkb->Plen) {
1326 				dkrcvq(stechan, dkp, pkb, 0) ;
1327 				pkb = NULL ;
1328 			}
1329 		}
1330 	}
1331 
1332 	if (pkb) {
1333 		if (pkb->Plen)
1334 			dkrcvq(stechan, dkp, pkb, 0) ;
1335 		else {
1336 			pkb->Pnext = dk_Sfree ;
1337 			dk_Sfree = pkb ;
1338 		}
1339 	}
1340 	raddr->dkcsr = ENABS ;
1341 	return;
1342 
1343 disable:
1344 	if(pkb){
1345 		pkb->Pnext = dk_Sfree;
1346 		dk_Sfree = pkb;
1347 	}
1348 	raddr->dkcsr = 0;
1349 	dkdisabled = 1;
1350 }
1351 
1352 dkrcvq(stechan, dkp, npkb, where)
1353 register struct dkchan *dkp ;
1354 struct dkpkbufr *npkb ;
1355 {
1356 register struct dkpkbufr *pkb ;
1357 	int	i ;
1358 
1359 	i = 0 ;
1360 	if (dkp->dk_trmode && where == 0)
1361 		pkb = (struct dkpkbufr *)&dkp->dk_rb ;
1362 	else
1363 		pkb = (struct dkpkbufr *)&dkp->dk_rq ;
1364 
1365 	while (pkb->Pnext) {
1366 		pkb = pkb->Pnext ;
1367 		i++ ;
1368 	}
1369 	if ( i >= PKBHOG ) {
1370 		/*
1371 		** This channel has too many buffers.
1372 		** Do not queue any more.
1373 		** Return the new buffer to the free list.
1374 		*/
1375 		npkb->Pnext = dk_Sfree ;
1376 		dk_Sfree = npkb ;
1377 		return ;
1378 	}
1379 	pkb->Pnext = npkb ;
1380 
1381 	if (dkp->dk_trmode && where == 0)
1382 		dkp->dk_rblen += npkb->Plen ;
1383 	else
1384 		dkrcv(dkp, stechan, 1) ;
1385 }
1386 
1387 
1388 
1389 dkreport(type, chan, info1, info2, intrpt)
1390 /*  intrpt parameter controlls whether the pdp-11 interrupt is called.
1391  *  Value 0 says no (means dkxint queued already)
1392  *  Value 1 says call it immediately (like from dr11c interrupt)
1393  *  Value 2 says to queue a call as soon as processor priority lowers
1394  *       (by sending a dummy packet on a channel and getting dkxint)
1395  */
1396 {
1397 	register struct dkstat	*sp;
1398 
1399 	if ((Tstat + 1) % dkdr_nstat == Hstat) {	/* room in queue? */
1400 		log(LOG_ERR, "dkit_dr: No room in status queue, Channel %d\n", chan);
1401 		return;
1402 	}
1403 
1404 	sp = &dkdr_stat[Tstat] ;
1405 	sp->k_chan = chan ;
1406 	sp->k_type = type ;
1407 	sp->k_info1 = info1 ;
1408 	sp->k_info2 = info2 ;
1409 	if (Tstat == dkdr_nstat-1)  Tstat = 0 ;  else Tstat++ ;
1410 	if (intrpt==1) {
1411 		dkkint() ;
1412 	} else if (intrpt==2) {
1413 		register struct rdevice *raddr ;
1414 		raddr = DKADDR ;
1415 		raddr->dkcsr = D_WRITE ;
1416 
1417 		/* Chl (dk_nchan-1) is used instead of 511 because
1418 		 * the LDI switch module will complain if we use
1419 		 * a chl outside the range set up in its route tables.
1420 		 */
1421 		raddr->dko = (dk_nchan-1) | DKMARK ;
1422 
1423 		/*
1424 		 * A null is used here because it should always
1425 		 * be ignored by the far end of the circuit.
1426 		 */
1427 		raddr->dko = 0 ;
1428 
1429 		raddr->dkcsr = D_XPACK ;
1430 		raddr->dko = 0 ;
1431 		raddr->dkcsr = ENABS ;
1432 	}
1433 }
1434 
1435 #ifdef	URPDEBUG
1436 struct	dkurps {
1437 	char	dku_ctl;
1438 	char	dku_S;
1439 	char	dku_R;
1440 	char	dku_A;
1441 } dkurps[URPDEBUG];
1442 int	dkurpsize = URPDEBUG;
1443 
1444 struct	dkurps	*dkurpsp = dkurps;
1445 int	dkurpreset;
1446 
1447 dkurptrace(ctl, dkp) char ctl; register struct dkchan *dkp;
1448 {
1449 #ifdef lint
1450 	dkurpsize = dkurpsize;
1451 #endif
1452 	if (dkurpreset) {
1453 		dkurpsp = dkurps;
1454 		dkurpreset = 0;
1455 	}
1456 	dkurpsp->dku_ctl = ctl;
1457 	dkurpsp->dku_S = dkp->dk_S;
1458 	dkurpsp->dku_R = dkp->dk_R;
1459 	dkurpsp->dku_A = dkp->dk_A;
1460 	if (++dkurpsp == dkurps+URPDEBUG)
1461 		dkurpsp = dkurps;
1462 }
1463 #endif	URPDEBUG
1464 #endif
1465