|
|
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, proto;
333:
334: if (dp->h.bd_dgsts != NISUC) {
335: printf("debna %d dg sts %x\n", bn - bna, dp->h.bd_dgsts);
336: return;
337: }
338: len = (dp->h.bd_len+BVPHSIZE)-sizeof(struct bvpdg)-ETHERCKSUM;
339: proto = ((struct etherpup *)dp->d)->type;
340: for (n = 0; n < BNACHAN; n++)
341: if (bn->chan[n].proto == proto)
342: break;
343: if (n >= BNACHAN)
344: return; /* unexpected proto */
345: q = bn->chan[n].rq;
346: if (q == NULL)
347: return; /* snh */
348: if (q->next->flag & QFULL)
349: return; /* no room */
350: p = dp->d;
351: while (len > 0) {
352: if ((bp = allocb(len)) == NULL)
353: return; /* wrong, but hard */
354: n = bp->lim - bp->wptr;
355: if (len < n)
356: n = len;
357: bcopy(p, bp->wptr, n);
358: bp->wptr += n;
359: p += n;
360: len -= n;
361: if (len <= 0)
362: bp->class |= S_DELIM;
363: (*q->next->qinfo->putp)(q->next, bp);
364: }
365: }
366:
367: /*
368: * here is a message
369: */
370:
371: bnarmsg(bn, dp)
372: register struct bnactl *bn;
373: register struct bvpmsg *dp;
374: {
375: register struct bnachan *bc;
376: register struct mst *sdp;
377:
378: switch (dp->bm_opc) {
379: case NISTPTDB: /* ptdb set, sent ioctl back */
380: sdp = (struct mst *)dp;
381: if (sdp->p.pt_id < 0 || sdp->p.pt_id >= BNACHAN)
382: panic("bnastptdb");
383: bc = &bn->chan[sdp->p.pt_id];
384: if (bc->rq == NULL || bc->proto != sdp->p.pt_proto)
385: return; /* early close? */
386: if (sdp->h.bm_nists != NISUC)
387: printf("debna %d %d stptdb sts %x\n", bn - bna,
388: sdp->p.pt_id, sdp->h.bm_nists);
389: putctl(bc->rq->next, M_IOCACK);
390: return;
391:
392: default:
393: printf("debna %d msg opc %x sts %x\n", dp->bm_opc, dp->bm_nists);
394: return;
395: }
396: }
397:
398: /*
399: * find a channel with a packet,
400: * find a buffer,
401: * and send
402: */
403: bnasend(unit)
404: int unit;
405: {
406: register struct bnactl *bn;
407: register struct bnachan *bc;
408: register struct dgi *dp;
409: register char *p;
410: register struct block *bp;
411: register int n;
412: char *ep;
413:
414: bn = &bna[unit];
415: n = bn->lastx;
416: while (bn->chan[n].dcnt == 0) {
417: if (++n >= BNACHAN)
418: n = 0;
419: if (n == bn->lastx)
420: return (0); /* nothing to send */
421: }
422: bn->lastx = n;
423: bc = &bn->chan[n];
424: if ((dp = bn->xfree) == NULL)
425: return (0); /* no buffer */
426: bn->xfree = (struct dgi *)dp->h.q.head;
427: bzero((caddr_t)&dp->h, sizeof(dp->h));
428: p = dp->d;
429: ep = p + sizeof(dp->d);
430: while ((bp = getq(WR(bc->rq))) != NULL) {
431: n = bp->wptr - bp->rptr;
432: if (p + n > ep)
433: n = ep - p; /* quietly truncate */
434: if (n) {
435: bcopy(bp->rptr, p, n);
436: p += n;
437: }
438: if (bp->class & S_DELIM) {
439: bc->dcnt--;
440: freeb(bp);
441: break;
442: }
443: freeb(bp);
444: }
445: if (bp == NULL) {
446: printf("debna %d no delim\n", unit);
447: bc->dcnt = 0;
448: dp->h.q.head = (quadque *)bn->xfree;
449: bn->xfree = dp;
450: return (1); /* ok to try another channel */
451: }
452: if (p - dp->d < ETHERMINTU)
453: p = dp->d + ETHERMINTU; /* quietly extend */
454: dp->h.bd_opc = BVPSNDDGI;
455: dp->h.bd_flag = BVPRSP; /* so it will appear on rsp queue */
456: dp->h.bd_len = p - &dp->h.bd_dgsts;
457: dp->h.bd_ptdb = unit; /* some valid number */
458: /* probably should zero some other fields */
459: if (insqti((caddr_t)dp, &bn->bvp.d->p.p_cmdq[PCMDQ]))
460: bvpcomm(bn->bvp.r, PCOWN|PCCMDQ|(PCMDQ<<PCDS));
461: return (1);
462: }
463:
464: /*
465: * free a buffer for the port to fill in
466: * -- port fusses if buffer bigger than an Ethernet packet + BVP header
467: */
468: bnarbuf(bn, dp)
469: register struct bnactl *bn;
470: register struct dgi *dp;
471: {
472:
473: dp->h.bd_sts = 0; /* just in case */
474: dp->h.bd_opc = BVPRCVDGI;
475: dp->h.bd_len = sizeof(struct bvpdg) + NIRCVBUF - BVPHSIZE;
476: if (insqti((caddr_t)dp, &bn->bvp.d->f[PFREQ].f_q))
477: bvpcomm(bn->bvp.r, PCOWN|PCFREQ|(PFREQ<<PCDS));
478: }
479:
480: bnaxbuf(bn, dp)
481: register struct bnactl *bn;
482: register struct dgi *dp;
483: {
484: register int i;
485:
486: dp->h.q.head = (quadque *)bn->xfree;
487: bn->xfree = dp;
488: if (bn->needst) {
489: bn->needst = 0;
490: for (i = 0; i < BNACHAN; i++)
491: if (bn->chan[i].needst)
492: bnastptdb(bn, &bn->chan[i]);
493: }
494: }
495:
496: /*
497: * (fairly) general BVP routines
498: */
499: bvpinit(bv, ap, roff)
500: register struct bvp *bv;
501: struct biaddr *ap;
502: int roff;
503: {
504: register struct bvpregs *r;
505: register struct biic *rb;
506: register long ps; /* most recent status */
507:
508: if ((rb = bv->rb) == NULL) {
509: if ((rb = (struct biic *)biaddr(ap)) == NULL
510: || badaddr(rb, sizeof(long))) {
511: printf("bvp absent\n");
512: return (0);
513: }
514: bv->rb = rb;
515: }
516: if (bv->r == NULL) {
517: r = (struct bvpregs *)((char *)rb + roff);
518: if (badaddr(r, sizeof(long))) {
519: printf("bvp off %x absent\n", roff);
520: return (0);
521: }
522: bv->r = r;
523: }
524: if (bv->dbuf == NULL) {
525: bv->dbuf = geteblk();
526: if (bv->dbuf->b_bcount < sizeof(struct bvpdata)) {
527: printf("bcount too small\n");
528: brelse(bv->dbuf);
529: return (0);
530: }
531: clrbuf(bv->dbuf);
532: bv->d = (struct bvpdata *)bv->dbuf->b_un.b_addr;
533: }
534: r = bv->r;
535: ps = r->stat;
536: if ((ps & PSSTAT) == SUNDEF) {
537: biinit(ap, 0);
538: bvpdatinit(bv->d);
539: bv->d->p.p_nodmsk = rb->biintr;
540: bv->d->p.p_vector = (ap->vec<<2) | 5; /* vec, br */
541: bvpcomm(r, physadr(&bv->d->p)|PCOWN|PCINIT);
542: ps = bvpstat(r);
543: }
544: if ((ps & PSSTAT) == SINIT) {
545: bvpcomm(r, PCOWN|PCENAB);
546: ps = bvpstat(r);
547: }
548: if ((ps & PSSTAT) != SENAB) {
549: printf("ps %x pe %x pd %x\n", r->stat, r->err, r->data);
550: return (0);
551: }
552: return (1);
553: }
554:
555: bvpdatinit(b)
556: register struct bvpdata *b;
557: {
558: bzero((char *)b, sizeof(*b));
559: b->p.p_nfreeq = NFREEQ;
560: b->p.p_fqb = b->f;
561: b->p.p_bvplvl = 1;
562: b->p.p_pqb = &b->p;
563: b->p.p_bdt = b->b;
564: b->p.p_bdtlen = NBDT; /* -1? */
565: b->p.p_spt = (struct pte *)physadr(Sysmap);
566: b->p.p_sptlen = 0x100000; /* huge */
567: b->p.p_gpt = b->p.p_spt;
568: b->p.p_gptlen = b->p.p_sptlen;
569: }
570:
571: /*
572: * send a port command
573: */
574: #define COMMTIME 1000000
575:
576: bvpcomm(r, c)
577: register struct bvpregs *r;
578: long c;
579: {
580: register int i;
581:
582: i = COMMTIME;
583: while (r->ctrl & PCOWN)
584: if (--i <= 0) {
585: printf("bvpcomm timeout c %x\n", c);
586: return; /* what else to do? */
587: }
588: r->stat &=~ PSOWN;
589: r->ctrl = c;
590: }
591:
592: /*
593: * wait for status in init
594: */
595:
596: #define STATTIME 1000000
597:
598: int
599: bvpstat(r)
600: register struct bvpregs *r;
601: {
602: register long ps;
603: register int i;
604:
605: i = STATTIME;
606: while (((ps = r->stat) & PSOWN) == 0)
607: if (--i <= 0) {
608: printf("bvpstat timeout, ps %x\n", ps);
609: return (0);
610: }
611: return (ps);
612: }
613:
614: /*
615: * VAX queue primitives
616: *
617: * -- to set up empty queue, just zero both longwords
618: */
619:
620: /*
621: * remove entry from head;
622: * return entry, or 0 if none
623: */
624: caddr_t
625: remqhi(q)
626: quadque *q;
627: {
628: asm("0: remqhi *4(ap),r0");
629: asm("bcs 0b"); /* couldn't interlock; try again */
630: asm("bvc 1f"); /* br if removed something */
631: asm("clrl r0");
632: asm("1:");
633: }
634:
635: /*
636: * insert entry to tail
637: * return 1 if this was the first entry
638: */
639: insqti(e, q)
640: caddr_t e;
641: quadque *q;
642: {
643: asm("clrl r0");
644: asm("0: insqti *4(ap),*8(ap)");
645: asm("bcs 0b");
646: asm("bneq 1f");
647: asm("incl r0");
648: asm("1:");
649: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.