|
|
1.1 root 1: /*
2: * stream driver for DK via KMC-11/KDI board
3: * delicately intertwined with kmc.c
4: */
5:
6: #include "sys/param.h"
7: #include "sys/stream.h"
8: #include "sys/ttyio.h"
9: #include "sys/dkio.h"
10: #include "sys/conf.h"
11: #include "sys/dkstat.h"
12: #include "sys/dkmod.h"
13: #include "sys/ubaddr.h"
14: #include "sys/kmc.h"
15: #include "sys/kdi.h"
16: #include "sys/buf.h"
17: #include "sys/dkwindow.h"
18:
19: #define KDIPRI 28
20:
21: /*
22: * flags
23: */
24: #define KMBUSY 0x01
25: #define KMSTOP 0x02
26: #define KMINC 0x04
27: #define KMBIG 0x3c /* rcvd lots last time, use big rcv buffer */
28: #define KMXCL 0x40 /* exclusive use */
29: #define KMXBIG 0x80 /* tell KMC to use large messages */
30: #define BIGSET(c) ((((c)<<1)|KMINC)&KMBIG | ((c)&~KMBIG))
31: #define BIGCLR(c) (((c)<<1)&KMBIG | ((c)&~KMBIG))
32:
33: /*
34: * device structure
35: */
36: struct device {
37: char sts;
38: char x1;
39: union {
40: struct {
41: u_short lo;
42: u_char hi;
43: } a;
44: struct {
45: u_char x2;
46: u_char x3;
47: u_char ch;
48: u_char ct;
49: u_char sh;
50: u_char st;
51: } q;
52: } u;
53: };
54:
55: /*
56: * KMC commands
57: */
58: #define KC_INIT 1
59: #define KC_SEND 2
60: #define KC_RCVB 3
61: #define KC_CLOSE 4
62: #define KC_XINIT 5
63: #define KC_CMD 6
64: #define KC_FLAG 7
65: #define KC_SOI 8
66:
67: /*
68: * subcommands of KC_CMD or KC_SEND
69: */
70: #define OFLUSH 02 /* flush output */
71: #define OSPND 04 /* suspend output */
72: #define ORSME 010 /* resume output */
73: #define OBOTM 0200 /* send BOTM trailer, not BOT */
74:
75: /*
76: * KMC reports
77: */
78: #define KS_SEND 024
79: #define KS_RDB 025
80: #define KS_EOI 026
81: #define KS_CNTL 027
82: #define KS_ERR 030
83:
84: /*
85: * KC_RCV modes
86: */
87: #define CBLOCK 0040 /* return on block boundary */
88: #define CTIME 0100 /* return when time expires */
89:
90: /*
91: * KS_RDB mode
92: */
93: #define SFULL 0001 /* buffer full */
94: #define SCNTL 0002 /* cntl char recv */
95: #define SABORT 0010 /* rcv aborted */
96: #define SBLOCK 0040 /* block boundary */
97: #define STIME 0100 /* time limit expired */
98:
99: /*
100: * URP control characters
101: */
102: #define D_DELAY 0100
103: #define D_BREAK 0110
104:
105: /*
106: * KMC errors
107: */
108: #define E_NOQB 4 /* internal buffer runout */
109: #define E_DUP 5 /* duplicate send (shouldn't but does happen) */
110: #define E_UMETA 7 /* unknown control character */
111:
112: /*
113: * tracing
114: */
115: #define DEBUG
116: #ifdef DEBUG
117: struct kin ktrbuf[256];
118: struct kin *ktrp = ktrbuf;
119: #define TRACE(x) *ktrp++ = x; if (ktrp >= &ktrbuf[256]) ktrp = ktrbuf;
120: #else
121: #define TRACE(x) ;
122: #endif
123:
124: int kdiclose(), kdiput(), kdiisrv();
125: long kdiopen();
126: struct qinit kdirinit = { noput, kdiisrv, kdiopen, kdiclose, 0, 0 };
127: struct qinit kdiwinit = { kdiput, NULL, kdiopen, kdiclose, 512, 128 };
128: struct streamtab kdiinfo = { &kdirinit, &kdiwinit };
129: struct cdevsw kdicdev = cstrinit(&kdiinfo);
130:
131: struct kmaddr kmcubaddr();
132: extern struct kdikmc kdikmc[];
133: extern struct kmcdk k[];
134: extern int kdicnt;
135: extern struct kmc kmc[];
136: extern struct ubaddr kmcaddr[];
137: extern int kmccnt;
138: struct dkstat dkstat;
139:
140: #define KDICHAN 96 /* channels per kdi (== per kmc) */
141: #define KMC(d) ((d)/KDICHAN)
142: #define CHAN(d) ((d)%KDICHAN)
143:
144: /*
145: * open channel
146: */
147: long
148: kdiopen(q, dev)
149: register struct queue *q;
150: dev_t dev;
151: {
152: register struct kdi *kp;
153: register struct block *bp;
154: register struct kdikmc *xp;
155: register int kno, chan;
156:
157: kno = KMC(minor(dev));
158: chan = CHAN(minor(dev));
159: if (kno >= kdicnt || kno >= kmccnt || chan >= KDICHAN)
160: return (0);
161: xp = &kdikmc[kno];
162: if (xp->bad)
163: return (0);
164: if (xp->init == 0)
165: if (kdiinit(dev) == 0)
166: return (0);
167: kp = &xp->kdi[chan];
168: if (xp->state[chan] != DKCLOSED) {
169: if (kp->ostate&KMXCL) /* exclusive use until reset */
170: return(0);
171: if (xp->state[chan] != DKOPEN)
172: return(0); /* closing channels cannot reopen */
173: return(1);
174: }
175: kp->dkrq = q;
176: q->ptr = (caddr_t)kp;
177: WR(q)->flag |= QDELIM|QBIGB;
178: q->flag |= QDELIM;
179: WR(q)->ptr = (caddr_t)kp;
180: xp->state[chan] = DKOPEN;
181: kp->ostate = KMXCL;
182: kcmd(kno, KC_INIT, kp->chan, 0, 0, 0, (uaddr_t)NULL);
183: if ((bp = allocb(64)) == NULL) {
184: xp->state[chan] = 0;
185: return(0);
186: }
187: kp->lastctl = 0;
188: kp->ibp = bp;
189: kp->imap = ubmblk(xp->ubno, bp, 0);
190: kcmd(kno, KC_RCVB, chan, bp->lim-bp->wptr, 50,
191: CBLOCK|CTIME, ubadwptr(xp->ubno, bp, kp->imap));
192: return(1);
193: }
194:
195: kdiclose(q)
196: register struct queue *q;
197: {
198: register struct kdi *kp = (struct kdi *)q->ptr;
199: register s, i;
200: register struct kdikmc *xp;
201:
202: xp = &kdikmc[kp->kno];
203: if (xp->modp == NULL || xp->modp->listnrq == NULL
204: || xp->state[kp->chan]==DKRCLOSE)
205: xp->state[kp->chan] = DKCLOSED;
206: else if (xp->state[kp->chan] == DKOPEN) {
207: xp->state[kp->chan] = DKLCLOSE;
208: for (i=0; i<30 && (WR(q)->count || kp->obp); i++)
209: tsleep((caddr_t)kp, KDIPRI, 1);
210: }
211: kp->dkrq = NULL;
212: if (xp->modp && xp->modp->listnrq)
213: putctl2(RD(xp->modp->listnrq), M_PRICTL, DKMCLOSE, kp->chan);
214: s = spl6();
215: if (kp->obp) {
216: freeb(kp->obp);
217: kp->obp = NULL;
218: }
219: splx(s);
220: kp->ostate &= ~KMXCL;
221: kcmd(kp->kno, KC_CLOSE, kp->chan, 0, 0, 0, (uaddr_t)NULL);
222: }
223:
224: kdiput(q, bp)
225: register struct queue *q;
226: register struct block *bp;
227: {
228: register struct kdi *kdp = (struct kdi *)q->ptr;
229: register char *sp;
230: register s;
231: register struct kdikmc *xp;
232: struct block *xbp;
233: int t;
234:
235: xp = &kdikmc[kdp->kno];
236: switch(bp->type) {
237:
238: case M_CTL:
239: case M_DATA:
240: case M_DELAY:
241: case M_BREAK:
242: if (xp->state[kdp->chan] < DKLCLOSE) {
243: freeb(bp);
244: return;
245: }
246: putq(q, bp);
247: if ((kdp->ostate&KMBUSY)==0)
248: kmstart(kdp);
249: return;
250:
251: case M_PRICTL:
252: switch (*bp->rptr) {
253: case DKMCLOSE:
254: s = bp->rptr[1];
255: if (s < KDICHAN) {
256: flushq(q, 1);
257: if (xp->state[s] == DKOPEN) {
258: xp->state[s] = DKRCLOSE;
259: putctl(xp->kdi[s].dkrq->next, M_HANGUP);
260: } else if (xp->state[s] == DKLCLOSE)
261: xp->state[s] = DKCLOSED;
262: kcmd(kdp->kno, KC_CLOSE, s, 0, 0, 0, (uaddr_t)NULL);
263: }
264: break;
265:
266: case DKMXINIT:
267: /* retrieve channel number */
268: bp->rptr++;
269: s = *bp->rptr++;
270:
271: /* forget it if this isn't a valid channel */
272: if (s >= KDICHAN || xp->state[s] != DKOPEN)
273: break;
274:
275: /* next two bytes (if there) are the traffic type */
276: if(bp->wptr-bp->rptr>=2){
277: t = (*bp->rptr++<<8) & 0xff00;
278: t |= *bp->rptr++ & 0xff;
279:
280: /* check window sizes */
281: if (W_VALID(t)) {
282:
283: /* kmc has only two possible window sizes */
284: t = W_VALUE(W_ORIG(t));
285: if(t<1024)
286: xp->kdi[s].ostate &= ~KMXBIG;
287: else
288: xp->kdi[s].ostate |= KMXBIG;
289: }
290: }
291:
292: /* restart urp on the channel, with the correct window */
293: kdixinit(&xp->kdi[s]);
294: break;
295:
296: default:
297: break;
298: }
299: break; /* and freeb */
300:
301: case M_IOCTL:
302: sp = stiodata(bp);
303: bp->type = M_IOCACK;
304: switch (stiocom(bp)) {
305:
306: case TIOCSDEV:
307: if (((struct ttydevb *)sp)->ispeed == 0)
308: putctl2(q, M_PRICTL, DKMCLOSE, kdp->chan);
309: case KIOCISURP:
310: bp->wptr = bp->rptr;
311: break;
312:
313: case DIOCSCTL:
314: bp->wptr = bp->rptr;
315: if (*sp == 0)
316: break;
317: if ((xbp = allocb(1)) == NULL)
318: bp->type = M_IOCNAK;
319: else {
320: xbp->type = M_CTL;
321: *xbp->wptr++ = *sp;
322: putq(q, xbp);
323: if ((kdp->ostate&KMBUSY) == 0)
324: kmstart(kdp);
325: }
326: break;
327:
328: case DIOCRCTL:
329: *sp = kdp->lastctl;
330: kdp->lastctl = 0;
331: bp->wptr = (unsigned char *)sp + 1;
332: break;
333:
334: case DIOCNXCL:
335: kdp->ostate &= ~KMXCL;
336: bp->wptr = bp->rptr;
337: break;
338:
339: case TIOCGDEV:
340: ((struct ttydevb *)sp)->ispeed =
341: ((struct ttydevb *)sp)->ospeed = B9600;
342: break;
343:
344: case KIOCINIT:
345: kdixinit(kdp);
346: bp->rptr = bp->wptr;
347: break;
348:
349: case KIOCSHUT:
350: if (kdp->chan > 2) { /* hackish security attempt */
351: bp->type = M_IOCNAK;
352: break;
353: }
354: kdireset(kdp->kno);
355: bp->rptr = bp->wptr;
356: break;
357:
358: case DIOCSTREAM:
359: RD(q)->flag &= ~QDELIM;
360: bp->rptr = bp->wptr;
361: break;
362:
363: case DIOCRECORD:
364: RD(q)->flag |= QDELIM;
365: bp->rptr = bp->wptr;
366: break;
367:
368: case DIOCXWIN: {
369: unsigned int wins;
370: /* KMC does big (756) or small (84) windows currently */
371: wins = (sp[0] + (sp[1]<<8))*sp[4];
372: kdp->ostate &= ~KMXBIG;
373: if (wins>=756)
374: kdp->ostate |= KMXBIG;
375: /* will take effect next XINIT */
376: bp->rptr = bp->wptr;
377: break;
378: }
379:
380: default:
381: bp->wptr = bp->rptr;
382: bp->type = M_IOCNAK;
383: break;
384: }
385: qreply(q, bp);
386: return;
387:
388: case M_STOP:
389: s = OSPND;
390: kdp->ostate |= KMSTOP;
391: goto dontcmd;
392:
393: case M_FLUSH:
394: flushq(q, 0);
395: s = spl6();
396: if (kdp->obp) {
397: freeb(kdp->obp); /* this cannot be right -- too early */
398: kdp->obp = 0;
399: }
400: kdp->ostate &= ~(KMSTOP|KMBUSY);
401: splx(s);
402: s = OFLUSH|ORSME;
403: goto docmd;
404:
405: case M_START:
406: case M_HANGUP:
407: s = ORSME;
408: kdp->ostate &= ~KMSTOP;
409: goto dontcmd;
410: docmd:
411: kcmd(kdp->kno, KC_CMD, kdp->chan, 0, s, 0, (uaddr_t)NULL);
412: dontcmd:
413: kmstart(kdp);
414: break;
415:
416: default: /* not handled; just toss */
417: break;
418: }
419: freeb(bp);
420: }
421:
422: /*
423: * restart URP on some channel:
424: * send XINIT to KMC;
425: * discard any pending transmit block
426: *
427: * should pending block really be discarded, or requeued?
428: * former seems to match real cases
429: */
430:
431: kdixinit(kp)
432: register struct kdi *kp;
433: {
434: register int s;
435:
436: s = spl6();
437: kcmd(kp->kno, KC_XINIT, kp->chan, 0, 0, (kp->ostate&KMXBIG)!=0, (uaddr_t)NULL);
438: if (kp->obp) {
439: freeb(kp->obp);
440: kp->obp = NULL;
441: }
442: if (kp->omap) {
443: ubmfree(kdikmc[kp->kno].ubno, kp->omap);
444: kp->omap = 0;
445: }
446: kp->ostate &=~ (KMSTOP|KMBUSY);
447: splx(s);
448: }
449:
450: kdiisrv(q)
451: register struct queue *q;
452: {
453: register struct kdi *kp = (struct kdi *)q->ptr;
454: register int ubno;
455: register struct block *bp;
456:
457: if ((q->next->flag&QFULL)==0 && kp->ibp==NULL) {
458: bp = allocb(kp->ostate&KMBIG? 1024:64);
459: if (bp == NULL)
460: panic("kdi: can't alloc");
461: kp->ibp = bp;
462: ubno = kdikmc[kp->kno].ubno;
463: kp->imap = ubmblk(ubno, bp, 0);
464: kcmd(kp->kno, KC_RCVB, kp->chan, bp->lim - bp->wptr,
465: 50, CBLOCK|CTIME, ubadwptr(ubno, bp, kp->imap));
466: }
467: }
468:
469: kmstart(kdp)
470: register struct kdi *kdp;
471: {
472: register s = spl5();
473: register struct block *bp;
474: register struct queue *qp;
475: register c;
476: register struct kdikmc *xp;
477:
478: if (kdp->ostate&(KMBUSY|KMSTOP)) {
479: splx(s);
480: return;
481: }
482: if ((qp = kdp->dkrq)==NULL || (qp = WR(qp))==NULL) {
483: splx(s);
484: return;
485: }
486: xp = &kdikmc[kdp->kno];
487: if (bp = getq(qp)) switch (bp->type) {
488:
489: case M_DATA:
490: c = OBOTM;
491: if (bp->class&S_DELIM)
492: c = 0;
493: kdp->omap = ubmblk(xp->ubno, bp, 0);
494: kcmd(kdp->kno, KC_SEND, kdp->chan, bp->wptr-bp->rptr,
495: 0, c, ubadrptr(xp->ubno, bp, kdp->omap));
496: kdp->ostate |= KMBUSY;
497: dkstat.output += bp->wptr - bp->rptr;
498: kdp->obp = bp;
499: break;
500:
501: case M_DELAY:
502: c = D_DELAY;
503: while (*bp->rptr>0) {
504: c++;
505: *bp->rptr >>= 1;
506: }
507: kdp->omap = ubmblk(xp->ubno, bp, 0);
508: kcmd(kdp->kno, KC_SEND, kdp->chan, 1, c, 0, ubadrptr(xp->ubno, bp, kdp->omap));
509: kdp->ostate |= KMBUSY;
510: kdp->obp = bp;
511: break;
512:
513: case M_CTL:
514: kdp->omap = ubmblk(xp->ubno, bp, 0);
515: kcmd(kdp->kno, KC_SEND, kdp->chan, 0, *bp->rptr, 0, ubadrptr(xp->ubno, bp, kdp->omap));
516: kdp->ostate |= KMBUSY;
517: kdp->obp = bp;
518: break;
519:
520: case M_BREAK:
521: kdp->omap = ubmblk(xp->ubno, bp, 0);
522: kcmd(kdp->kno, KC_SEND, kdp->chan, 0, D_BREAK, 0, ubadrptr(xp->ubno, bp, kdp->omap));
523: kdp->ostate |= KMBUSY;
524: kdp->obp = bp;
525: break;
526:
527: default:
528: printf("mesg %o in kdi\n", bp->type);
529: freeb(bp);
530: break;
531: }
532: splx(s);
533: }
534:
535: int kcmdovern[10];
536: long kcmdovert[10];
537:
538: kcmd(kno, type, chan, len, ctl, mode, addr)
539: uaddr_t addr;
540: {
541: register i;
542: register struct device *dp = kmc[kno].k_addr;
543: register struct kin *kp;
544: register s;
545: static struct kmaddr nulladr = {0, 0};
546: static serno;
547: register long loop;
548:
549: /*
550: * if the kmc is dead, don't ask it to do things
551: */
552: if(dp->sts ==3)
553: return;
554:
555: if (dp->u.q.x3)
556: dp->u.q.x3 = 0;
557: busywait:
558: /*
559: * wait at low priority till there's a free command. No
560: * sense slowing all processes down.
561: */
562: if(((dp->u.q.ch+1)%NKMB)==dp->u.q.ct) {
563: loop = 0;
564: while (((dp->u.q.ch+1)%NKMB)==dp->u.q.ct) {
565: if (loop == 1000)
566: printf("waiting for kdi%d\n", kno);
567: if(loop++>1000000) {
568: printf("kmc%d died, restart\n", kno);
569: kdireset(kno);
570: return;
571: }
572: }
573: kcmdovern[kno]++;
574: if(kcmdovert[kno]<loop)
575: kcmdovert[kno] = loop;
576: }
577: s = spl5();
578: /*
579: * someone else might have gotten in at low priority. check
580: * again.
581: */
582: if(((dp->u.q.ch+1)%NKMB)==dp->u.q.ct) {
583: splx(s);
584: goto busywait;
585: }
586: i = dp->u.q.ch;
587: if (i >= NKMB)
588: panic("kcmd");
589: kp = &k[kno].cmd[i];
590: kp->type = type;
591: kp->serno = ++serno;
592: kp->chan = chan;
593: kp->len = len;
594: kp->ctl = ctl;
595: kp->mode = mode;
596: kp->addr.hi = addr>>16;
597: kp->addr.lo = addr;
598: i++;
599: if (i >= NKMB)
600: i = 0;
601: dp->u.q.ch = i;
602: TRACE(*kp);
603: splx(s);
604: }
605:
606: u_char kdiseqno[10];
607:
608: /*
609: * Interrupt routine-- unload status buffer:
610: * release write blocks, collect input
611: */
612: kdiintr(kno)
613: {
614: register struct device *dp = kmc[kno].k_addr;
615: register struct kin *sp;
616: register struct kdi *kp;
617: register struct block *bp;
618: register c;
619: register struct kdikmc *xp;
620:
621: xp = &kdikmc[kno];
622: if (dp->u.q.x3)
623: dp->u.q.x3 = 0;
624: for ( ; (c = dp->u.q.st) != dp->u.q.sh; dp->u.q.st = c) {
625: if (c >= NKMB) {
626: printf("kdi stat buf is %d\n", c);
627: panic("kdiintr");
628: }
629: sp = &k[kno].stat[c];
630: TRACE(*sp);
631: c++;
632: if (c >= NKMB)
633: c = 0;
634: if (sp->chan >= KDICHAN) {
635: printf("kdi%d stat chan is 0%o\n", kno, sp->chan);
636: printf("type: %o len: 0%o mode: 0%o\n");
637: continue;
638: }
639: if(sp->serno!=kdiseqno[kno]){
640: printf("kdi%d stat chan is 0%o\n", kno, sp->chan);
641: printf("seqno is %d, should be %d\n",sp->serno,
642: kdiseqno[kno]);
643: }
644: kdiseqno[kno]=(sp->serno+1)%256;
645: kp = &xp->kdi[sp->chan];
646: switch (sp->type) {
647:
648: case KS_SEND:
649: if (kp->obp) {
650: freeb(kp->obp);
651: kp->obp = NULL;
652: }
653: kp->ostate &= ~KMBUSY;
654: if (kp->omap) {
655: ubmfree(xp->ubno, kp->omap);
656: kp->omap = 0;
657: }
658: if (kp->dkrq && WR(kp->dkrq)->first)
659: kmstart(kp);
660: break;
661:
662: case KS_RDB:
663: if (kp->imap) {
664: ubmfree(xp->ubno, kp->imap);
665: kp->imap = 0;
666: }
667: bp = kp->ibp;
668: kp->ibp = NULL;
669: if (kp->dkrq==NULL || xp->state[kp->chan]!=DKOPEN) {
670: if (bp)
671: freeb(bp);
672: break;
673: }
674: if (sp->mode & SABORT) {
675: printf("kdi%d rcv abort chan %d mode %o bp %x\n",
676: kno, kp->chan, sp->mode, bp);
677: if (bp)
678: kp->ibp = bp;
679: kp->rsize = 0;
680: kp->ostate &= ~KMBIG;
681: break;
682: }
683: if (bp == NULL) {
684: printf("kdi%d: no ibp\n", kno);
685: break;
686: }
687: /* special hacks */
688: if (sp->mode&020
689: || sp->mode==0100 && bp->wptr+sp->len==bp->lim) {
690: /*
691: * Something no one understands. Print out
692: * some info so that we might figure out
693: * why this freeb is in the code.
694: */
695: printf("kdi%d rcv chan %d mode %o bp %x len %d\n",
696: kno, kp->chan, sp->mode, bp, sp->len);
697: freeb(bp);
698: } else {
699: bp->wptr = bp->lim - sp->len;
700: kp->rsize += bp->wptr - bp->rptr;
701: dkstat.input += bp->wptr - bp->rptr;
702: if(sp->mode&(SBLOCK|STIME)) {
703: bp->class |= S_DELIM;
704: if (kp->rsize >= 512)
705: kp->ostate = BIGSET(kp->ostate);
706: else
707: kp->ostate = BIGCLR(kp->ostate);
708: kp->rsize = 0;
709: }
710: (*kp->dkrq->next->qinfo->putp)
711: (kp->dkrq->next, bp);
712: kp->ibp = NULL;
713: if (sp->mode&SCNTL) {
714: switch (sp->ctl) {
715:
716: case D_BREAK:
717: putctl(kp->dkrq->next, M_BREAK);
718: break;
719:
720: default:
721: kp->lastctl = sp->ctl;
722: putctl1(kp->dkrq->next, M_CTL, sp->ctl);
723: break;
724:
725: }
726: }
727: }
728: if ((kp->dkrq->next->flag&QFULL) == 0) {
729: bp = allocb(kp->ostate&KMBIG? 1024:64);
730: if (bp == NULL)
731: panic("kdi: can't alloc");
732: kp->ibp = bp;
733: kp->imap = ubmblk(xp->ubno, bp, 0);
734: kcmd(kno, KC_RCVB, kp->chan, bp->lim - bp->wptr,
735: 50, CBLOCK|CTIME, ubadwptr(xp->ubno, bp, kp->imap));
736: }
737: break;
738:
739: case KS_EOI:
740: printf("kdi%d chan %d rcv EOI %x\n", kno, sp->chan, sp->len);
741: break;
742:
743: case KS_CNTL:
744: /*
745: printf("kdi%d chan %d rcv ctl %x\n", kno, sp->chan, sp->len);
746: */
747: break;
748:
749: case KS_ERR:
750: printf("kdi%d chan %d error %d\n", kno, sp->chan, sp->len);
751: if (sp->len==E_NOQB || sp->len==E_UMETA
752: || sp->len==E_DUP) {
753: printf("ignored\n");
754: break;
755: }
756: kdireset(kno);
757: break;
758:
759: }
760: }
761: }
762:
763: /*
764: * init things, including data structures
765: * -- assume KDICHAN struct kdis and KDICHAN chars for state
766: * will fit in a buffer. when BSIZE is 4096, it's true.
767: */
768: int kdireload();
769:
770: kdiinit(dev)
771: int dev;
772: {
773: register struct device *kp;
774: register i;
775: register struct kdikmc *xp;
776: register int kno;
777: struct kmaddr ka;
778: extern time_t time;
779:
780: kno = KMC(minor(dev));
781: /* close all open channels? */
782: if ((kp = kmc[kno].k_addr) == NULL)
783: return (0);
784: xp = &kdikmc[kno];
785: if (xp->badtime+30 > time) /* UGH */
786: return(0);
787: kp->sts = 0; /* initialize KMC */
788: if (xp->buf == NULL) {
789: if ((xp->buf = geteblk()) == NULL)
790: return (0);
791: clrbuf(xp->buf);
792: xp->kdi = (struct kdi *)xp->buf->b_un.b_addr;
793: xp->state = (char *)&xp->kdi[KDICHAN];
794: for (i = 0; i < KDICHAN; i++) {
795: xp->kdi[i].chan = i;
796: xp->kdi[i].kno = kno;
797: }
798: }
799: if ((xp->modp = dkmodall(dev, kno*KDICHAN, (kno+1)*KDICHAN)) == 0)
800: return (0);
801: xp->modp->dkstate = xp->state;
802: xp->ubno = kmcaddr[kno].ubno;
803: if (xp->umap == 0) {
804: if ((xp->umap = ubmalloc(xp->ubno, sizeof(struct kmcdk), 0)) == 0) {
805: printf("kdi%d: no map\n", kno);
806: return (0);
807: }
808: }
809: xp->ubad = ubmaddr(xp->ubno, (caddr_t)&k[kno], sizeof(struct kmcdk), xp->umap);
810: k[kno].kinit.cmdaddr = kmcubaddr((caddr_t)k[kno].cmd, (caddr_t)&k[kno], xp->ubad);
811: k[kno].kinit.stataddr = kmcubaddr((caddr_t)k[kno].stat, (caddr_t)&k[kno], xp->ubad);
812: k[kno].kinit.bufaddr = kmcubaddr((caddr_t)k[kno].kmcbuf, (caddr_t)&k[kno], xp->ubad);
813: ka = kmcubaddr((caddr_t)&k[kno].kinit, (caddr_t)&k[kno], xp->ubad);
814: kp->u.a.lo = ka.lo;
815: kp->u.a.hi = ka.hi;
816: xp->badtime = time;
817: kp->sts = 1; /* start handshake */
818: for (i = 0; i<100000; i++) {
819: if (kp->sts == 2) {
820: kmc[kno].k_rint = kdiintr;
821: kmc[kno].k_xint = kdiintr;
822: kmc[kno].k_reset = kdireload;
823: xp->init = 1;
824: return(1); /* KMC is running OK */
825: }
826: if (kp->sts == 3) {
827: printf("kdi%d: entered state 3\n", kno);
828: return(0);
829: }
830: }
831: printf("kdi%d: kmc not ready\n", kno);
832: return(0);
833: }
834:
835: struct kmaddr
836: kmcubaddr(memaddr, membase, ubbase)
837: caddr_t memaddr, membase;
838: uaddr_t ubbase;
839: {
840: register struct kmaddr r;
841: register long a;
842:
843: a = (long)memaddr - (long)membase + (long)ubbase;
844: r.hi = a >> 16;
845: r.lo = (u_short)a;
846: return(r);
847: }
848:
849: /*
850: * kmc reload
851: */
852: kdireload(kno)
853: {
854: register struct kdikmc *xp;
855:
856: xp = &kdikmc[kno];
857: xp->init = 0;
858: xp->modp = 0;
859: xp->bad = 0;
860: }
861:
862: /*
863: * zap all open channels
864: */
865: kdireset(kno)
866: {
867: register struct kdi *kp;
868: register struct kdikmc *xp;
869: register struct device *dp;
870:
871: xp = &kdikmc[kno];
872: if (xp->modp==0)
873: return;
874: if ((dp = kmc[kno].k_addr) != NULL)
875: dp->sts = 3; /* disable kdi kmc code */
876: for (kp = &xp->kdi[KDICHAN-1]; kp >= xp->kdi; --kp) {
877: register state = xp->state[kp->chan];
878: if ((state==DKOPEN || state==DKLCLOSE) && kp->dkrq) {
879: flushq(WR(kp->dkrq), 1);
880: xp->state[kp->chan] = state==DKOPEN? DKRCLOSE: DKCLOSED;
881: putctl(kp->dkrq->next, M_HANGUP);
882: }
883: if (kp->imap)
884: ubmfree(xp->ubno, kp->imap);
885: if (kp->omap)
886: ubmfree(xp->ubno, kp->omap);
887: kp->imap = kp->omap = 0;
888: }
889: xp->bad = 1;
890: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.