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