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
dk_init()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
dk_ubainit()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
dk_open(chan,supfcn)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
dk_close(chan)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 */
dk_free(chan)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 */
dk_reset(chan)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 */
dk_xint(chan,intr)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 */
dk_recv(chan,addr,len,mode,endfcn,endparm)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
dk_status(chan)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 */
dk_cmd(chan,cmd)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
flushall(dkp,rwflag)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 */
dkkint()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 */
dkstart(dkp)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 */
dkcmd(type,chan,addr,len,mode,ctl)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