|
|
1.1 root 1: /*
2: * first cut at NI port in DEBNA
3: * slower than it need be, because of all the copying;
4: * disallows use of the storage port
5: */
6: #include "sys/param.h"
7: #include "sys/biaddr.h"
8: #include "sys/conf.h"
9: #include "sys/user.h"
10: #include "sys/buf.h"
11: #include "sys/stream.h"
12: #include "sys/biic.h"
13: #include "sys/ethernet.h"
14: #include "sys/enio.h"
15: #include "sys/pte.h"
16: #include "sys/bvp.h"
17: #include "sys/debna.h"
18:
19: caddr_t remqhi();
20:
21:
22: #define PCMDQ 0 /* just one command queue */
23: #define PFREQ 0 /* just one free queue for now */
24:
25: /*
26: * internal ideas about packets
27: */
28:
29: /*
30: * bounds of an Ethernet packet
31: * min is probably uninteresting
32: * max is constrained by the port, which will fuss and shut down
33: * if handed a buffer bigger than ETHERMAXTU+ETHERCKSUM
34: */
35: #define ETHERMINTU 60
36: #define ETHERMAXTU 1514
37: #define ETHERCKSUM 4
38:
39: #define NIRCVBUF (ETHERMAXTU+ETHERCKSUM)
40:
41: struct dgi {
42: struct bvpdg h; /* header */
43: char d[NIRCVBUF];
44: };
45:
46: struct mst {
47: struct bvpmsg h;
48: struct stptdb p;
49: };
50:
51: /*
52: * config stuff
53: */
54: extern struct bnactl bna[];
55: extern struct bnabuf bnabuf[];
56: extern struct biaddr bnaaddr[];
57: extern int bnacnt;
58:
59: long bnaopen();
60: int bnaclose(), bnaput();
61:
62: static struct qinit bnarinit = { noput, NULL, bnaopen, bnaclose, 0, 0 };
63: static struct qinit bnawinit = { bnaput, NULL, bnaopen, bnaclose, 4*ETHERMAXTU, 64 };
64: static struct streamtab bnasinfo = { &bnarinit, &bnawinit };
65: struct cdevsw bnacdev = cstrinit(&bnasinfo);
66:
67: long
68: bnaopen(q, dev)
69: register struct queue *q;
70: dev_t dev;
71: {
72: register int unit, chan;
73: register struct bnachan *bc;
74:
75: unit = minor(dev);
76: chan = unit % BNACHAN;
77: unit /= BNACHAN;
78: if (unit >= bnacnt)
79: return (0);
80: if (bnainit(unit) == 0)
81: return (0);
82: bc = &bna[unit].chan[chan];
83: if (bc->rq)
84: return (0);
85: bc->unit = unit;
86: bc->proto = 0;
87: q->ptr = (caddr_t)bc;
88: q->flag |= QDELIM;
89: WR(q)->ptr = (caddr_t)bc;
90: WR(q)->flag |= QDELIM|QBIGB;
91: bc->rq = q;
92: return (1);
93: }
94:
95: /*
96: * init the bvp port registers and pqb
97: * set up our list of free transmit buffers,
98: * and the free queue for the port
99: * -- only one free queue for now
100: */
101: bnainit(unit)
102: register int unit;
103: {
104: register char *cp;
105: register struct bnactl *bn;
106: register int i;
107:
108: bn = &bna[unit];
109: if (bvpinit(&bn->bvp, &bnaaddr[unit], NIREGS) == 0) {
110: printf("debna %d: can't init\n", unit);
111: return (0);
112: }
113: if (bn->bvp.d->f[PFREQ].f_size == 0) { /* somewhat sleazy init flag */
114: bn->bvp.d->f[PFREQ].f_size = BNABSIZE-BVPHSIZE;
115: cp = bnabuf[unit].rbuf;
116: cp = (char *)(((int)cp + 7) & ~07); /* quad-align */
117: for (i = 0; i < BNARBUF; i++, cp += BNABSIZE) {
118: if (((int)cp&PGOFSET) > (((int)cp+sizeof(struct bvpdg))&PGOFSET))
119: cp = (char *)(((int)cp+PGOFSET)&~PGOFSET);
120: bnarbuf(bn, (struct dgi *)cp);
121: }
122: cp = bnabuf[unit].xbuf;
123: cp = (char *)(((int)cp + 7) & ~07); /* quad-align */
124: for (i = 0; i < BNAXBUF; i++, cp += BNABSIZE) {
125: if (((int)cp&PGOFSET) > (((int)cp+sizeof(struct bvpdg))&PGOFSET))
126: cp = (char *)(((int)cp+PGOFSET)&~PGOFSET);
127: bnaxbuf(bn, (struct dgi *)cp);
128: }
129: }
130: bcopy(bn->bvp.r->addr, bn->myaddr, sizeof(bn->myaddr));
131: return (1);
132: }
133:
134: bnaclose(q)
135: register struct queue *q;
136: {
137: register struct bnachan *bc;
138:
139: bc = (struct bnachan *)q->ptr;
140: /* turn off PTDB? */
141: bc->rq = NULL;
142: bc->proto = 0;
143: }
144:
145: /*
146: * output put
147: */
148: bnaput(q, bp)
149: register struct queue *q;
150: register struct block *bp;
151: {
152: register struct bnachan *bc;
153: register int s;
154:
155: bc = (struct bnachan *)q->ptr;
156: switch (bp->type) {
157: case M_IOCTL:
158: bnaioctl(q, bp);
159: return;
160:
161: case M_DATA:
162: putq(q, bp);
163: if (bp->class & S_DELIM)
164: break;
165: return;
166:
167: default:
168: freeb(bp);
169: return;
170: }
171: /*
172: * at least a whole packet on the queue
173: */
174: bc->dcnt++;
175: s = spl6();
176: while (bnasend(bc->unit))
177: ;
178: splx(s);
179: }
180:
181: bnaioctl(q, bp)
182: register struct queue *q;
183: register struct block *bp;
184: {
185: register struct bnachan *bc;
186: register struct bnactl *bn;
187:
188: bc = (struct bnachan *)q->ptr;
189: bn = &bna[bc->unit];
190: bp->type = M_IOCACK;
191: switch (stiocom(bp)) {
192: case ENIOTYPE: /* set proto */
193: bc->proto = *((int *)stiodata(bp));
194: bnastptdb(bn, bc);
195: freeb(bp); /* IOCACK when the port finishes */
196: return;
197:
198: case ENIOADDR:
199: bcopy(bn->myaddr, stiodata(bp), sizeof(bn->myaddr));
200: bp->wptr = bp->rptr + sizeof(bn->myaddr) + STIOCHDR;
201: break;
202:
203: default:
204: bp->type = M_IOCNAK;
205: break;
206: }
207: qreply(q, bp);
208: }
209:
210: bnastptdb(bn, bc)
211: register struct bnactl *bn;
212: register struct bnachan *bc;
213: {
214: register struct mst *dp;
215: register int s;
216:
217: s = spl6();
218: if ((dp = (struct mst *)bn->xfree) == NULL) {
219: bc->needst = 1;
220: bn->needst = 1;
221: splx(s);
222: return;
223: }
224: bn->xfree = (struct dgi *)(dp->h.q.head);
225: bc->needst = 0;
226: splx(s);
227: bzero((caddr_t)dp, sizeof(*dp));
228: dp->h.bd_opc = BVPSNDMSG;
229: dp->h.bd_flag = BVPRSP;
230: dp->h.bm_len = sizeof(*dp) - ((char *)&dp->h.bm_opc - (char *)dp);
231: dp->h.bm_opc = NISTPTDB;
232: dp->p.pt_proto = bc->proto;
233: dp->p.pt_fqi = PFREQ;
234: dp->p.pt_flag = PTABM|PTAAM;
235: dp->p.pt_id = bc - bn->chan;
236: if (insqti((caddr_t)dp, &bn->bvp.d->p.p_cmdq[PCMDQ]))
237: bvpcomm(bn->bvp.r, PCOWN|PCCMDQ|(PCMDQ<<PCDS));
238: }
239:
240: /*
241: * here on an interrupt
242: */
243: bna0int(unit)
244: int unit;
245: {
246: register struct bvpdata *b;
247: register struct bnactl *bn;
248: register struct dgi *dp;
249: register struct bnabuf *bf; /* just for safety check */
250: register int i;
251:
252: if ((unsigned)unit >= bnacnt)
253: panic("bna0int");
254: bn = &bna[unit];
255: if (bn->bvp.r == NULL) {
256: printf("debna %d stray intr\n", unit);
257: return;
258: }
259: bn->bvp.rsave = *bn->bvp.r; /* copy all, for debugging */
260: if (bn->bvp.rsave.stat & PSOWN)
261: bn->bvp.r->stat &=~ PSOWN; /* allow fresh status */
262: if ((bn->bvp.rsave.stat & PSSTAT) != SENAB) {
263: printf("debna %d: ps %x pe %x pd %x\n", unit,
264: bn->bvp.rsave.stat, bn->bvp.rsave.err, bn->bvp.rsave.data);
265: return;
266: }
267: b = bn->bvp.d;
268: bf = &bnabuf[unit];
269: while ((dp = (struct dgi *)remqhi(&b->p.p_rspq)) != NULL) {
270: if (dp->h.bd_sts != BVPSUC)
271: printf("debna %d opc %x sts %x\n", unit, dp->h.bd_opc, dp->h.bd_sts);
272: switch (dp->h.bd_opc) {
273: case BVPSNDDGI: /* datagram sent */
274: for (i = ETHERALEN-1; i >= 0; --i)
275: if (((struct etherpup *)dp->d)->dhost[i] != 0xff
276: && ((struct etherpup *)dp->d)->dhost[i] != bn->myaddr[i])
277: goto notecho;
278: /*
279: * packet sent to ourselves;
280: * port won't echo it back
281: */
282: dp->h.bd_len += ETHERCKSUM; /* banrdg will trim */
283: bcopy(bn->myaddr, ((struct etherpup *)dp->d)->shost, sizeof(bn->myaddr));
284: bnardg(bn, dp);
285: notecho:
286: /* fall through */
287: case BVPSNDMSG: /* message sent */
288: if ((char *)dp < bf->xbuf
289: || (char *)dp >= &bf->xbuf[sizeof(bf->xbuf)])
290: panic("bna0int sent");
291: bnaxbuf(bn, dp);
292: continue;
293:
294: case BVPRCVDGI: /* datagram received */
295: if ((char *)dp < bf->rbuf
296: || (char *)dp >= &bf->rbuf[sizeof(bf->rbuf)])
297: panic("bna0int rcv dg");
298: bnardg(bn, dp);
299: bnarbuf(bn, dp);
300: continue;
301:
302: case BVPRCVMSG: /* message received */
303: if ((char *)dp < bf->rbuf
304: || (char *)dp >= &bf->rbuf[sizeof(bf->rbuf)])
305: panic("bna0int rcv msg");
306: bnarmsg(bn, (struct bvpmsg *)dp);
307: bnarbuf(bn, dp);
308: continue;
309:
310: default:
311: printf("debna %d: %x: opc %x\n", unit, dp, dp->h.bd_opc);
312: continue; /* leaving buffer tied up */
313: }
314: }
315: while (bnasend(unit))
316: ;
317: }
318:
319: /*
320: * here is a received datagram;
321: * find the right channel,
322: * and send it up the queue
323: */
324: bnardg(bn, dp)
325: register struct bnactl *bn;
326: register struct dgi *dp;
327: {
328: register int n;
329: register struct block *bp;
330: register char *p;
331: register struct queue *q;
332: int len;
333: short proto;
334:
335: if (dp->h.bd_dgsts != NISUC) {
336: printf("debna %d dg sts %x\n", bn - bna, dp->h.bd_dgsts);
337: return;
338: }
339: len = (dp->h.bd_len+BVPHSIZE)-sizeof(struct bvpdg)-ETHERCKSUM;
340: proto = (short)((struct etherpup *)dp->d)->type;
341: for (n = 0; n < BNACHAN; n++)
342: if (bn->chan[n].proto == proto)
343: break;
344: if (n >= BNACHAN)
345: return; /* unexpected proto */
346: q = bn->chan[n].rq;
347: if (q == NULL)
348: return; /* snh */
349: if (q->next->flag & QFULL)
350: return; /* no room */
351: p = dp->d;
352: while (len > 0) {
353: if ((bp = allocb(len)) == NULL)
354: return; /* wrong, but hard */
355: n = bp->lim - bp->wptr;
356: if (len < n)
357: n = len;
358: bcopy(p, bp->wptr, n);
359: bp->wptr += n;
360: p += n;
361: len -= n;
362: if (len <= 0)
363: bp->class |= S_DELIM;
364: (*q->next->qinfo->putp)(q->next, bp);
365: }
366: }
367:
368: /*
369: * here is a message
370: */
371:
372: bnarmsg(bn, dp)
373: register struct bnactl *bn;
374: register struct bvpmsg *dp;
375: {
376: register struct bnachan *bc;
377: register struct mst *sdp;
378:
379: switch (dp->bm_opc) {
380: case NISTPTDB: /* ptdb set, sent ioctl back */
381: sdp = (struct mst *)dp;
382: if (sdp->p.pt_id < 0 || sdp->p.pt_id >= BNACHAN)
383: panic("bnastptdb");
384: bc = &bn->chan[sdp->p.pt_id];
385: if (bc->rq == NULL || bc->proto != sdp->p.pt_proto)
386: return; /* early close? */
387: if (sdp->h.bm_nists != NISUC)
388: printf("debna %d %d stptdb sts %x\n", bn - bna,
389: sdp->p.pt_id, sdp->h.bm_nists);
390: putctl(bc->rq->next, M_IOCACK);
391: return;
392:
393: default:
394: printf("debna %d msg opc %x sts %x\n", dp->bm_opc, dp->bm_nists);
395: return;
396: }
397: }
398:
399: /*
400: * find a channel with a packet,
401: * find a buffer,
402: * and send
403: */
404: bnasend(unit)
405: int unit;
406: {
407: register struct bnactl *bn;
408: register struct bnachan *bc;
409: register struct dgi *dp;
410: register char *p;
411: register struct block *bp;
412: register int n;
413: char *ep;
414:
415: bn = &bna[unit];
416: n = bn->lastx;
417: while (bn->chan[n].dcnt == 0) {
418: if (++n >= BNACHAN)
419: n = 0;
420: if (n == bn->lastx)
421: return (0); /* nothing to send */
422: }
423: bn->lastx = n;
424: bc = &bn->chan[n];
425: if ((dp = bn->xfree) == NULL)
426: return (0); /* no buffer */
427: bn->xfree = (struct dgi *)dp->h.q.head;
428: bzero((caddr_t)&dp->h, sizeof(dp->h));
429: p = dp->d;
430: ep = p + sizeof(dp->d);
431: while ((bp = getq(WR(bc->rq))) != NULL) {
432: n = bp->wptr - bp->rptr;
433: if (p + n > ep)
434: n = ep - p; /* quietly truncate */
435: if (n) {
436: bcopy(bp->rptr, p, n);
437: p += n;
438: }
439: if (bp->class & S_DELIM) {
440: bc->dcnt--;
441: freeb(bp);
442: break;
443: }
444: freeb(bp);
445: }
446: if (bp == NULL) {
447: printf("debna %d no delim\n", unit);
448: bc->dcnt = 0;
449: dp->h.q.head = (quadque *)bn->xfree;
450: bn->xfree = dp;
451: return (1); /* ok to try another channel */
452: }
453: if (p - dp->d < ETHERMINTU)
454: p = dp->d + ETHERMINTU; /* quietly extend */
455: dp->h.bd_opc = BVPSNDDGI;
456: dp->h.bd_flag = BVPRSP; /* so it will appear on rsp queue */
457: dp->h.bd_len = p - &dp->h.bd_dgsts;
458: dp->h.bd_ptdb = unit; /* some valid number */
459: /* probably should zero some other fields */
460: if (insqti((caddr_t)dp, &bn->bvp.d->p.p_cmdq[PCMDQ]))
461: bvpcomm(bn->bvp.r, PCOWN|PCCMDQ|(PCMDQ<<PCDS));
462: return (1);
463: }
464:
465: /*
466: * free a buffer for the port to fill in
467: * -- port fusses if buffer bigger than an Ethernet packet + BVP header
468: */
469: bnarbuf(bn, dp)
470: register struct bnactl *bn;
471: register struct dgi *dp;
472: {
473:
474: dp->h.bd_sts = 0; /* just in case */
475: dp->h.bd_opc = BVPRCVDGI;
476: dp->h.bd_len = sizeof(struct bvpdg) + NIRCVBUF - BVPHSIZE;
477: if (insqti((caddr_t)dp, &bn->bvp.d->f[PFREQ].f_q))
478: bvpcomm(bn->bvp.r, PCOWN|PCFREQ|(PFREQ<<PCDS));
479: }
480:
481: bnaxbuf(bn, dp)
482: register struct bnactl *bn;
483: register struct dgi *dp;
484: {
485: register int i;
486:
487: dp->h.q.head = (quadque *)bn->xfree;
488: bn->xfree = dp;
489: if (bn->needst) {
490: bn->needst = 0;
491: for (i = 0; i < BNACHAN; i++)
492: if (bn->chan[i].needst)
493: bnastptdb(bn, &bn->chan[i]);
494: }
495: }
496:
497: /*
498: * (fairly) general BVP routines
499: */
500: bvpinit(bv, ap, roff)
501: register struct bvp *bv;
502: struct biaddr *ap;
503: int roff;
504: {
505: register struct bvpregs *r;
506: register struct biic *rb;
507: register long ps; /* most recent status */
508:
509: if ((rb = bv->rb) == NULL) {
510: if ((rb = (struct biic *)biaddr(ap)) == NULL
511: || badaddr(rb, sizeof(long))) {
512: printf("bvp absent\n");
513: return (0);
514: }
515: bv->rb = rb;
516: }
517: if (bv->r == NULL) {
518: r = (struct bvpregs *)((char *)rb + roff);
519: if (badaddr(r, sizeof(long))) {
520: printf("bvp off %x absent\n", roff);
521: return (0);
522: }
523: bv->r = r;
524: }
525: if (bv->dbuf == NULL) {
526: bv->dbuf = geteblk();
527: if (bv->dbuf->b_bcount < sizeof(struct bvpdata)) {
528: printf("bcount too small\n");
529: brelse(bv->dbuf);
530: return (0);
531: }
532: clrbuf(bv->dbuf);
533: bv->d = (struct bvpdata *)bv->dbuf->b_un.b_addr;
534: }
535: r = bv->r;
536: ps = r->stat;
537: if ((ps & PSSTAT) == SUNDEF) {
538: biinit(ap, 0);
539: bvpdatinit(bv->d);
540: bv->d->p.p_nodmsk = rb->biintr;
541: bv->d->p.p_vector = (ap->vec<<2) | 5; /* vec, br */
542: bvpcomm(r, physadr(&bv->d->p)|PCOWN|PCINIT);
543: ps = bvpstat(r);
544: }
545: if ((ps & PSSTAT) == SINIT) {
546: bvpcomm(r, PCOWN|PCENAB);
547: ps = bvpstat(r);
548: }
549: if ((ps & PSSTAT) != SENAB) {
550: printf("ps %x pe %x pd %x\n", r->stat, r->err, r->data);
551: return (0);
552: }
553: return (1);
554: }
555:
556: bvpdatinit(b)
557: register struct bvpdata *b;
558: {
559: bzero((char *)b, sizeof(*b));
560: b->p.p_nfreeq = NFREEQ;
561: b->p.p_fqb = b->f;
562: b->p.p_bvplvl = 1;
563: b->p.p_pqb = &b->p;
564: b->p.p_bdt = b->b;
565: b->p.p_bdtlen = NBDT; /* -1? */
566: b->p.p_spt = (struct pte *)physadr(Sysmap);
567: b->p.p_sptlen = 0x100000; /* huge */
568: b->p.p_gpt = b->p.p_spt;
569: b->p.p_gptlen = b->p.p_sptlen;
570: }
571:
572: /*
573: * send a port command
574: */
575: #define COMMTIME 1000000
576:
577: bvpcomm(r, c)
578: register struct bvpregs *r;
579: long c;
580: {
581: register int i;
582:
583: i = COMMTIME;
584: while (r->ctrl & PCOWN)
585: if (--i <= 0) {
586: printf("bvpcomm timeout c %x\n", c);
587: return; /* what else to do? */
588: }
589: r->stat &=~ PSOWN;
590: r->ctrl = c;
591: }
592:
593: /*
594: * wait for status in init
595: */
596:
597: #define STATTIME 1000000
598:
599: int
600: bvpstat(r)
601: register struct bvpregs *r;
602: {
603: register long ps;
604: register int i;
605:
606: i = STATTIME;
607: while (((ps = r->stat) & PSOWN) == 0)
608: if (--i <= 0) {
609: printf("bvpstat timeout, ps %x\n", ps);
610: return (0);
611: }
612: return (ps);
613: }
614:
615: /*
616: * VAX queue primitives
617: *
618: * -- to set up empty queue, just zero both longwords
619: */
620:
621: /*
622: * remove entry from head;
623: * return entry, or 0 if none
624: */
625: caddr_t
626: remqhi(q)
627: quadque *q;
628: {
629: asm("0: remqhi *4(ap),r0");
630: asm("bcs 0b"); /* couldn't interlock; try again */
631: asm("bvc 1f"); /* br if removed something */
632: asm("clrl r0");
633: asm("1:");
634: }
635:
636: /*
637: * insert entry to tail
638: * return 1 if this was the first entry
639: */
640: insqti(e, q)
641: caddr_t e;
642: quadque *q;
643: {
644: asm("clrl r0");
645: asm("0: insqti *4(ap),*8(ap)");
646: asm("bcs 0b");
647: asm("bneq 1f");
648: asm("incl r0");
649: asm("1:");
650: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.