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