|
|
1.1 root 1: /*
2: * simple two-stream kmc datakit driver
3: * -- assumes it is the first kmc, and only one allowed for now
4: * (the latter not severe, as 256 channels are permitted)
5: */
6: #include "sys/param.h"
7: #include "sys/stream.h"
8: #include "sys/dkio.h"
9: #include "sys/ubaddr.h"
10: #include "sys/conf.h"
11: #include "sys/kb.h"
12: #include "sys/kmc.h"
13: #include "sys/dkstat.h"
14: #include "sys/dkmod.h"
15:
16: #define TRACE 0 /* turn on to provoke tracing */
17:
18: /*
19: * hardware stuff
20: */
21:
22: struct device {
23: char ctl; /* control -- written by host */
24: unsigned char sts; /* status -- written by device */
25: short xlo; /* xmit descriptor, low address */
26: short rlo; /* rcv descriptor, low address */
27: char xhi, rhi; /* high addresses and flags */
28: };
29:
30: /*
31: * control bits
32: */
33: #define CXIE 01 /* transmit interrupt enable */
34: #define CRIE 02 /* receive interrupt enable */
35:
36: /*
37: * status bits
38: */
39: #define SERROR 0200 /* some error, usually NXM */
40:
41: /*
42: * flags in xhi and rhi
43: */
44: #define CNOADDR 0200 /* OK to give another descriptor address */
45: #define CNODESC 0100 /* no descriptor being processed */
46: #define CXA 014 /* high address bits */
47: #define CXSHIFT 2 /* shift high bits this much */
48:
49: /*
50: * descriptor flags
51: */
52: #define DVALID 0200 /* valid descriptor for device */
53: #define DCHAIN 020 /* `buffer' is a fresh descriptor address */
54: #define DXA 014 /* high buffer address bits */
55: #define DSCTL 01 /* first char of buffer is a control char */
56:
57: #define DXSHIFT 2 /* shift high addr bits this much */
58:
59: /*
60: * per-channel stuff
61: */
62: struct kb kb[];
63: extern int kbcnt;
64: char kbstate[];
65:
66: /*
67: * kb flags
68: */
69: #define DKXCL 01 /* exclusive open */
70: #define DKXWANT 02 /* output pending this channel */
71:
72: /*
73: * per-controller stuff;
74: * always just one for now
75: */
76:
77: struct kbkmc kbkmc[1];
78: #define KBNO 0 /* always this kb for now */
79:
80: /*
81: * kbkmc flags
82: */
83: #define INIT 01
84:
85: /*
86: * illicit linkage to other datakit code
87: */
88:
89: struct dkstat dkstat;
90:
91: /*
92: * illicit linkage to kmc driver
93: */
94:
95: extern struct kmc kmc[];
96: extern struct ubaddr kmcaddr[];
97: extern int kmccnt;
98: #define KNO 0 /* kmc0 is ours, by fiat */
99:
100: #define RBSIZE 1024 /* desired receive buffer size */
101: #define MINRBYTES 4096 /* desired total receive buffer */
102:
103: #define XNEXT(i) ((i)>=XRING-1?0:(i)+1)
104: #define RNEXT(i) ((i)>=RRING-1?0:(i)+1)
105:
106: long kbopen();
107: int kbclose(), kbput(), kbosrv();
108:
109: static struct qinit kbrinit = { nodev, NULL, kbopen, kbclose, 0, 0 };
110: struct qinit kbwinit = { kbput, NULL, kbopen, kbclose, 1500, 600 };
111: struct streamtab kbinfo = { &kbrinit, &kbwinit };
112: struct cdevsw kbcdev = cstrinit(&kbinfo);
113:
114: /*
115: * open DK channel
116: */
117: long
118: kbopen(q, dev)
119: register struct queue *q;
120: register dev_t dev;
121: {
122: register struct kb *dkp;
123: register struct kbkmc *kk;
124: register chan;
125:
126: chan = minor(dev);
127: if (chan<=0 || chan>=kbcnt)
128: return(0);
129: kk = &kbkmc[KBNO];
130: if ((kk->flags & INIT) == 0) {
131: if ((kk->modp = dkmodall(dev, 0, kbcnt)) == NULL)
132: return (0);
133: kk->modp->dkstate = kbstate;
134: if (kbinit(kk) == 0)
135: return (0);
136: kk->flags |= INIT;
137: }
138: dkp = &kb[chan];
139: if (kbstate[chan] != DKCLOSED) { /* already open */
140: if (dkp->flag & DKXCL)
141: return(0);
142: if (kbstate[chan] != DKOPEN)
143: return(0); /* closing channels can't reopen */
144: return(1);
145: }
146: dkp->dkrq = q;
147: q->ptr = (caddr_t)dkp;
148: WR(q)->ptr = (caddr_t)dkp;
149: WR(q)->flag |= QNOENB|QBIGB;
150: dkp->flag = DKXCL;
151: dkp->chan = chan;
152: kbstate[chan] = DKOPEN;
153: return(1);
154: }
155:
156: /*
157: * make sure kmc is alive;
158: * init data structures once
159: */
160: kbinit(kk)
161: register struct kbkmc *kk;
162: {
163: register struct kmc *kp;
164: struct device *reg;
165: uaddr_t ua;
166: extern kbintr(), kbreset();
167:
168: kk->kno = KNO;
169: kk->ubno = kmcaddr[KNO].ubno; /* cheat */
170: kp = &kmc[kk->kno];
171: if ((reg = kp->k_addr) == 0)
172: return (0);
173: if ((kk->ringmap = ubmalloc(kk->ubno, sizeof(kk->rings), 0)) == 0) {
174: printf("kb init no map\n");
175: return (0);
176: }
177: ua = ubmaddr(kk->ubno, (caddr_t)&kk->rings, sizeof(kk->rings), kk->ringmap);
178: kk->xrua = ua + ((caddr_t)kk->xring - (caddr_t)&kk->rings);
179: kk->rrua = ua + ((caddr_t)kk->rring - (caddr_t)&kk->rings);
180: kp->k_rint = kbintr;
181: kp->k_xint = kbintr;
182: kp->k_reset = kbreset;
183: kk->addr = reg;
184: kbreset(KNO);
185: return (1);
186: }
187:
188: /*
189: * called when, e.g., kmc is reloaded
190: */
191: kbreset(kno)
192: int kno;
193: {
194: register struct kbkmc *kk;
195: register int i;
196: register struct device *reg;
197:
198: kk = &kbkmc[kno];
199: bzero((caddr_t)&kk->rings, sizeof(kk->rings));
200: kk->rrp = 0;
201: kk->rwp = 0;
202: kk->xrp = 0;
203: kk->xwp = 0;
204: for (i = 0; i < XRING; i++) {
205: if (kk->xmap[i]) {
206: ubmfree(kk->ubno, kk->xmap[i]);
207: kk->xmap[i] = 0;
208: }
209: if (kk->xblock[i]) {
210: freeb(kk->xblock[i]);
211: kk->xblock[i] = 0;
212: }
213: }
214: kk->xring[XRING].loaddr = kk->xrua;
215: kk->xring[XRING].flag = DVALID|DCHAIN|((kk->xrua>>16)<<DXSHIFT);
216: for (i = 0; i < RRING; i++) {
217: if (kk->rmap[i]) {
218: ubmfree(kk->ubno, kk->rmap[i]);
219: kk->rmap[i] = 0;
220: }
221: if (kk->rblock[i]) {
222: freeb(kk->rblock[i]);
223: kk->rblock[i] = 0;
224: }
225: }
226: kk->rring[RRING].loaddr = kk->rrua;
227: kk->rring[RRING].flag = DVALID|DCHAIN|((kk->rrua>>16)<<DXSHIFT);
228: kk->rbytes = 0;
229: reg = kk->addr;
230: reg->ctl = CRIE;
231: i = spl5();
232: kbibufs(kk);
233: reg->rlo = kk->rrua; /* kk->rring[0] */
234: reg->rhi = (kk->rrua>>16)<<CXSHIFT;
235: splx(i);
236: }
237:
238: /*
239: * close DK channel
240: */
241: kbclose(q)
242: register struct queue *q;
243: {
244: register struct kb *dkp;
245: register struct kbkmc *kk;
246:
247: kk = &kbkmc[KBNO];
248: dkp = (struct kb *)q->ptr;
249: if (dkp == NULL)
250: panic("kbclose");
251: dkp->dkrq = NULL;
252: dkp->flag = 0;
253: if (kbstate[dkp->chan] == DKRCLOSE || kk->modp->listnrq==NULL)
254: kbstate[dkp->chan] = DKCLOSED;
255: else if (kbstate[dkp->chan] == DKOPEN)
256: kbstate[dkp->chan] = DKLCLOSE;
257: if (kk->modp->listnrq)
258: putctl2(RD(kk->modp->listnrq), M_PRICTL, DKMCLOSE, dkp->chan);
259: }
260:
261: /*
262: * interrupt
263: * receive any blocks that have arrived;
264: * reload receive buffers;
265: * clean up finished transmit buffers
266: * restart receiver or transmitter if needed
267: */
268:
269: int kbxrst; /* debugging count */
270: int kbxnst; /* debugging count */
271:
272: kbintr(dev)
273: {
274: register struct kbkmc *kk;
275: register struct device *reg;
276: register int i;
277: register uaddr_t ua;
278:
279: kk = &kbkmc[dev];
280: if ((reg = kk->addr) == NULL)
281: return;
282: #if NOTDEF /* straighten out protocol */
283: i = reg->sts;
284: if (i & SERROR) {
285: reg->sts = 0;
286: printf("kb sts %o\n", i);
287: }
288: #endif
289: for (i = kk->rrp; i != kk->rwp; i = RNEXT(i)) {
290: if (kk->rring[i].flag & DVALID)
291: break;
292: kbrcv(kk, i);
293: }
294: if (kk->rbytes < MINRBYTES)
295: kbibufs(kk);
296: if ((reg->rhi & (CNOADDR|CNODESC)) == (CNOADDR|CNODESC)) {
297: /*
298: * receiver has stopped, but may have finished
299: * another block or two since the loop above
300: */
301: for (; i != kk->rwp; i = RNEXT(i)) {
302: if (kk->rring[i].flag & DVALID)
303: break;
304: kbrcv(kk, i);
305: }
306: if (kk->rbytes < MINRBYTES)
307: kbibufs(kk);
308: if (kk->rwp != i) { /* safety check */
309: ua = kk->rrua + i * sizeof(struct kbdesc);
310: reg->rlo = ua;
311: reg->rhi = (ua>>16)<<CXSHIFT;
312: }
313: }
314: kk->rrp = i;
315: i = reg->xhi;
316: if (kk->xrp != kk->xwp)
317: kbxscan(kk);
318: if ((i & (CNOADDR|CNODESC)) == (CNOADDR|CNODESC)
319: && kk->xrp != kk->xwp) {
320: ua = kk->xrua + kk->xrp * sizeof(struct kbdesc);
321: reg->xlo = ua;
322: reg->xhi = (ua>>16)<<CXSHIFT;
323: kbxrst++;
324: }
325: }
326:
327: /*
328: * receive a block
329: */
330: kbrcv(kk, i)
331: register struct kbkmc *kk;
332: register int i;
333: {
334: register struct kbdesc *dxp;
335: register struct queue *q;
336: register int chan;
337: register struct block *bp;
338: struct block *xbp;
339:
340: dxp = &kk->rring[i];
341: #if TRACE
342: trace('i', (i<<24)|(dxp->chan<<16)|dxp->flag, -dxp->len,
343: *(int *)(kk->rblock[i]->rptr));
344: #endif
345: if (kk->rmap[i] == 0)
346: panic("kbrcv");
347: ubmfree(kk->ubno, kk->rmap[i]);
348: kk->rmap[i] = 0;
349: bp = kk->rblock[i];
350: kk->rblock[i] = NULL;
351: kk->rbytes -= bp->lim - bp->wptr;
352: bp->wptr = bp->lim + dxp->len; /* negative residual length */
353: if (dxp->flag & DSCTL) {
354: /*
355: * special hack to save big blocks
356: */
357: if (bp->wptr == bp->rptr + 1
358: && (xbp = allocb(1)) != NULL) {
359: *xbp->wptr++ = *bp->rptr;
360: freeb(bp);
361: bp = xbp;
362: }
363: bp->type = M_CTL;
364: }
365: if (bp->wptr <= bp->base || bp->wptr > bp->lim) {
366: printf("kb ch%d bad len %d\n", dxp->chan, -dxp->len);
367: freeb(bp);
368: return;
369: }
370: chan = dxp->chan;
371: if (chan == 0 || chan >= kbcnt || (q = kb[chan].dkrq) == NULL) {
372: if (chan == 0)
373: dkstat.pack0++;
374: else if (chan >= kbcnt)
375: dkstat.packstrange++;
376: else
377: dkstat.closepack++;
378: freeb(bp);
379: return;
380: }
381: dkstat.input += bp->wptr - bp->rptr;
382: if ((q->next->flag & QFULL) == 0)
383: (*q->next->qinfo->putp)(q->next, bp);
384: else
385: freeb(bp);
386: }
387:
388: /*
389: * refresh our supply of input buffers
390: */
391: kbibufs(kk)
392: register struct kbkmc *kk;
393: {
394: register struct block *bp;
395: register int i;
396: register struct kbdesc *dxp;
397: register uaddr_t ua;
398:
399: i = kk->rwp;
400: while (kk->rbytes < MINRBYTES) {
401: if (RNEXT(i) == kk->rrp) /* all descriptors used */
402: break;
403: if ((bp = allocb(RBSIZE)) == NULL)
404: break;
405: if ((kk->rmap[i] = ubmblk(kk->ubno, bp, 0)) == 0) {
406: printf("kb no rcv map\n");
407: freeb(bp);
408: break;
409: }
410: kk->rblock[i] = bp;
411: ua = ubadrptr(kk->ubno, bp, kk->rmap[i]);
412: dxp = &kk->rring[i];
413: dxp->loaddr = ua;
414: dxp->len = bp->wptr - bp->lim; /* negative length */
415: dxp->flag = ((ua>>16)<<DXSHIFT)|DVALID;
416: kk->rbytes += bp->lim - bp->wptr;
417: i = RNEXT(i);
418: }
419: kk->rwp = i;
420: }
421:
422: /*
423: * put procedure for output
424: */
425: kbput(q, bp)
426: struct queue *q;
427: register struct block *bp;
428: {
429: register struct kb *dkp;
430: register struct kbkmc *kk;
431: register int i;
432: register struct device *reg;
433: register struct kbdesc *dxp;
434: uaddr_t ua;
435: int s;
436:
437: dkp = (struct kb *)q->ptr;
438: kk = &kbkmc[KBNO];
439: switch (bp->type) {
440:
441: case M_IOCTL:
442: switch (stiocom(bp)) {
443: case DIOCNXCL:
444: dkp->flag &=~ DKXCL;
445: bp->wptr = bp->rptr;
446: bp->type = M_IOCACK;
447: break;
448:
449: case KIOCINIT:
450: /* eventually, reset things here */
451:
452: default:
453: bp->type = M_IOCNAK;
454: break;
455: }
456: qreply(q, bp);
457: return;
458:
459: case M_CTL:
460: case M_DATA:
461: if (bp->rptr == bp->wptr) {
462: freeb(bp);
463: return;
464: }
465: s = spl5();
466: i = kk->xwp - kk->xrp;
467: if (i < 0)
468: i += XRING;
469: if (i > XRING/2)
470: kbxscan(kk);
471: if (XNEXT(kk->xwp) == kk->xrp) { /* no desc available? */
472: splx(s);
473: printf("kb xmt ch%d lost block\n", dkp->chan);
474: freeb(bp);
475: return;
476: }
477: i = kk->xwp;
478: kk->xwp = XNEXT(i);
479: if ((kk->xmap[i] = ubmblk(kk->ubno, bp, 0)) == 0) {
480: splx(s);
481: printf("kb xmt ch%d no map\n", dkp->chan);
482: freeb(bp);
483: return;
484: }
485: #if TRACE
486: trace('x', (i<<24)|(dkp->chan<<16)|bp->type, bp->wptr - bp->rptr,
487: *(int *)bp->rptr);
488: #endif
489: kk->xblock[i] = bp;
490: ua = ubadrptr(kk->ubno, bp, kk->xmap[i]);
491: dxp = &kk->xring[i];
492: dxp->loaddr = ua;
493: dxp->len = bp->rptr - bp->wptr; /* negative length */
494: dxp->chan = dkp->chan;
495: dxp->flag = (ua>>16)<<DXSHIFT;
496: if (bp->type != M_DATA)
497: dxp->flag |= DSCTL;
498: reg = kk->addr;
499: dxp->flag |= DVALID;
500: if ((reg->xhi & (CNOADDR|CNODESC)) == (CNOADDR|CNODESC)) {
501: if (i != kk->xrp)
502: kbxscan(kk);
503: if (kk->xwp != kk->xrp) { /* maybe it finished it off -- unlikely */
504: ua = kk->xrua + kk->xrp * sizeof(struct kbdesc);
505: reg->xlo = ua;
506: reg->xhi = ((ua>>16)<<CXSHIFT);
507: }
508: }
509: else /* debug */
510: kbxnst++; /* debug */
511: dkstat.output += bp->wptr - bp->rptr;
512: splx(s);
513: return;
514:
515: case M_PRICTL:
516: switch (*bp->rptr) {
517: case DKMCLOSE:
518: i = bp->rptr[1];
519: if (i < kbcnt) {
520: if (kbstate[i] == DKOPEN) {
521: kbstate[i] = DKRCLOSE;
522: putctl(kb[i].dkrq->next, M_HANGUP);
523: } else if (kbstate[i] == DKLCLOSE)
524: kbstate[i] = DKCLOSED;
525: }
526: freeb(bp);
527: return;
528:
529: case DKMXINIT:
530: i = bp->rptr[1];
531: if (i < kbcnt && kbstate[i] == DKOPEN)
532: (*kb[i].dkrq->next->qinfo->putp)(kb[i].dkrq->next, bp);
533: else
534: freeb(bp);
535: return;
536:
537: default:
538: freeb(bp);
539: return;
540: }
541:
542: default:
543: freeb(bp);
544: return;
545: }
546: }
547:
548: /*
549: * clean up finished transmit buffers
550: * call at spl5
551: */
552:
553: kbxscan(kk)
554: register struct kbkmc *kk;
555: {
556: register int i;
557:
558: for (i = kk->xrp; i != kk->xwp; i = XNEXT(i)) {
559: if (kk->xring[i].flag & DVALID)
560: break;
561: if (kk->xblock[i] == NULL)
562: panic("kbxscan");
563: ubmfree(kk->ubno, kk->xmap[i]);
564: kk->xmap[i] = 0;
565: freeb(kk->xblock[i]);
566: kk->xblock[i] = NULL;
567: }
568: kk->xrp = i;
569: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.