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