xref: /original-bsd/sys/vax/datakit/dkit_kmc.c (revision 4da674f5)
1 /*
2  * Datakit driver
3  * KMC assistance, with or without DR11C
4  *	@(#)dkit_kmc.c	1.4 (Berkeley) 12/16/90
5  */
6 
7 #include "dkitkmc.h"
8 #if NDKITKMC>0
9 
10 #include "datakit.h"
11 
12 #include "../include/pte.h"
13 #include "sys/param.h"
14 #include "sys/syslog.h"
15 #include "sys/time.h"
16 #include "sys/kernel.h"
17 #include "sys/buf.h"
18 #include "sys/mbuf.h"
19 #include "sys/errno.h"
20 #include "sys/socket.h"
21 #include "net/if.h"
22 #include "../if/if_uba.h"
23 #include "../uba/ubareg.h"
24 #include "../uba/ubavar.h"
25 
26 #include "dkit.h"
27 #include "dkkmc.h"
28 #include "dk.h"
29 
30 #define KMXSMALL	0
31 #define KMXBIG		1
32 
33 #define	MONITOR	1
34 
35 #ifdef	MONITOR
36 static	int	dummy ;
37 int	*DKP = &dummy ;
38 #define	M_ON(a)		*DKP |= (a)
39 #define M_OFF(a)	*DKP &= ~(a)
40 #define	M_TRACE(a)	*DKP |= (a);*DKP &= ~(a)
41 
42 #define	Mxmit	01
43 #define	Mrecv	02
44 #define	Mkint	04
45 #define	Mint	010
46 #define	Mcmd	020
47 
48 #else
49 #define	M_ON(a)
50 #define	M_OFF(a)
51 #define	M_TRACE(a)
52 #endif
53 
54 extern int		dk_nchan;
55 
56 struct dkchan	dkit[NDATAKIT];
57 
58 #define	DKNCMDB	20
59 #define	DKNSTB	20
60 
61 int dkk_ncmd = DKNCMDB;
62 struct dkkin dkkcmdbuf[DKNCMDB];
63 int dkk_nstat = DKNSTB;
64 struct dkkin dkkstat[DKNSTB];
65 char dkkbuf[16*1024];
66 int dkubmbuf;
67 
68 static struct kdevice *dkkaddr;
69 
70 /*
71  * initial information to the KMC
72  */
73 struct dkinit {
74 	caddr_t	cmdaddr;	/* command buffer */
75 	caddr_t	stataddr;	/* status buffer  */
76 	caddr_t	bufaddr ;	/* kmc workspace  */
77 	caddr_t	csraddr;	/* for KMC/DR DR register address */
78 } dkkmcinit;
79 
80 /*
81  * structure of data in first mbuf on chain (type DKM_HDR)
82  *
83  */
84 struct	mpacket {
85 	short	mp_len;		/* Total length left */
86 	char	mp_ctl;		/* Control character */
87 	int	mp_eob;		/* Send end-of-block indicator */
88 	int	(*mp_endfcn)();	/* End-action function */
89 	caddr_t	mp_endparm;	/* Parameter to above function */
90 };
91 
92 
93 /*
94  * The circular buffer, cmdbuf, is used to pass command to kmc:
95  * while the circular buffer statbuf is used to report status.
96  * There are 8 control and status registers (csr) accessible to
97  * both cpu and kmc.
98  * Csr4-csr5 are used to indicate the head and tail respectively
99  * of the cmdbuf.  Likewise, csr6-csr7 for statbuf.
100  * At initialization time, the cpu and kmc would agree on the beginning
101  * address of both buffers and their sizes.
102  */
103 #define	csr0	dkkaddr->un.bsel.bsel0	/* kmc state */
104 #define	csr1	dkkaddr->un.bsel.bsel1
105 #define	csr2	dkkaddr->un.bsel.bsel2	/* used at init time, to pass */
106 #define	csr3	dkkaddr->un.bsel.bsel3	/* addresses to the kmc       */
107 #define	csr4	dkkaddr->un.bsel.bsel4  /* head cmdbuf */
108 #define	csr5	dkkaddr->un.bsel.bsel5  /* tail cmdbuf */
109 #define	csr6	dkkaddr->un.bsel.bsel6	/* head statbuf */
110 #define	csr7	dkkaddr->un.bsel.bsel7	/* tail statbuf */
111 
112 
113 /*
114  * kmc device registers
115  */
116 struct kdevice {
117 union {
118 struct	{ short sel0, sel2, sel4, sel6;} wsel ;
119 struct	{ char bsel0, bsel1, bsel2, bsel3;
120 	  char bsel4, bsel5, bsel6, bsel7; } bsel ;
121 } un;
122 };
123 
124 
125 /*
126  * For the moment, only support one kmc (kmc0)
127  * More need be done for multiple kmc's
128  */
129 
130 int	dkdebug = 512 ;
131 int	dkactive = 0 ;
132 int	dkbindex ;
133 	static int	kseqchk = 0;	/* used to check seq. #'s in statbuf */
134 	static int	dkpanic = 0;	/* # of dk_close(0)'s in this run */
135 	static int	kseq = 0;	/* # kmc responses mod 0377 */
136 	static int	pseq = 0;
137 
138 	static struct dkkin *cmd4;		/* dkkcmdbuf[csr4] pointer */
139 	static struct dkkin *stat7;		/* dkkstat[csr7] pointer */
140 
141 int dkk_cnt ;
142 static struct uba_device *ui;
143 
144 dkkmc_attach(kui) struct uba_device *kui;
145 {
146 	ui = kui;
147 	dkk_cnt = kui->ui_unit;
148 }
149 
150 dk_init()
151 {
152 	int t, kt ;
153 	extern dkkint() ;
154 
155 	/*
156 	 *  On the first open of the hardware interface
157 	 */
158 	if (!ui) return -ENXIO;
159 	if (kmcset((dkk_cnt)<<6,03,dkkint)) {
160 /* debug */	log(LOG_ERR, "dkkmcinit bad: kmcset failed\n");
161 		return -1;
162 	}
163 	dkkaddr = ((struct kdevice *) ui->ui_addr);
164 
165 	/* if csr0 != 0, then error
166 	   else pass the address of struct init
167 	   in csr2~4 and set csr0 to 1	*/
168 
169 	if ((csr0 & 3) != 0) {
170 /* debug */	log(LOG_ERR, "dkkmcinit: csr0 != 0\n");
171 		return EIO;
172 	}
173 
174 	/* Map UBA registers to point to our stuff */
175 	kt = dk_ubainit();
176 	if (kt == 0) {
177 		log(LOG_ERR, "dkkmcinit: no uba resources\n");
178 		return ENOBUFS;
179 	}
180 
181 	/* Address of DR11-C (if any) */
182 	t = ui->ui_flags & ~03 ;
183 	dkkmcinit.csraddr = (caddr_t) ((t<<16) + 3) ;	/* bits 17 + 18 must be 1 */
184 
185 	/* append new init info here, if it is needed */
186 
187 	dkkaddr->un.wsel.sel2 = (short)(UBAI_ADDR(kt) & 0xFFFF);/* bits 0-15 */
188 	dkkaddr->un.bsel.bsel4 = (char)(UBAI_ADDR(kt) >> 16);	/* bits 16-17 */
189 
190 	csr0 = 1;	/* tell KMC to read csr2 */
191 	kseq = 0 ;
192 
193 	cmd4 = &dkkcmdbuf[0] ;	/* driver's pointers into cmdbuf and statbuf */
194 	stat7 = &dkkstat[0] ;
195 	dkactive = 1 ;
196 	return 0 ;
197 }
198 
199 int	dk_ubaed = 0;
200 
201 dk_ubainit()
202 {
203 	int t;
204 	static int kt;
205 
206 	if (dk_ubaed) {
207 		if (dkdebug < dk_nchan)
208 			log(LOG_ERR, "dk_ubainit: reinit\n");
209 		return kt;
210 	}
211 	dk_ubaed = 1;
212 
213 	/* Initialization buffer */
214 	kt = uballoc(ui->ui_ubanum, (caddr_t) &dkkmcinit, sizeof dkkmcinit, UBA_CANTWAIT);
215 	if (kt == 0) return 0;
216 
217 	/* Command input buffer */
218 	t = uballoc(ui->ui_ubanum, (caddr_t) dkkcmdbuf, sizeof dkkcmdbuf, UBA_CANTWAIT) ;
219 	if (t == 0) return 0;
220 	dkkmcinit.cmdaddr = (caddr_t)((UBAI_ADDR(t)<<16) | ((UBAI_ADDR(t)>>16)));	/* must swap bytes for unibus */
221 
222 	/* Status out buffer */
223 	t = uballoc(ui->ui_ubanum, (caddr_t) dkkstat, sizeof dkkstat, UBA_CANTWAIT);
224 	if (t == 0) return 0;
225 	dkkmcinit.stataddr = (caddr_t)((UBAI_ADDR(t)<<16) | (UBAI_ADDR(t)>>16));
226 
227 	/* KMC buffer */
228 	dkubmbuf = uballoc(ui->ui_ubanum, (caddr_t) dkkbuf, sizeof dkkbuf, UBA_CANTWAIT);
229 	if (dkubmbuf == 0) return 0;
230 	dkkmcinit.bufaddr = (caddr_t) ((UBAI_ADDR(dkubmbuf)<<16) |
231 	    (UBAI_ADDR(dkubmbuf)>>16));
232 	if (dkdebug < dk_nchan)
233 		log(LOG_ERR, "dk_ubainit: bufaddr %x mapped %x\n", (caddr_t)dkkbuf,
234 		    dkubmbuf);
235 
236 	return kt;
237 }
238 
239 dk_open(chan, supfcn)
240 register chan ;
241 int (*supfcn)() ;
242 {
243 	register struct	dkchan	*dkp;
244 	register	s ;
245 	extern 	dkkint() ;
246 	extern int commchan;
247 	int init;
248 
249 	if (chan >= dk_nchan)
250 		return -ENXIO ;
251 	if (dkactive == -1)	/* fail request if reset is in progress */
252 		return(-ENETRESET) ;
253 	dkp = &dkit[chan] ;
254 	s = splimp() ;
255 	/*
256 	 * Channel 0 (0-3 in ISN) is reserved for maintenance.
257 	 * An open on channel 0 is interpreted as a request
258 	 * for an unused channel.  Channel 1 (4 in ISN or RADIAN)
259 	 * is the common supervisory channel.
260 	 */
261 	if (chan == 0) {
262 		chan = commchan+1;		/* Start above commchan */
263 		while (1) {
264 			dkp = &dkit[chan] ;
265 			if (dkp->dk_state == 0)
266 				break ;
267 			chan++ ;
268 			if (chan >= dk_nchan) {
269 				splx(s) ;
270 				return -EADDRNOTAVAIL ;
271 			}
272 		}
273 	}
274 	splx(s) ;
275 
276 	if (dkactive == 0)
277 		if ((init = dk_init()) < 0)
278 			return init ;
279 
280 	/*
281 	 * On first use of a channel, we must
282 	 * allocate per-channel UBA resource for transmit.
283 	 * Some day, when we convert the receivers to use mbufs,
284 	 * we'll do the same for reads.
285 	 * Note that these resources can't easily be freed (I think).
286 	 */
287 	if (!dkp->dk_uba.ifu_uba) {
288 		dkp->dk_uba.ifu_flags = UBA_CANTWAIT;
289 		if (if_ubaminit(&dkp->dk_uba.ifu_info, ui->ui_ubanum, 0,
290 		    btoc(CLBYTES),
291 		    &dkp->dk_uba.ifu_r, 0,
292 		    &dkp->dk_uba.ifu_xmt, 1) == 0) {
293 			log(LOG_ERR, "dkkmc: no ubamap for channel %d\n", chan);
294 			return -ENOBUFS;
295 		}
296 		dkp->dk_outq.ifq_maxlen = 20;
297 	}
298 
299 	/*
300 	 * Finish setting up dkp struct.
301 	 */
302 	if ((dkp->dk_state & DK_OPEN) ==0) {
303 		dkcmd(KC_XINIT, chan, (caddr_t)0, (unsigned) 0, KMXBIG, 0);
304 		flushall(dkp, 0);
305 		dkp->dk_state |= DK_OPEN;
306 		dkp->dk_state &= ~(DK_LINGR | DK_RESET);
307 		dkactive++ ;
308 	}
309 	dkp->dk_supfcn = supfcn ;
310 	return chan ;
311 }
312 
313 
314 /*
315  * Close a channel:
316  */
317 
318 dk_close(chan)
319 {
320 	register struct	dkchan	*dkp;
321 	register s ;
322 	int init;
323 
324 	if (dkkaddr == 0) return(-ENODEV);	/* if no init, can't close */
325 						/* ie: can't do dkmaint */
326 
327 	s = splimp() ;
328 	dkp = &dkit[chan] ;
329 	if (chan == 0) {
330 		for (dkp = &dkit[1]; dkp < &dkit[dk_nchan]; dkp++) {
331 			if (dkp->dk_state & (DK_OPEN|DK_BUSY|DK_RCV)) {
332 				dkp->dk_state |= DK_RESET ;
333 				flushall(dkp, 0) ;
334 				dkp->dk_state = DK_RESET ;
335 			}
336 		}
337 		dkpanic++ ;
338 		kseq = 0 ;
339 		pseq = 0 ;
340 #ifdef notdef
341 		if(dkubmbuf){   /* only deallocate mem if still allocated */
342 			ubarelse(ui->ui_ubanum, &dkubmbuf);
343 			dkubmbuf = NULL;
344 		}
345 #endif
346 		/* wait for protocols to close channels */
347 		dkactive = -1 ;
348 		DELAY(4 * hz) ;
349 		/* do a dk_free for all channels */
350 		for (dkp = &dkit[1]; dkp < &dkit[dk_nchan]; dkp++) {
351 			dkp->dk_state &= ~DK_LINGR ;
352 		}
353 		dkactive = 0 ;
354 		csr0 = 0 ;	/* set kmc to idle mode */
355 		if ((init = dk_init()) < 0) {
356 			splx(s) ;
357 			return init ;
358 		}
359 	} else {
360 		flushall(dkp, 0) ;
361 		dkp->dk_state = DK_LINGR ;	/* set while UNIXP protocol
362 						   closes up channel with DK */
363 	}
364 	splx(s) ;
365 	return 0;
366 }
367 
368 
369 
370 
371 /*
372  *	Close phase 2 - mark available for reassignment
373  */
374 dk_free(chan)
375 {
376 	if (chan > dkdebug)
377 		log(LOG_ERR, "dk_free %d\n", chan) ;
378 	dkit[chan].dk_state &= ~(DK_LINGR | DK_RESET);
379 }
380 
381 
382 /*
383  *	Reset a channel
384  *	 prevents further I/O until close
385  */
386 dk_reset(chan)
387 {
388 register struct dkchan *dkp ;
389 register s ;
390 
391 	if (chan > dkdebug)
392 		log(LOG_ERR, "dk_reset %d\n", chan) ;
393 	s = splimp() ;
394 	dkp = &dkit[chan] ;
395 	dkp->dk_state |= DK_RESET ;
396 	flushall(dkp, 0) ;
397 	splx(s) ;
398 }
399 
400 
401 
402 /*
403  *	Xmit a short control (interrupt) packet (max 2 bytes)
404  */
405 dk_xint(chan, intr)
406 {
407 register s ;
408 
409 	s = splimp() ;
410 	dkcmd(KC_SOI, chan, (caddr_t)0, (unsigned) intr, 0, 0) ;
411 	splx(s) ;
412 	return 0 ;
413 }
414 
415 
416 /*
417  * Adjust window size
418  */
419 /*ARGSUSED*/
420 dk_winsize(chan, win)
421 	struct diocxwin *win;
422 {
423 	return EINVAL;		/* For now... */
424 }
425 
426 
427 
428 /*
429  * Xmit data on a channel
430  */
431 dk_xmit(chan, m, eob, ctlchar, endfcn, endparm)
432 	struct mbuf *m ;
433 	int (*endfcn)() ;
434 	caddr_t endparm ;
435 {
436 	register struct dkchan *dkp ;
437 	short s ;
438 	register struct mpacket *mbp ;
439 	register struct mbuf *mb;
440 	int len;
441 
442 	M_ON(Mxmit) ;
443 	s = splimp() ;
444 	dkp = &dkit[chan] ;
445 	if ((dkp->dk_state & DK_RESET) || (mb = m_get(M_DONTWAIT,DKMT_HDR)) == NULL) {
446 		m_freem(m);
447 		splx(s) ;
448 		return 0 ;
449 	}
450 
451 	mb->m_len = 0;
452 	mbp = mtod(mb, struct mpacket *);
453 	mbp->mp_endfcn = endfcn ;
454 	mbp->mp_endparm = endparm ;
455 	mbp->mp_eob = eob;
456 	mbp->mp_ctl = ctlchar;
457 
458 	if ((dkp->dk_state & DK_BUSY) == 0) {
459 		dkp->dk_state |= DK_BUSY ;
460 		dkp->dk_obuf = mbp ;
461 		mb->m_next = NULL;
462 		len = if_wubaput(&dkp->dk_uba, m);
463 		dkcmd(KC_SEND, chan, (caddr_t) UBAI_ADDR(dkp->dk_uba.ifu_w.ifrw_info),
464 		    (unsigned) len, eob ? SBOT : SBOTM, ctlchar) ;
465 		splx(s) ;
466 		M_OFF(Mxmit) ;
467 		return dkp->dk_state ;
468 	}
469 
470 	mb->m_next = m;
471 	if (IF_QFULL(&dkp->dk_outq)) {
472 		IF_DROP(&dkp->dk_outq);
473 		m_freem(mb);
474 	}
475 	else
476 		IF_ENQUEUE(&dkp->dk_outq, mb);
477 	splx(s) ;
478 	M_OFF(Mxmit) ;
479 	return dkp->dk_state ;
480 }
481 
482 /*
483  * Receive into a block buffer
484  */
485 dk_recv(chan, addr, len, mode, endfcn, endparm)
486 int len;
487 int (*endfcn)() ;
488 caddr_t addr, endparm ;
489 {
490 	register struct dkchan *dkp ;
491 	int s;
492 
493 	s = splimp() ;
494 	M_ON(Mrecv) ;
495 	dkp = &dkit[chan] ;
496 	if (dkp->dk_state & (DK_RCV | DK_RESET)) {
497 		splx(s) ;
498 		return(0) ;
499 	}
500 	dkp->dk_ubmbase = uballoc(ui->ui_ubanum, addr, len, UBA_CANTWAIT);
501 	if (dkp->dk_ubmbase == NULL) {
502 		splx(s) ;
503 		return(0) ;
504 	}
505 	dkp->dk_state |= DK_RCV ;
506 	dkp->dk_endfcn = endfcn ;
507 	dkp->dk_endparm = endparm ;
508 	dkp->dk_rlen = len;
509 	dkcmd(KC_RCVB, chan, (caddr_t) UBAI_ADDR(dkp->dk_ubmbase), (unsigned) len, mode&0377, mode>>8);
510 	M_OFF(Mrecv) ;
511 	splx(s);
512 	return dkp->dk_state ;
513 }
514 
515 /* Abort pending receive */
516 
517 
518 dk_rabort(chan, nendfcn, nendparm)
519 int (*nendfcn)() ;
520 caddr_t nendparm;
521 {
522 register struct dkchan *dkp ;
523 register s ;
524 
525 	dkp = &dkit[chan] ;
526 	s = splimp() ;
527 	if (dkp->dk_state & DK_RCV) {	/* cancel outstanding receive */
528 		dkcmd(KC_RCVB, chan, (caddr_t)0, (unsigned) 0, 0, 0) ;
529 		dkp->dk_endfcn = nendfcn ;
530 		dkp->dk_endparm = nendparm ;
531 	}
532 	splx(s) ;
533 	return dkp->dk_state ;
534 }
535 
536 
537 
538 dk_status(chan)
539 {
540 	if (chan >= dk_nchan)
541 		return 0 ;
542 	return dkit[chan].dk_state ;
543 }
544 
545 
546 /*
547  * Various control commands to KMC
548  */
549 dk_cmd(chan, cmd)
550 {
551 	register struct dkchan *dkp ;
552 	register s ;
553 
554 	dkp = &dkit[chan] ;
555 	if (cmd & (DKC_XINIT|DKC_FLUSH)) {
556 		/*for either command do the same thing:
557 		 * reinit the transmitter and flush any pending output.
558 		 * NOTE: for the kmc, there is no response to XINIT
559 		 * and no send complete for flush
560 		 */
561 		s = splimp() ;
562 		dkcmd(KC_XINIT, chan, (caddr_t)0, (unsigned) 0, KMXBIG, 0) ;
563 		flushall(dkp, -1) ;
564 		dkcmd(KC_CMD, chan, (caddr_t)0, (unsigned) DKC_FLUSH, 0, 0) ;
565 		splx(s);
566 		cmd &= ~(DKC_XINIT|DKC_FLUSH) ;
567 	}
568 	if (cmd)
569 		dkcmd(KC_CMD, chan, (caddr_t)0, (unsigned) cmd, 0, 0) ;
570 }
571 
572 
573 /*
574  *	Note that flushall is often recursive when a tty driver
575  *	is involved.
576  */
577 
578 static
579 flushall(dkp, rwflag)
580 register struct dkchan *dkp ;
581 {
582 	register s ;
583 	register struct mpacket *mbp ;
584 	int (*endfcn)();
585 
586 	s = splimp() ;
587 	if ((dkp->dk_state & DK_RCV) && (rwflag >= 0)) {
588 		dkcmd(KC_RCVB, dkp-dkit, (caddr_t)0, (unsigned) 0, 0, 0) ;
589 		dkp->dk_state &= ~DK_RCV ;
590 		if (dkp->dk_ubmbase) {
591 			ubarelse(ui->ui_ubanum, &dkp->dk_ubmbase);
592 			dkp->dk_ubmbase = NULL;
593 		}
594 		if (endfcn = dkp->dk_endfcn) {
595 			dkp->dk_endfcn = NULL ;
596 			(*endfcn)(dkp->dk_endparm, dkp-dkit, dkp->dk_rlen, DKR_ABORT, 0) ;
597 		}
598 	}
599 
600 	/* flush all writes current and pending */
601 
602 	if ((dkp->dk_state & DK_BUSY) && (rwflag <= 0)) {
603 		register struct mbuf *m ;
604 
605 		/* flush current write */
606 		if (mbp = dkp->dk_obuf) {
607 			dkp->dk_obuf = NULL;
608 			if (endfcn = mbp->mp_endfcn) {
609 				mbp->mp_endfcn = NULL;
610 				(endfcn)(mbp->mp_endparm, dkp-dkit);
611 			}
612 			m_free(dtom(mbp));
613 		}
614 		/* flush any pending writes which may be queued up */
615 		while (1) {
616 			IF_DEQUEUE(&dkp->dk_outq, m);
617 			if (!m) break;
618 			mbp = mtod(m, struct mpacket *);
619 			if (endfcn = mbp->mp_endfcn) {
620 				mbp->mp_endfcn = NULL;
621 				(endfcn)(mbp->mp_endparm, dkp-dkit);
622 			}
623 			m_freem(m);
624 		}
625 		/* mark channel as not busy */
626 		dkp->dk_state &= ~DK_BUSY ;
627 	}
628 	if ((dkp->dk_state & DK_OPEN) && (rwflag >= 0)) {
629 		dkcmd(KC_CLOSE, dkp-dkit, (caddr_t)0, (unsigned) 0, 0, 0) ;
630 		if (dkp->dk_state & DK_BUSY){
631 			mbp = dkp->dk_obuf;
632 			dkp->dk_obuf = NULL;
633 			if (endfcn = mbp->mp_endfcn) {
634 				mbp->mp_endfcn = NULL;
635 				(endfcn)(mbp->mp_endparm, dkp-dkit);
636 			}
637 			m_free(dtom(mbp));
638 			dkp->dk_state &= ~DK_BUSY ;
639 		}
640 	}
641 	splx(s) ;
642 }
643 
644 
645 short dup_count = 0; /* counter for number of duplicate sends */
646 
647 /*
648  * Routine to handle interrupts from the KMC
649  *
650  * This routine is called when
651  * the KMC generates an unsolicited interrupt (VEC4 == 1)
652  *
653  * These interrupts are used by the KMC to notify dkit_kmc.c
654  * of events such as output buffer completions
655  * csr6 & csr7 point to dkkstat
656  */
657 dkkint()
658 {
659 	register struct dkchan *dkp;
660 	register struct dkkin *sp;
661 	register chan;
662 	struct mpacket *mbp ;
663 	int (*endfcn)();
664 
665 	M_ON(Mkint) ;
666 
667 	chan = csr0 ;	/* temp for cc -O bug */
668 	if((chan & 01) == 1)	/* 1 or 3 -> ignore */
669 		return;
670 	sp = stat7 ;	/* next response to be processed */
671 	while (csr6 != csr7) {
672 		if (kseqchk)
673 			if ((((sp->k_chan >> 8)&0377) != kseq) ||
674 			    (((sp->k_type >> 8)&0377) != kseq)) {
675 				log(LOG_ERR, "dkkint: kseq %x chan %d type %x\n",
676 					kseq, sp->k_chan, sp->k_type) ;
677 				goto reset ;
678 			}
679 		kseq = (kseq + 1) & 0377 ;
680 		sp->k_addr = pseq ;
681 		pseq++ ;
682 		chan = sp->k_chan & 0377 ;	/* mask off seq. # */
683 		dkp = &dkit[chan];
684 		if (chan > dkdebug) {
685 			log(LOG_ERR, " dkkint: head %d tail %d", csr6, csr7) ;
686 			log(LOG_ERR, " type %x chan %d len %d mode %x ctl %x\n", sp->k_type&0377, sp->k_chan&0377, sp->k_len, sp->k_mode, sp->k_ctl) ;
687 		}
688 		switch(sp->k_type & 0377) {
689 		case KS_CNTL:
690 			if (dkp->dk_supfcn)
691 				(*dkp->dk_supfcn)(chan, sp->k_ctl) ;
692 			break ;
693 		case KS_EOI:
694 			break ;
695 		case KS_SEND:
696 			mbp = dkp->dk_obuf ;
697 			if (mbp == NULL) {
698 				if (dkp->dk_state & (DK_RESET|DK_LINGR))
699 					break;	/* flushall was already called */
700 				log(LOG_ERR, "dkkint: xbufout chan %d state %x\n", chan, dkp->dk_state) ;
701 				log(LOG_ERR, "head %d tail %d", csr6, csr7) ;
702 				log(LOG_ERR, " type %x len %d mode %x ctl %x\n",
703 				sp->k_type&0377, sp->k_len, sp->k_mode, sp->k_ctl) ;
704 				break ;
705 			}
706 			dkp->dk_state &= ~DK_BUSY;
707 			dkp->dk_obuf = NULL ;
708 			if (endfcn = mbp->mp_endfcn) {
709 				mbp->mp_endfcn = NULL;
710 				(endfcn)(mbp->mp_endparm, chan) ;
711 			}
712 			m_free(dtom(mbp)) ;
713 			if (dkp->dk_uba.ifu_xtofree) {
714 				m_freem(dkp->dk_uba.ifu_xtofree);
715 				dkp->dk_uba.ifu_xtofree = 0;
716 			}
717 			if (dkp->dk_outq.ifq_head)
718 				dkstart(dkp) ;
719 			break;
720 		case KS_RDB:
721 			if (((dkp->dk_state & DK_RCV) == 0) && dkp->dk_endfcn) {
722 				log(LOG_ERR, "dkkint: rbufin chan %d state %x\n", chan, dkp->dk_state) ;
723 				log(LOG_ERR, " head %d tail %d\n", csr6, csr7) ;
724 				log(LOG_ERR, " type %x len %d mode %x ctl %x\n",
725 				sp->k_type&0377, sp->k_len, sp->k_mode, sp->k_ctl) ;
726 
727 				if (sp->k_ctl)
728 					break ;
729 				else {
730 					stat7 = sp ;	/* save it for dump */
731 					csr0 = 3 ;	/* stop KMC */
732 					panic("") ;	/* KMC probably wrote
733 						into a mbuf we don't own */
734 				}
735 			}
736 			dkp->dk_state &= ~DK_RCV ;
737 			if (dkp->dk_ubmbase) {
738 				ubarelse(ui->ui_ubanum, &dkp->dk_ubmbase);
739 				dkp->dk_ubmbase = NULL;
740 			}
741 			if (endfcn = dkp->dk_endfcn) {
742 				dkp->dk_endfcn = NULL;
743 				(endfcn)(dkp->dk_endparm, chan, sp->k_len, sp->k_mode, sp->k_ctl) ;
744 			}
745 			break;
746 		case KS_ERR:
747 			log(LOG_ERR, "dkkint: err : chan %d, code %x\nchead: %d, ctail: %d, rhead: %d, rtail: %d\n",
748 				chan, sp->k_len, csr4, csr5, csr6, csr7);
749 
750 			/* if error is duplicate send, only close that chan, */
751 			/* not the whole interface */
752 
753 			if (sp->k_len == E_DUP)  {
754 				dup_count++;
755 				if (dkp->dk_state & DK_OPEN)  {
756 					dk_reset(chan);
757 				}
758 				break;
759 			}
760 reset:
761 			(void) dk_close(0) ;
762 			return ;
763 		default:
764 			log(LOG_ERR, "dkkint: chan %d, type %x, len %d, ctl %x, mode %x\n",
765 			chan, sp->k_type&0377, sp->k_len, sp->k_ctl, sp->k_mode);
766 			goto reset ;
767 		}	/* end switch */
768 
769 		if (csr7 == dkk_nstat-1) {
770 			csr7 = 0 ;
771 			sp = &dkkstat[0] ;
772 		} else {
773 			csr7++ ;
774 			sp++ ;
775 		}
776 
777 	}	/* end while */
778 	stat7 = sp ;
779 	M_OFF(Mkint) ;
780 }
781 
782 /*
783  * Start (Restart) transmission on the given line
784  */
785 dkstart(dkp)
786 register struct dkchan *dkp;
787 {
788 	register struct mpacket *mbp;
789 	register struct mbuf *m;
790 	int len;
791 
792 	/*
793 	 * If it is currently active, just return
794 	 */
795 	if (dkp->dk_state&DK_BUSY)
796 		return;
797 
798 	IF_DEQUEUE(&dkp->dk_outq, m);
799 	if (!m)
800 		return;
801 	mbp = mtod(m, struct mpacket *);
802 
803 	dkp->dk_state |= DK_BUSY ;
804 	dkp->dk_obuf = mbp ;
805 	len = if_wubaput(&dkp->dk_uba, m->m_next);
806 	dkcmd(KC_SEND, dkp-dkit, (caddr_t) UBAI_ADDR(dkp->dk_uba.ifu_w.ifrw_info),
807 	    (unsigned) len, mbp->mp_eob ? SBOT : SBOTM, mbp->mp_ctl) ;
808 }
809 
810 /*
811  * Put command in dkkcmdbuf which is pointed by csr4~5
812  */
813 dkcmd(type, chan, addr, len, mode, ctl)
814 int type, chan;
815 caddr_t addr ;
816 unsigned len ;
817 {
818 	register struct dkkin *sp;
819 	register s;
820 	register next;
821 	register loop;
822 	struct timeval tv1, tv2;
823 
824 	M_ON(Mcmd) ;
825 	s = csr0 ;
826 	if ((s & 3) != 2)
827 		return;
828 
829 	s = splimp();
830 	next = (csr4+1)%dkk_ncmd;
831 	loop = 0;
832 	while (csr5 == next) {
833 		/* give it a chance to empty the buffer */
834 		if (loop++>10000000) {
835 			log(LOG_ERR, "KMC DIED, restart\n");
836 			dk_close(0);
837 			splx(s);
838 			return;
839 		}
840 		log(LOG_ERR, "KMC cmd overrun for %ld\n", loop);
841 	}
842 
843 	sp = cmd4 ;
844 	sp->k_type = type | ((pseq&0177)<<9) ;
845 	sp->k_chan = chan | ((kseq&0377)<<8) ;
846 	sp->k_addr = ((int)addr << 16) + ((int)addr >> 16) ;
847 	sp->k_len = len ;
848 	sp->k_mode = mode ;
849 	sp->k_ctl = ctl ;
850 	pseq++ ;
851 
852 	csr4 = next;
853 	cmd4 = &dkkcmdbuf[next];
854 
855 	if (chan > dkdebug) {
856 	    	log(LOG_ERR, " dkcmd: head %d, tail %d", csr4, csr5);
857 	    	log(LOG_ERR, " type %x, chan %d, addr %x, len %d",
858 						type, chan, addr, len);
859 		log(LOG_ERR, " mode %x, ctl %x\n", mode, ctl);
860 	}
861 	splx(s) ;
862 	M_OFF(Mcmd) ;
863 }
864 
865 #endif
866