|
|
1.1 root 1: /*
2: * stream driver for DK via KMC-11/KDI board
3: */
4: #include "kdi.h"
5: #include "kmc.h"
6: #if NKDI && NKMC
7:
8: #include "../h/param.h"
9: #include "../h/systm.h"
10: #include "../h/stream.h"
11: #include "../h/ioctl.h"
12: #include "../h/pte.h"
13: #include "../h/map.h"
14: #include "../h/buf.h"
15: #include "../h/ubavar.h"
16: #include "../h/conf.h"
17: #include "../h/ttyld.h"
18: #include "../h/dkstat.h"
19: #include "../h/dkmod.h"
20:
21: #define NKMB 10 /* size of cmd/status buffers */
22: #define KDIPRI 28
23:
24: /* channel states */
25: #define CLOSED 0
26: #define RCLOSE 1 /* remote gone, local still around */
27: #define LCLOSE 2 /* closed locally, not acked yet */
28: #define OPEN 3 /* in use */
29:
30: /*
31: * format of UB addresses sent to KMC
32: */
33: struct kmaddr {
34: u_short hi;
35: u_short lo;
36: };
37:
38: /*
39: * KMC init packet
40: */
41: struct kinit {
42: struct kmaddr cmdaddr; /* UB addr of cmd buf */
43: struct kmaddr stataddr; /* UB addr of statbuf */
44: struct kmaddr bufaddr; /* UB addr of KMC workspace */
45: struct kmaddr csraddr; /* for DR11C - unused */
46: };
47:
48: /*
49: * command/status packets
50: */
51: struct kin { /* KMC command buffer */
52: u_char type; /* command type */
53: u_char serno; /* probably seq number */
54: u_char chan; /* channel number */
55: u_char fill2; /* probably seq number */
56: u_short len; /* byte count */
57: char ctl; /* possible control byte */
58: char mode; /* command variant */
59: struct kmaddr addr; /* UB location of buffer */
60: };
61:
62: /*
63: * Big structure with stuff that needs to be accessible on the unibus
64: */
65: struct kmcdk {
66: struct kinit kinit; /* the init packet */
67: struct kin cmd[NKMB]; /* KMC command buffer */
68: struct kin stat[NKMB]; /* KMC status buffer */
69: char kmcbuf[16*1024]; /* temp space for KMC */
70: } k;
71:
72: struct kdi {
73: struct queue *dkrq;
74: struct block *ibp;
75: struct block *obp;
76: u_short rsize; /* # bytes in last read */
77: char chan;
78: char ostate;
79: } kdi[NKDI];
80:
81:
82: #define KMBUSY 01
83: #define KMSTOP 02
84: #define KMBIG 04 /* rcvd lots last time, use big buffer */
85:
86: /*
87: * device structure
88: */
89: struct device {
90: char sts;
91: char x1;
92: union {
93: struct {
94: u_short lo;
95: u_char hi;
96: } a;
97: struct {
98: u_char x2;
99: u_char x3;
100: u_char ch;
101: u_char ct;
102: u_char sh;
103: u_char st;
104: } q;
105: } u;
106: };
107:
108: /*
109: * KMC commands
110: */
111: #define KC_INIT 1
112: #define KC_SEND 2
113: #define KC_RCVB 3
114: #define KC_CLOSE 4
115: #define KC_XINIT 5
116: #define KC_CMD 6
117: #define KC_FLAG 7
118: #define KC_SOI 8
119:
120: /*
121: * subcommands of KC_CMD or KC_SEND
122: */
123: #define OFLUSH 02 /* flush output */
124: #define OSPND 04 /* suspend output */
125: #define ORSME 010 /* resume output */
126: #define OBOTM 0200 /* send BOTM trailer, not BOT */
127:
128: /*
129: * KMC reports
130: */
131: #define KS_SEND 024
132: #define KS_RDB 025
133: #define KS_EOI 026
134: #define KS_CNTL 027
135: #define KS_ERR 030
136:
137: /*
138: * KC_RCV modes
139: */
140: #define CBLOCK 0040 /* return on block boundary */
141: #define CTIME 0100 /* return when time expires */
142:
143: /*
144: * KS_RDB mode
145: */
146: #define SFULL 0001 /* buffer full */
147: #define SCNTL 0002 /* cntl char recv */
148: #define SABORT 0010 /* rcv aborted */
149: #define SBLOCK 0040 /* block boundary */
150: #define STIME 0100 /* time limit expired */
151:
152: /*
153: * URP control characters
154: */
155: #define D_DELAY 0100
156: #define D_BREAK 0110
157:
158: /*
159: * KMC errors
160: */
161: #define E_NOQB 4 /* internal buffer runout */
162: #define E_UMETA 7 /* unknown control character */
163:
164: /*
165: * tracing
166: */
167: #define DEBUG
168: #ifdef DEBUG
169: struct kin ktrbuf[256];
170: struct kin *ktrp = ktrbuf;
171: #define TRACE(x) *ktrp++ = x; if (ktrp >= &ktrbuf[256]) ktrp = ktrbuf;
172: #else
173: #define TRACE(x) ;
174: #endif
175:
176: int nodev(), kdiopen(), kdiclose(), kdiput(), kdiisrv();
177: struct qinit kdirinit = { nodev, kdiisrv, kdiopen, kdiclose, 0, 0 };
178: struct qinit kdiwinit = { kdiput, NULL, kdiopen, kdiclose, 512, 128 };
179: struct streamtab kdiinfo = { &kdirinit, &kdiwinit };
180:
181: extern u_char blkdata[]; /* stream IO blocks */
182: extern long blkubad; /* unibus address of IO blocks */
183: long kdiubad; /* unibus address of device data */
184: struct kmaddr kmcaddr();
185: int kdiopened;
186: int kmcbad;
187: char kdistate[NKDI];
188: struct dkmodule *kdmodp;
189: extern struct dkmodule dkmod[];
190: extern struct uba_device *kmcdinfo[NKMC];
191: extern struct uba_driver kmcdriver;
192: extern (*kdirint)();
193: extern (*kdixint)();
194: struct dkstat dkstat;
195:
196: /*
197: * open channel
198: */
199: kdiopen(q, dev)
200: register struct queue *q;
201: register dev_t dev;
202: {
203: register struct kdi *kp;
204: register struct block *bp;
205: register mindev = minor(dev);
206:
207: if (mindev <= 0 || mindev >= NKDI || kmcbad)
208: return(0);
209: if (!kdiopened) {
210: if (mindev > 1)
211: return(0);
212: for (kp = &kdi[0]; kp < &kdi[NKDI]; kp++)
213: kp->chan = kp - &kdi[0];
214: if (kdiinit() == 0)
215: return(0);
216: for (kdmodp = dkmod; ;kdmodp++) {
217: if (kdmodp->dev==(dev_t)0 || kdmodp->dev==major(dev)) {
218: kdmodp->dev = major(dev);
219: kdmodp->dkstate = kdistate;
220: kdmodp->nchan = NKDI;
221: break;
222: }
223: }
224: kdiopened++;
225: }
226: kp = &kdi[mindev];
227: if (kdmodp->dkstate[mindev] != CLOSED) {
228: if (mindev&01 && mindev>1) /* outgoing channels cannot reopen */
229: return(0);
230: if (kdmodp->dkstate[mindev] != OPEN)
231: return(0); /* closing channels cannot reopen */
232: return(1);
233: }
234: kp->dkrq = q;
235: q->ptr = (caddr_t)kp;
236: WR(q)->flag |= QDELIM|QBIGB;
237: q->flag |= QDELIM;
238: WR(q)->ptr = (caddr_t)kp;
239: kdmodp->dkstate[mindev] = OPEN;
240: kp->ostate = 0;
241: kcmd(KC_INIT, kp->chan, 0, 0, 0, (caddr_t)0);
242: if ((bp = allocb(64)) == NULL) {
243: kdmodp->dkstate[mindev] = 0;
244: return(0);
245: }
246: kp->ibp = bp;
247: kcmd(KC_RCVB, mindev, bp->lim-bp->wptr, 50,
248: CBLOCK|CTIME, (caddr_t)bp->wptr);
249: return(1);
250: }
251:
252: kdiclose(q)
253: register struct queue *q;
254: {
255: register struct kdi *kp = (struct kdi *)q->ptr;
256: register s, i;
257: register struct block *bp;
258:
259: if (kdmodp->dkstate[kp->chan]==RCLOSE || kdmodp->listnrq==NULL)
260: kdmodp->dkstate[kp->chan] = CLOSED;
261: else if (kdmodp->dkstate[kp->chan] == OPEN) {
262: kdmodp->dkstate[kp->chan] = LCLOSE;
263: for (i=0; i<30 && (WR(q)->count || kp->obp); i++)
264: tsleep((caddr_t)kp, KDIPRI, 1);
265: }
266: kp->dkrq = NULL;
267: if (kdmodp->listnrq)
268: putctl1(RD(kdmodp->listnrq), M_CLOSE, kp->chan);
269: s = spl6();
270: if (kp->obp) {
271: freeb(kp->obp);
272: kp->obp = NULL;
273: }
274: splx(s);
275: kcmd(KC_CLOSE, kp->chan, 0, 0, 0, (caddr_t)NULL);
276: }
277:
278: kdiput(q, bp)
279: register struct queue *q;
280: register struct block *bp;
281: {
282: register struct kdi *kdp = (struct kdi *)q->ptr;
283: register union stmsg *sp;
284: register s;
285:
286: switch(bp->type) {
287:
288: case M_DATA:
289: case M_DELIM:
290: case M_DELAY:
291: case M_BREAK:
292: if (kdmodp->dkstate[kdp->chan] < LCLOSE) {
293: freeb(bp);
294: return;
295: }
296: putq(q, bp);
297: if ((kdp->ostate&KMBUSY)==0)
298: kmstart(kdp);
299: return;
300:
301: case M_CLOSE:
302: s = *bp->rptr;
303: if (s < NKDI) {
304: flushq(q, 1);
305: if (kdmodp->dkstate[s] == OPEN) {
306: kdmodp->dkstate[s] = RCLOSE;
307: putctl(kdi[s].dkrq->next, M_HANGUP);
308: } else if (kdmodp->dkstate[s] == LCLOSE)
309: kdmodp->dkstate[s] = CLOSED;
310: kcmd(KC_CLOSE, s, 0, 0, 0, (caddr_t)NULL);
311: }
312: freeb(bp);
313: return;
314:
315: case M_IOCTL:
316: sp = (union stmsg *)bp->rptr;
317: bp->type = M_IOCACK;
318: switch (sp->ioc0.com) {
319:
320: case TIOCSETP:
321: case TIOCSETN:
322: if (sp->ioc1.sb.sg_ispeed == 0)
323: putctl1(q, M_CLOSE, kdp->chan);
324: case KIOCISURP:
325: bp->wptr = bp->rptr;
326: break;
327:
328: case TIOCGETP:
329: sp->ioc1.sb.sg_ispeed =
330: sp->ioc1.sb.sg_ospeed = B9600;
331: break;
332:
333: case KIOCINIT:
334: kcmd(KC_XINIT, kdp->chan, 0, 0, 0, (caddr_t)NULL);
335: bp->rptr = bp->wptr;
336: break;
337:
338: case KIOCSHUT:
339: if (kdp->chan > 1) {
340: bp->type = M_IOCNAK;
341: break;
342: }
343: kdireset();
344: bp->rptr = bp->wptr;
345: break;
346:
347: case DIOCSTREAM:
348: RD(q)->flag &= ~QDELIM;
349: bp->rptr = bp->wptr;
350: break;
351:
352: case DIOCRECORD:
353: RD(q)->flag |= QDELIM;
354: bp->rptr = bp->wptr;
355: break;
356:
357: default:
358: bp->wptr = bp->rptr;
359: bp->type = M_IOCNAK;
360: break;
361: }
362: qreply(q, bp);
363: return;
364:
365: case M_STOP:
366: s = OSPND;
367: kdp->ostate |= KMSTOP;
368: goto dontcmd;
369:
370: case M_FLUSH:
371: flushq(q, 0);
372: s = spl6();
373: if (kdp->obp) {
374: freeb(kdp->obp);
375: kdp->obp = 0;
376: }
377: kdp->ostate &= ~(KMSTOP|KMBUSY);
378: splx(s);
379: s = OFLUSH|ORSME;
380: goto docmd;
381:
382: case M_START:
383: case M_HANGUP:
384: s = ORSME;
385: kdp->ostate &= ~KMSTOP;
386: goto dontcmd;
387: docmd:
388: kcmd(KC_CMD, kdp->chan, 0, s, 0, (caddr_t)NULL);
389: dontcmd:
390: kmstart(kdp);
391: break;
392:
393: default: /* not handled; just toss */
394: break;
395: }
396: freeb(bp);
397: }
398:
399: kdiisrv(q)
400: register struct queue *q;
401: {
402: register struct kdi *kp = (struct kdi *)q->ptr;
403:
404: if ((q->next->flag&QFULL)==0 && kp->ibp==NULL) {
405: register struct block *bp = allocb(kp->ostate&KMBIG? 1024:64);
406: if (bp == NULL)
407: panic("kdi: can't alloc");
408: kp->ibp = bp;
409: kcmd(KC_RCVB, kp->chan, bp->lim - bp->wptr,
410: 50, CBLOCK|CTIME, (caddr_t)bp->wptr);
411: }
412: }
413:
414: kmstart(kdp)
415: register struct kdi *kdp;
416: {
417: register s = spl5();
418: register struct block *bp;
419: register struct queue *qp;
420: register c;
421: register struct block *xbp;
422:
423: if (kdp->ostate&(KMBUSY|KMSTOP)) {
424: splx(s);
425: return;
426: }
427: if ((qp = kdp->dkrq)==NULL || (qp = WR(qp))==NULL) {
428: splx(s);
429: return;
430: }
431: if (bp = getq(qp)) switch (bp->type) {
432:
433: case M_DELIM:
434: kcmd(KC_SEND, kdp->chan, 0,
435: D_DELAY, 0, (caddr_t)bp->rptr);
436: kdp->ostate |= KMBUSY;
437: kdp->obp = bp;
438: break;
439:
440: case M_DATA:
441: c = OBOTM;
442: if (xbp = qp->first) {
443: if (xbp->type==M_DELIM) {
444: if (xbp = getq(qp))
445: freeb(xbp);
446: c = 0;
447: }
448: } else { /* wait for delim or data */
449: putbq(qp, bp);
450: splx(s);
451: return;
452: }
453: kcmd(KC_SEND, kdp->chan, bp->wptr-bp->rptr,
454: 0, c, (caddr_t)bp->rptr);
455: kdp->ostate |= KMBUSY;
456: dkstat.output += bp->wptr - bp->rptr;
457: kdp->obp = bp;
458: break;
459:
460: case M_DELAY:
461: c = D_DELAY;
462: while (*bp->rptr>0) {
463: c++;
464: *bp->rptr >>= 1;
465: }
466: kcmd(KC_SEND, kdp->chan, 1, c, 0, (caddr_t)bp->rptr);
467: kdp->ostate |= KMBUSY;
468: kdp->obp = bp;
469: break;
470:
471: case M_BREAK:
472: kcmd(KC_SEND, kdp->chan, 0, D_BREAK, 0, (caddr_t)bp->rptr);
473: kdp->ostate |= KMBUSY;
474: kdp->obp = bp;
475: break;
476:
477: default:
478: printf("mesg %o in kdi\n", bp->type);
479: freeb(bp);
480: break;
481: }
482: splx(s);
483: }
484:
485: kcmd(type, chan, len, ctl, mode, addr)
486: caddr_t addr;
487: {
488: register i;
489: register struct device *dp = (struct device *)kmcdinfo[0]->ui_addr;
490: register struct kin *kp;
491: register s = spl5();
492: static struct kmaddr nulladr = {0, 0};
493: static serno;
494:
495: i = dp->u.q.ch;
496: if (i >= NKMB)
497: panic("cmd hd %d in kcmd\n", i);
498: kp = &k.cmd[i];
499: kp->type = type;
500: kp->serno = ++serno;
501: kp->chan = chan;
502: kp->len = len;
503: kp->ctl = ctl;
504: kp->mode = mode;
505: if (addr)
506: kp->addr = kmcaddr(addr, (caddr_t)blkdata, blkubad);
507: else
508: kp->addr = nulladr;
509: i++;
510: if (i >= NKMB)
511: i = 0;
512: dp->u.q.ch = i;
513: TRACE(*kp);
514: splx(s);
515: }
516:
517: /*
518: * Interrupt routine-- unload status buffer:
519: * release write blocks, collect input
520: */
521: kdiintr()
522: {
523: register struct device *dp = (struct device *)(kmcdinfo[0]->ui_addr);
524: register struct kin *sp;
525: register struct kdi *kp;
526: register struct block *bp;
527: register c;
528:
529: for ( ; (c = dp->u.q.st) != dp->u.q.sh; dp->u.q.st = c) {
530: if (c >= NKMB)
531: panic("kdi stat buf is %d\n", c);
532: sp = &k.stat[c];
533: TRACE(*sp);
534: c++;
535: if (c >= NKMB)
536: c = 0;
537: if (sp->chan >= NKDI) {
538: printf("kdi stat chan is 0%o\n", sp->chan);
539: printf("type: %o len: 0%o mode: 0%o\n");
540: continue;
541: }
542: kp = &kdi[sp->chan];
543: switch (sp->type) {
544:
545: case KS_SEND:
546: if (kp->obp) {
547: freeb(kp->obp);
548: kp->obp = NULL;
549: }
550: kp->ostate &= ~KMBUSY;
551: if (kp->dkrq && WR(kp->dkrq)->first)
552: kmstart(kp);
553: break;
554:
555: case KS_RDB:
556: bp = kp->ibp;
557: kp->ibp = NULL;
558: if (kp->dkrq==NULL || kdmodp->dkstate[kp->chan]!=OPEN) {
559: if (bp)
560: freeb(bp);
561: break;
562: }
563: if (sp->mode & SABORT) {
564: printf("kdi rcv abort chan %d mode %o bp %x\n",
565: kp->chan, sp->mode, bp);
566: if (bp)
567: kp->ibp = bp;
568: kp->rsize = 0;
569: kp->ostate &= ~KMBIG;
570: break;
571: }
572: if (bp == NULL) {
573: printf("kdi intr: no ibp\n");
574: break;;
575: }
576: /* special hacks */
577: if (sp->mode&020
578: || sp->mode==0100 && bp->wptr+sp->len == bp->lim) {
579: printf("I");
580: freeb(bp);
581: } else {
582: bp->wptr = bp->lim - sp->len;
583: kp->rsize += bp->wptr - bp->rptr;
584: dkstat.input += bp->wptr - bp->rptr;
585: (*kp->dkrq->next->qinfo->putp)
586: (kp->dkrq->next, bp);
587: kp->ibp = NULL;
588: if(sp->mode&(SBLOCK|STIME)) {
589: putctl(kp->dkrq->next, M_DELIM);
590: kp->ostate &= ~KMBIG;
591: if (kp->rsize >= 512)
592: kp->ostate |= KMBIG;
593: kp->rsize = 0;
594: }
595: if (sp->mode&SCNTL) {
596: switch (sp->ctl) {
597:
598: case D_BREAK:
599: putctl(kp->dkrq->next, M_BREAK);
600: break;
601:
602: }
603: }
604: }
605: if ((kp->dkrq->next->flag&QFULL) == 0) {
606: bp = allocb(kp->ostate&KMBIG? 1024:64);
607: if (bp == NULL)
608: panic("kdi: can't alloc");
609: kp->ibp = bp;
610: kcmd(KC_RCVB, kp->chan, bp->lim - bp->wptr,
611: 50, CBLOCK|CTIME, (caddr_t)bp->wptr);
612: }
613: break;
614:
615: case KS_EOI:
616: printf("kdi chan %d rcv EOI %x\n", sp->chan, sp->len);
617: break;
618:
619: case KS_CNTL:
620: /*
621: printf("kdi chan %d rcv ctl %x\n", sp->chan, sp->len);
622: */
623: break;
624:
625: case KS_ERR:
626: printf("kdi chan %d error %d\n", sp->chan, sp->len);
627: if (sp->len==E_NOQB || sp->len==E_UMETA) {
628: printf("ignored\n");
629: break;
630: }
631: kdireset();
632: break;
633:
634: }
635: }
636: }
637:
638: kdiinit()
639: {
640: register struct device *kp = (struct device *)kmcdinfo[0]->ui_addr;
641: register i;
642: struct kmaddr ka;
643: static time_t kditime;
644: extern time_t time;
645:
646: /* close all open channels? */
647: if (kditime+30 > time)
648: return(0);
649: kp->sts = 0; /* initialize KMC */
650: if (kdiubad == 0) {
651: kdiubad = uballoc(kmcdinfo[0]->ui_ubanum,
652: (caddr_t)&k, sizeof(k), 0);
653: if (kdiubad == 0)
654: panic("UB AD 0 in kdiinit");
655: }
656: k.kinit.cmdaddr = kmcaddr((caddr_t)k.cmd, (caddr_t)&k, kdiubad);
657: k.kinit.stataddr = kmcaddr((caddr_t)k.stat, (caddr_t)&k, kdiubad);
658: k.kinit.bufaddr = kmcaddr((caddr_t)k.kmcbuf, (caddr_t)&k, kdiubad);
659: ka = kmcaddr((caddr_t)&k.kinit, (caddr_t)&k, kdiubad);
660: kp->u.a.lo = ka.lo;
661: kp->u.a.hi = ka.hi;
662: kditime = time;
663: kp->sts = 1; /* start handshake */
664: for (i = 0; i<100000; i++) {
665: if (kp->sts == 2) {
666: kdirint = kdiintr;
667: kdixint = kdiintr;
668: return(1); /* KMC is running OK */
669: }
670: if (kp->sts == 3) {
671: printf("KMC entered state 3\n");
672: return(0);
673: }
674: }
675: printf("KMC did not come ready\n");
676: return(0);
677: }
678:
679: struct kmaddr
680: kmcaddr(memaddr, membase, ubbase)
681: caddr_t memaddr, membase, ubbase;
682: {
683: register struct kmaddr r;
684: register long a;
685:
686: a = (long)memaddr - (long)membase + ((long)ubbase & 0x03ffff);
687: r.hi = a >> 16;
688: r.lo = (u_short)a;
689: return(r);
690: }
691:
692: /*
693: * kmc reload
694: */
695: kdireload()
696: {
697: kdiopened = 0;
698: kdmodp = 0;
699: kmcbad = 0;
700: }
701:
702: /*
703: * zap all open channels
704: */
705: kdireset()
706: {
707: register struct kdi *kp;
708:
709: if (kdmodp==0)
710: return;
711: for (kp = kdi; kp < &kdi[NKDI]; kp++) {
712: register state = kdmodp->dkstate[kp->chan];
713: if ((state==OPEN || state==LCLOSE) && kp->dkrq) {
714: flushq(WR(kp->dkrq), 1);
715: kdmodp->dkstate[kp->chan] = state==OPEN? RCLOSE: CLOSED;
716: putctl(kp->dkrq->next, M_HANGUP);
717: }
718: }
719: kmcbad = 1;
720: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.