|
|
1.1 root 1: #include "enp.h"
2: #define ENPBPTE 128
3: #if NENP > 0
4:
5: /*
6: * Modified 3 Com Ethernet Controller interface
7: * enp modifications added S. F. Holmgren
8: */
9:
10: #include "../h/param.h"
11: #include "../h/systm.h"
12: #include "../h/mbuf.h"
13: #include "../h/buf.h"
14: #include "../h/protosw.h"
15: #include "../h/socket.h"
16: #include "../h/vmmac.h"
17: #include "../h/errno.h"
18: #include "../h/time.h"
19: #include "../h/kernel.h"
20: #include "../h/uio.h"
21: #include "../net/if.h"
22: #include "../net/netisr.h"
23: #include "../net/route.h"
24: #include "../netinet/in.h"
25: #include "../h/ioctl.h"
26:
27: #include "../netinet/in_systm.h"
28: #include "../netinet/ip.h"
29: #include "../netinet/ip_var.h"
30: #include "../netinet/if_ether.h"
31: #include "../netpup/pup.h"
32: #include "../vba/vbavar.h"
33: #include "../tahoeif/if_enp.h"
34: #include "../machine/mtpr.h"
35: #include "../tahoeif/if_debug.h"
36:
37: #define ENP0_PHYSADDR 0xf40000 /* board # 0 physical base addr */
38: #define ENP1_PHYSADDR 0xf60000 /* board # 1 physical base addr */
39: #define ENPSTART 0xf02000 /* standard enp start addr */
40:
41: int enpprobe(), enpattach(), enpintr();
42: extern nulldev();
43: caddr_t vtoph();
44: struct mbuf *m_tofree();
45: struct vba_device *enpinfo[ NENP ];
46:
47: /* Maximun 2 controllers per system supported */
48:
49: long enpstd[] = { ENP0_PHYSADDR+0x1000,ENP1_PHYSADDR+0x1000, 0 };
50: extern char enp0utl[], enp1utl[]; /* enp accessible ram map */
51: char *enpmap[]= { enp0utl, enp1utl };
52: extern long ENP0map[], ENP1map[];
53: long *ENPmap[] = {ENP0map, ENP1map};
54: long ENPmapa[] = {0xfff41000, 0xfff61000};
55: long enpismapped[NENP];
56:
57: unsigned short intvec[4] =
58: { 0xc1, 0xc2, 0xc3, 0xc4 }; /* intrvec of upto 4 enps */
59:
60: struct vba_driver enpdriver =
61: {
62: /* use of prom based version
63: enpprobe, 0, enpattach, 0, 0, enpintr,
64: */
65: enpprobe, 0, nulldev, 0,
66: enpstd, "enp", enpinfo, "ENP 20", 0
67: };
68:
69: int enpinit(),
70: enpioctl(),
71: enpoutput(),
72: enpreset(),
73: enpbroadcast(),
74: enptimeout();
75:
76: int enpcopy();
77:
78: struct mbuf *enpget();
79:
80: extern struct ifnet loif;
81:
82: /*
83: * Ethernet software status per interface.
84: *
85: * Each interface is referenced by a network interface structure,
86: * es_if, which the routing code uses to locate the interface.
87: * This structure contains the output queue for the interface, its address, ...
88: */
89:
90: struct enp_softc enp_softc[NENP];
91: long stat_addr[NENP]; /* enp statistic addr (for nstat use) */
92: long ring_addr[NENP]; /* enp dev ring addresses (for nstat use) */
93: int numenp = NENP;
94: int enp_intr = 0, /* no. of enp_to_host interrupts */
95: host_intr = 0; /* no. of host_to_enp interrupts */
96: short enpram[NENP]; /* open/close flags for enp devices */
97: /* Debugging tools, used to trace input packets */
98: extern int printerror; /* error print flag, from if_ace.c */
99: int save_enp_inpkt = 0;
100: #define ENPTRACE(X) if (save_enp_inpkt) X;
101:
102: struct inp_err enperr[NENP];
103:
104: /*
105: * Probe for device.
106: */
107:
108: enpprobe(reg)
109: caddr_t reg;
110: {
111: static int unit=0;
112: register ENPDEVICE *addr = (ENPDEVICE *)reg;
113:
114: if( (badaddr( addr, 2 ) ) || (badaddr( &addr->enp_ram[0], 2 ) ) )
115: return( 0 );
116: addr->enp_state = S_ENPRESET; /* controller is reset by vbus reset */
117: /* save address of statistic area for nstat uses */
118:
119: stat_addr[unit] = (long) &(addr->enp_stat);
120: ring_addr[unit++] = (long) &(addr->enp_toenp);
121:
122: return( ENPSIZE );
123: }
124:
125: /*
126: * Interface exists: make available by filling in network interface
127: * record. System will initialize the interface when it is ready
128: * to accept packets.
129: */
130:
131: enpattach( md )
132: register struct vba_device *md;
133: {
134: struct enp_softc *es = &enp_softc[md->ui_unit];
135: register struct ifnet *ifp = &es->es_if;
136: register ENPDEVICE *addr = (ENPDEVICE *)md->ui_addr;
137: struct sockaddr_in *sin;
138:
139: enpgetaddr( md->ui_unit );
140:
141: ifp->if_unit = md->ui_unit;
142: ifp->if_name = "enp";
143: ifp->if_mtu = ETHERMTU;
144:
145: /* bcopy(&es->es_boardaddr, es->es_enaddr, sizeof(es->es_enaddr)); */
146:
147: sin = (struct sockaddr_in *)&es->es_if.if_addr;
148: sin->sin_family = AF_INET;
149:
150: ifp->if_init = enpinit;
151: ifp->if_ioctl = enpioctl;
152: ifp->if_output = enpoutput;
153: ifp->if_reset = enpreset;
154: if_attach(ifp);
155: }
156:
157:
158: /*
159: * Reset of interface after UNIBUS reset.
160: */
161: enpreset(unit)
162: int unit;
163: {
164: register struct vba_device *md;
165:
166: if (unit >= NENP || (md = enpinfo[unit]) == 0 || md->ui_alive == 0)
167: return(ENODEV);
168:
169: enpinit(unit);
170: }
171:
172: /*
173: * Initialization of interface; clear recorded pending
174: * operations.
175: */
176:
177: enpinit( unit )
178: int unit;
179: {
180: struct enp_softc *es = &enp_softc[unit];
181: ENPDEVICE *addr;
182: int i, s;
183: u_char *cp, *ap;
184: register struct ifnet *ifp = &es->es_if;
185: register struct sockaddr_in *sin, *sinb;
186:
187: sin = (struct sockaddr_in *)&ifp->if_addr;
188:
189: if ( !enpismapped[unit] ) {
190: ioaccess(ENPmap[unit],ENPmapa[unit],ENPBPTE);
191: ++enpismapped[unit];
192: }
193: if ((addr = (ENPDEVICE *)enpinfo[unit]->ui_addr) == (ENPDEVICE *)0)
194: return(ENODEV);
195: s = splimp();
196: RESET_ENP( addr );
197: DELAY( 200000 );
198:
199: #ifdef notdef
200: /* only needed if not downloading ( ie, ROM-resident ENP code) */
201: addr->enp_intrvec = intvec[unit];
202: ENP_GO( addr,ENPSTART );
203: DELAY( 200000 );
204: /* end of ROM-resident */
205: #endif notdef
206:
207: es->es_if.if_flags |= IFF_UP|IFF_RUNNING; /* open for business*/
208: splx(s);
209:
210: if_rtinit( &es->es_if,RTF_UP );
211: arpwhohas(&es->es_ac, &sin->sin_addr);
212: }
213:
214:
215: /*
216: * Ethernet interface interrupt.
217: */
218:
219: enpintr( unit )
220: {
221: register ENPDEVICE *addr;
222: register BCB *bcbp;
223: register struct vba_device *md;
224:
225: enp_intr++;
226:
227: if (unit >= NENP || (md = enpinfo[unit]) == 0)
228: return;
229:
230: addr = (ENPDEVICE *)md->ui_addr;
231:
232: if( IS_ENP_INTR(addr) == 0 )
233: return;
234:
235: ACK_ENP_INTR( addr );
236:
237: while( (bcbp = (BCB *)ringget( &addr->enp_tohost )) != 0 )
238: {
239: enpread( &enp_softc[ unit ],bcbp, unit );
240: ringput( &addr->enp_enpfree,bcbp );
241: }
242: return(0);
243: }
244:
245: #define MAXBLEN 1500
246: char errpkt[MAXBLEN];
247: int bufptr = 0;
248: int maxl_tosave = 200; /* save only the first 200 bytes */
249:
250: saverrpkt(errbuf, errtype, len)
251: register u_char *errbuf;
252: int errtype, len;
253: {
254: int remain, newptr;
255:
256: remain = MAXBLEN - bufptr;
257: if (remain < 50) /* if too small */
258: return; /* no space avail */
259: len = (len > maxl_tosave || len <= 0) ? maxl_tosave : len;
260: len = len > remain ? (remain - 2*sizeof(len)): len;
261: newptr = bufptr + len + 2*sizeof(len);
262: if (newptr <= MAXBLEN) {
263: enpcopy((char *)&len, &errpkt[bufptr], sizeof(len));
264: enpcopy((char *)&errtype, &errpkt[bufptr+sizeof(len)],
265: sizeof(errtype));
266: enpcopy(errbuf, &errpkt[bufptr+(2*sizeof(len))], len);
267: }
268: bufptr = newptr;
269: }
270:
271: /*
272: * Read input packet, examine its packet type, and enqueue it.
273: */
274:
275: enpread( es, bcbp, unit )
276: struct enp_softc *es;
277: register BCB *bcbp;
278: int unit;
279: {
280: register struct ether_header *enp;
281: struct mbuf *m;
282: long int s, v;
283: register short *vp = (short *)&v,
284: *sp;
285: int len, off, resid, enptype;
286: register struct ifqueue *inq;
287:
288: es->es_if.if_ipackets++;
289:
290: /*
291: * Get input data length.
292: * Get pointer to ethernet header (in input buffer).
293: * Deal with trailer protocol: if type is PUP trailer
294: * get true type from first 16-bit word past data.
295: * Remember that type was trailer by setting off.
296: */
297:
298: len = bcbp->b_msglen - SIZEOF_ETHEADER;
299: #ifdef TAHOE
300: sp = (short *)&bcbp->b_addr;
301: *vp = *sp; vp[1] = sp[1];
302: enp = (struct ether_header *) v;
303: #else
304: enp = (struct ether_header *)bcbp->b_addr;
305: #endif TAHOE
306:
307: #define enpdataaddr(enp, off, type) ((type)(((caddr_t)(((char *)enp)+SIZEOF_ETHEADER)+(off))))
308:
309: enptype = enp->ether_type;
310: if (enptype >= ETHERPUP_TRAIL && enptype < ETHERPUP_TRAIL+ETHERPUP_NTRAILER)
311: {
312: off = (enptype - ETHERPUP_TRAIL) * 512;
313: if (off >= ETHERMTU) {
314: enperr[unit].bad_offset++;
315: ENPTRACE(saverrpkt((char *)enp, B_OFFSET, bcbp->b_msglen));
316:
317: goto badinput;
318: }
319: enptype = *enpdataaddr(enp, off, u_short *);
320: resid = *(enpdataaddr(enp, off+2, u_short *));
321:
322: if (off + resid > len) {
323: enperr[unit].bad_length++;
324: ENPTRACE(saverrpkt((char *)enp, B_LENGTH, bcbp->b_msglen));
325: goto badinput;
326: }
327: len = off + resid;
328: }
329: else
330: off = 0;
331:
332: if( len == 0 ) {
333: enperr[unit].bad_length++;
334: ENPTRACE(saverrpkt((char *)enp, B_LENGTH, bcbp->b_msglen));
335: goto badinput;
336: }
337: /*
338: * Pull packet off interface. Off is nonzero if packet
339: * has trailing header; enpget will then force this header
340: * information to be at the front, but we still have to drop
341: * the type and length which are at the front of any trailer data.
342: */
343:
344: m = enpget(bcbp, len, off);
345: if( m == 0 ) {
346: enperr[unit].h_nobuffer++; /* host runs out of buf */
347: goto badinput;
348: }
349: if( off )
350: {
351: m->m_off += 2 * sizeof (u_short);
352: m->m_len -= 2 * sizeof (u_short);
353: }
354:
355: switch (enptype)
356: {
357: #ifdef INET
358: case ETHERPUP_IPTYPE:
359: #ifdef notdef
360: arpipin(enp, m);
361: #endif notdef
362: schednetisr(NETISR_IP);
363: inq = &ipintrq;
364: break;
365:
366: case ETHERPUP_ARPTYPE:
367: arpinput(&es->es_ac, m);
368: return(0);
369: #endif
370: default: /* unrecognized ethernet header */
371: enperr[unit].bad_packetype++;
372: if (printerror) {
373: printf("\nenp%d: Undefined packet type 0x%x ", unit,
374: enp->ether_type);
375: printf("from host: %x.%x.%x.%x.%x.%x\n",
376: enp->ether_shost[0], enp->ether_shost[1],
377: enp->ether_shost[2], enp->ether_shost[3],
378: enp->ether_shost[4], enp->ether_shost[5]);
379: } /* end debugging aid */
380: ENPTRACE(saverrpkt((char *)enp, B_PACKETYPE, bcbp->b_msglen));
381: m_freem(m);
382: goto badinput;
383: }
384:
385: if (IF_QFULL(inq))
386: {
387: enperr[unit].inq_full++;
388: IF_DROP(inq);
389: m_freem(m);
390: return(0);
391: }
392: s = splimp();
393: IF_ENQUEUE(inq, m);
394: splx(s);
395: badinput:
396: return(0); /* sanity */
397: }
398:
399: /*
400: * Ethernet output routine. (called by user)
401: * Encapsulate a packet of type family for the local net.
402: * Use trailer local net encapsulation if enough data in first
403: * packet leaves a multiple of 512 bytes of data in remainder.
404: * If destination is this address or broadcast, send packet to
405: * loop device to kludge around the fact that 3com interfaces can't
406: * talk to themselves.
407: */
408:
409: enpoutput(ifp, m0, dst)
410: struct ifnet *ifp;
411: struct mbuf *m0;
412: struct sockaddr *dst;
413: {
414: int type, s, error;
415: struct ether_addr edst;
416: struct in_addr idst;
417:
418: register struct enp_softc *es = &enp_softc[ifp->if_unit];
419: register struct mbuf *m = m0;
420: register struct ether_header *enp;
421: register int off, i;
422:
423: struct mbuf *mcopy = (struct mbuf *) 0; /* Null */
424: int unit = ifp->if_unit;
425:
426: switch( dst->sa_family )
427: {
428: #ifdef INET
429: case AF_INET:
430: idst = ((struct sockaddr_in *)dst)->sin_addr;
431:
432: /* translate internet to ethernet address */
433:
434: switch(arpresolve(&es->es_ac, m, &idst, &edst)) {
435:
436: case ARPRESOLVE_WILLSEND:
437: return (0); /* if not yet resolved */
438: case ARPRESOLVE_BROADCAST:
439: mcopy = m_copy(m, 0, (int)M_COPYALL);
440: if (mcopy)
441: looutput(&loif, mcopy, dst);
442:
443: /* falls through ... */
444: case ARPRESOLVE_OK:
445: break;
446: }
447: off = ((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
448: if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
449: if (off > 0 && (off & 0x1ff) == 0 &&
450: m->m_off >= MMINOFF + 2 * sizeof (u_short))
451: {
452: type = ETHERPUP_TRAIL + (off>>9);
453: m->m_off -= 2 * sizeof (u_short);
454: m->m_len += 2 * sizeof (u_short);
455: *mtod(m, u_short *) = ETHERPUP_IPTYPE;
456: *(mtod(m, u_short *) + 1) = m->m_len;
457: goto gottrailertype;
458: }
459:
460: type = ETHERPUP_IPTYPE;
461: off = 0;
462: goto gottype;
463: #endif
464:
465: #ifdef notdef
466: case AF_RAW:
467: enp = mtod(m, struct ether_header *);
468: if (m->m_len < sizeof *enp)
469: {
470: error = EMSGSIZE;
471: goto bad;
472: }
473: goto gotheader;
474: #endif
475:
476: case AF_UNSPEC:
477: enp = (struct ether_header *)dst->sa_data;
478: bcopy( enp->ether_dhost, &edst, sizeof(edst));
479: type = enp->ether_type;
480: goto gottype;
481:
482: default:
483: if (printerror)
484: printf("enp%d: can't handle af%d\n", unit,dst->sa_family);
485: error = EAFNOSUPPORT;
486: goto bad;
487: }
488:
489: gottrailertype:
490: /*
491: * Packet to be sent as trailer: move first packet
492: * (control information) to end of chain.
493: */
494: while (m->m_next)
495: m = m->m_next;
496: m->m_next = m0;
497: m = m0->m_next;
498: m0->m_next = 0;
499: m0 = m;
500:
501: gottype:
502: /*
503: * Add local net header. If no space in first mbuf,
504: * allocate another.
505: */
506: if (m->m_off > MMAXOFF ||
507: MMINOFF + SIZEOF_ETHEADER > m->m_off)
508: {
509: m = m_get(M_DONTWAIT, MT_HEADER);
510: if (m == 0)
511: {
512: enperr[unit].h_nobuffer++; /* host runs out of buf */
513: error = ENOBUFS;
514: goto bad;
515: }
516: m->m_next = m0;
517: m->m_off = MMINOFF;
518: m->m_len = SIZEOF_ETHEADER;
519: }
520: else
521: {
522: m->m_off -= SIZEOF_ETHEADER;
523: m->m_len += SIZEOF_ETHEADER;
524: }
525: enp = mtod(m, struct ether_header *);
526: bcopy( &edst, enp->ether_dhost, sizeof(enp->ether_dhost) );
527: enp->ether_type = type;
528: gotheader:
529: bcopy( es->es_enaddr, enp->ether_shost, sizeof(enp->ether_shost));
530:
531: /*
532: * Queue message on interface if possible
533: */
534:
535: s = splimp();
536: if( enpput( unit,m ) )
537: {
538: error = ENOBUFS;
539: enperr[unit].c_nobuffer++; /* controller runs out of buf */
540: goto qfull;
541: }
542: splx( s );
543: es->es_if.if_opackets++;
544: return(0);
545: qfull:
546: splx( s );
547: m0 = m;
548: bad:
549: m_freem(m0);
550: return(error);
551: }
552:
553: /*
554: * Routine to copy from mbuf chain to transmitter
555: * buffer in Multibus memory.
556: */
557:
558: enpput( unit,m )
559: int unit;
560: struct mbuf *m;
561: {
562: register BCB *bcbp;
563: register ENPDEVICE *addr;
564: register struct mbuf *mp;
565: register u_char *bp;
566: int ctr = 0;
567: long int v;
568: register short *vp = (short *)&v,
569: *sp;
570:
571: addr = (ENPDEVICE *)enpinfo[ unit ]->ui_addr;
572:
573: if ( ringempty( &addr->enp_hostfree ) )
574: return( 1 );
575:
576: bcbp = (BCB *)ringget( &addr->enp_hostfree );
577: bcbp->b_len = 0;
578: #ifdef TAHOE
579: sp = (short *)&bcbp->b_addr;
580: *vp = *sp; vp[1] = sp[1];
581: bp = (u_char *)v;
582: #else
583: bp = (u_char *)bcbp->b_addr;
584: #endif TAHOE
585: for (mp = m; mp; mp = mp->m_next)
586: {
587: register unsigned len;
588: u_char *mcp;
589:
590: len = mp->m_len;
591: if( len == 0 )
592: continue;
593: mcp = mtod( mp,u_char * );
594: enpcopy( mcp,bp,len );
595: bp += len;
596: bcbp->b_len += len;
597: }
598: bcbp->b_len = max( MINPKTSIZE,bcbp->b_len );
599: bcbp->b_reserved = 0;
600: if ( ringput( &addr->enp_toenp,bcbp ) == 1 ) {
601: host_intr++;
602: INTR_ENP( addr );
603: }
604: m_freem(m);
605: return( 0 );
606: }
607:
608: /*
609: * Routine to copy from Multibus memory into mbufs.
610: *
611: * Warning: This makes the fairly safe assumption that
612: * mbufs have even lengths.
613: */
614: struct mbuf *
615: enpget( bcbp, totlen, off0 )
616: register BCB *bcbp;
617: int totlen, off0;
618: {
619: register struct mbuf *m;
620: register int off = off0;
621: register unsigned char *cp;
622: long int v;
623: register short *vp = (short *)&v,
624: *sp;
625:
626: int len;
627: struct mbuf *top = 0;
628: struct mbuf **mp = ⊤
629:
630: #ifdef TAHOE
631: sp = (short *)&bcbp->b_addr;
632: *vp = *sp; vp[1] = sp[1];
633: cp = (unsigned char *)v + SIZEOF_ETHEADER;
634: #else
635: cp = (unsigned char *)bcbp->b_addr + SIZEOF_ETHEADER;
636: #endif TAHOE
637:
638: while( totlen > 0 )
639: {
640: u_char *mcp;
641:
642: MGET(m, M_DONTWAIT, MT_DATA);
643: if (m == 0)
644: goto bad;
645: if( off )
646: {
647: len = totlen - off;
648: #ifdef TAHOE
649: sp = (short *)&bcbp->b_addr;
650: *vp = *sp; vp[1] = sp[1];
651: cp = (unsigned char *)v + SIZEOF_ETHEADER
652: + off;
653: #else
654: cp = (unsigned char *)bcbp->b_addr +
655: SIZEOF_ETHEADER + off;
656: #endif TAHOE
657: }
658: else
659: len = totlen;
660:
661:
662: if (len >= CLBYTES) {
663: struct mbuf *p;
664:
665: MCLGET(p, 1);
666: if (p != 0) {
667: m->m_len = len = CLBYTES;
668: m->m_off = (int)p - (int)m;
669: } else {
670: m->m_len = len = MIN(MLEN, len);
671: m->m_off = MMINOFF;
672: }
673: } else {
674: m->m_len = len = MIN(MLEN, len);
675: m->m_off = MMINOFF;
676: }
677:
678: mcp = mtod(m, u_char *);
679: enpcopy(cp, mcp, len);
680: cp += len;
681: *mp = m;
682: mp = &m->m_next;
683: if (off == 0)
684: {
685: totlen -= len;
686: continue;
687: }
688: off += len;
689: if (off == totlen)
690: {
691: #ifdef TAHOE
692: sp = (short *)&bcbp->b_addr;
693: *vp = *sp; vp[1] = sp[1];
694: cp = (unsigned char *)v + SIZEOF_ETHEADER;
695: #else
696: cp = (unsigned char *)bcbp->b_addr + SIZEOF_ETHEADER;
697: #endif TAHOE
698: off = 0;
699: totlen = off0;
700: }
701: }
702: return (top);
703: bad:
704: m_freem(top);
705: return (0);
706: }
707:
708: /*
709: * Process an ioctl request.
710: * this can be called via the "socket" route for SIOCSIFADDR or
711: * by the cdev/inode route for SIOCSIFCCFWR/RD
712: *
713: */
714:
715: enpioctl(ifp, cmd, data)
716: register struct ifnet *ifp;
717: int cmd;
718: caddr_t data;
719: {
720: register int unit = ifp->if_unit;
721: register struct vba_device *md;
722: int s, error = 0;
723: struct sockaddr_in *sin;
724: struct sockaddr *sa;
725: struct enp_softc *es = &enp_softc[ifp->if_unit];
726: ENPDEVICE *addr;
727: struct config_entry *cf;
728: struct ifreq *ifr = (struct ifreq *)data;
729: struct sockaddr_in *et_addr;
730: int code, i;
731:
732:
733: if (unit >= NENP || (md = enpinfo[unit]) == 0 || md->ui_alive == 0)
734: return(ENODEV);
735:
736: switch (cmd) {
737:
738: case SIOCSIFADDR:
739: s = splimp();
740: sa = (struct sockaddr *)&ifr->ifr_addr;
741: if (sa->sa_family == AF_UNSPEC ) {
742: if (sa->sa_data[0] & 1){ /*broad or multi-cast*/
743: splx( s );
744: return( EINVAL );
745: }
746: bcopy(sa->sa_data,es->es_enaddr,sizeof(es->es_enaddr));
747: enpinit( ifp->if_unit);
748: break;
749: }
750: sin = (struct sockaddr_in *)&ifr->ifr_addr;
751: if (sin->sin_family != AF_INET){
752: splx( s );
753: return( EINVAL );
754: }
755: if (ifp->if_flags & IFF_RUNNING)
756: if_rtinit(ifp, -1); /* delete previous route */
757: enpsetaddr(ifp, sin);
758: enpinit(ifp->if_unit);
759: enpgetaddr( ifp->if_unit );
760: splx(s);
761: break;
762:
763:
764: case SIOCSETETADDR: /* Set Ethernet station address */
765: s = splimp();
766: ifp->if_flags &= (~IFF_RUNNING | IFF_UP);
767: et_addr = (struct sockaddr_in *)&ifr->ifr_addr;
768: addr = (ENPDEVICE *)enpinfo[ifp->if_unit]->ui_addr;
769:
770: /* Set station address and reset controller board */
771: {
772: u_char *to = &addr->enp_addr.e_baseaddr.ea_addr[0];
773: char *from = &et_addr->sin_zero[2];
774: int i;
775:
776: for (i = 0 ; i < ETHADDR_SIZE; i++)
777: *to++ = (u_char) (~(*from++ & 0xff));
778: }
779: enpcopy(&addr->enp_addr.e_listsize, &code, sizeof(code));
780: code |= E_ADDR_SUPP;
781: enpcopy(&code, &addr->enp_addr.e_listsize, sizeof(code));
782: enpreset(ifp->if_unit); /* Re-initialize */
783: enpgetaddr(ifp->if_unit);
784: splx(s);
785: break;
786:
787: case SIOCGETETADDR: /* Get Foreign Hosts' Ethernet addresses */
788: arpwhohas(&es->es_ac, (struct in_addr *)ifr->ifr_data);
789: break;
790:
791: default:
792: error = EINVAL;
793: }
794: return(error);
795: }
796:
797: enpsetaddr(ifp, sin)
798: register struct ifnet *ifp;
799: register struct sockaddr_in *sin;
800: {
801:
802: ifp->if_addr = *(struct sockaddr *)sin;
803: ifp->if_net = in_netof(sin->sin_addr);
804: ifp->if_host[0] = in_lnaof(sin->sin_addr);
805: sin = (struct sockaddr_in *)&ifp->if_broadaddr;
806: sin->sin_family = AF_INET;
807: sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY);
808: ifp->if_flags |= IFF_BROADCAST;
809: }
810:
811:
812: /*
813: * Get the ethernet addr, store it and print it
814: * Read the ethernet address off the board, one byte at a time.
815: * put it in enp_softc
816: */
817:
818:
819: enpgetaddr( unit )
820: int unit;
821: {
822: register struct enp_softc *es = &enp_softc[unit];
823: register ENPDEVICE *addr =(ENPDEVICE *)enpinfo[unit]->ui_addr;
824: int i;
825:
826: #ifdef TAHOE
827: enpcopy(&addr->enp_addr.e_baseaddr, &es->es_boardaddr, sizeof(es->es_boardaddr));
828: #else
829: es->es_boardaddr = addr->enp_addr.e_baseaddr;
830: #endif TAHOE
831: bcopy(&es->es_boardaddr, es->es_enaddr, ETHADDR_SIZE);
832: return( 1 );
833: }
834:
835: /*
836: * enpram device
837: *
838: */
839:
840: enpr_open( dev )
841: {
842: register int unit = minor(dev);
843: register struct vba_device *md;
844: register ENPDEVICE *addr;
845:
846: if (unit >= NENP || (md = enpinfo[unit]) == 0 || md->ui_alive == 0 ||
847: (addr = (ENPDEVICE *)md->ui_addr) == (ENPDEVICE *)0)
848: return(ENODEV);
849: if (addr->enp_state != S_ENPRESET)
850: return(EACCES); /* enp is not in reset state, don't open */
851: if ( !enpismapped[unit] ) {
852: ioaccess(ENPmap[unit],ENPmapa[unit],ENPBPTE);
853: ++enpismapped[unit];
854: }
855: enpram[unit] = ENP_OPEN;
856: return( 0 );
857: }
858:
859: enpr_close(dev)
860: {
861: enpram[minor(dev)] = ENP_CLOSE;
862: return( 0 );
863: }
864:
865: enpr_read( dev,uio )
866: int dev;
867: register struct uio *uio;
868: {
869: register ENPDEVICE *addr;
870: register struct iovec *iov;
871: register r=0;
872:
873: if (enpram[minor(dev)] != ENP_OPEN)
874: return(EACCES);
875: if ( uio->uio_offset > RAM_SIZE )
876: return( ENODEV );
877: if ( uio->uio_offset + iov->iov_len > RAM_SIZE )
878: iov->iov_len = RAM_SIZE - uio->uio_offset;
879: addr = (ENPDEVICE *)enpinfo[ minor( dev ) ]->ui_addr;
880: iov = uio->uio_iov;
881:
882: if( r = enpcopyout( &addr->enp_ram[ uio->uio_offset ], iov->iov_base,
883: iov->iov_len ) )
884: return( r );
885:
886: uio->uio_resid -= iov->iov_len;
887: iov->iov_len = 0;
888:
889: return( 0 );
890: }
891:
892: enpr_write( dev,uio )
893: int dev;
894: register struct uio *uio;
895: {
896: register ENPDEVICE *addr;
897: register struct iovec *iov;
898: register r=0;
899:
900: if (enpram[minor(dev)] != ENP_OPEN)
901: return(EACCES);
902: addr = (ENPDEVICE *)enpinfo[ minor( dev ) ]->ui_addr;
903: iov = uio->uio_iov;
904:
905: if ( uio->uio_offset > RAM_SIZE )
906: return( ENODEV );
907: if ( uio->uio_offset + iov->iov_len > RAM_SIZE )
908: iov->iov_len = RAM_SIZE - uio->uio_offset;
909: if( r = enpcopyin( iov->iov_base, &addr->enp_ram[ uio->uio_offset ],
910: iov->iov_len ) )
911: return( r );
912:
913: uio->uio_resid -= iov->iov_len;
914: iov->iov_len = 0;
915:
916: return( 0 );
917: }
918:
919: enpr_ioctl( dev,cmd,arg,fflag )
920: dev_t dev;
921: caddr_t *arg;
922: {
923: register ENPDEVICE *addr;
924: long int v;
925: register short *vp = (short *)&v, *sp;
926: register unit = minor(dev);
927: register struct vba_device *md;
928:
929: if (unit >= NENP || (md = enpinfo[unit]) == 0 || md->ui_alive == 0 ||
930: (addr = (ENPDEVICE *)md->ui_addr) == (ENPDEVICE *)0)
931: return(ENODEV);
932: switch( cmd )
933: {
934: case ENPIOGO:
935: /* not needed if prom based version */
936: #ifdef TAHOE
937: sp = (short *)&addr->enp_base;
938: v = (int)addr;
939: *sp = *vp; sp[1] = vp[1];
940: #else
941: addr->enp_base = (int)addr;
942: #endif TAHOE
943: addr->enp_intrvec = intvec[ unit ];
944: ENP_GO( addr, ENPSTART );
945: DELAY( 200000 );
946: enpattach( enpinfo[ unit ] );
947: enpinit( unit );
948: addr->enp_state = S_ENPRUN; /* it is running now */
949: /* end of not needed */
950:
951: break;
952:
953: case ENPIORESET:
954: RESET_ENP( addr );
955: addr->enp_state = S_ENPRESET; /* it is reset now */
956: DELAY( 100000 );
957: break;
958: }
959: return( 0 );
960: }
961:
962: /*
963: * routines to synchronize enp and host
964: */
965:
966: static
967: ringinit( rp,size )
968: register RING *rp;
969: {
970: register int i;
971: register short *sp;
972:
973: rp->r_rdidx = rp->r_wrtidx = 0;
974: rp->r_size = size;
975: }
976:
977: static
978: ringempty( rp )
979: register RING *rp;
980: {
981: return( rp->r_rdidx == rp->r_wrtidx );
982: }
983:
984: static
985: ringfull( rp )
986: register RING *rp;
987: {
988: register short idx;
989:
990: idx = (rp->r_wrtidx + 1) & (rp->r_size-1);
991: return( idx == rp->r_rdidx );
992: }
993:
994: static
995: ringput( rp,v )
996: register RING *rp;
997: {
998: register int idx;
999: register short *vp = (short *)&v,
1000: *sp;
1001:
1002: idx = (rp->r_wrtidx + 1) & (rp->r_size-1);
1003: if( idx != rp->r_rdidx )
1004: {
1005: #ifdef TAHOE
1006: sp = (short *)&rp->r_slot[ rp->r_wrtidx ];
1007: *sp = *vp; sp[1] = vp[1];
1008: #else
1009: rp->r_slot[ rp->r_wrtidx ] = v;
1010: #endif TAHOE
1011: rp->r_wrtidx = idx;
1012: if( (idx -= rp->r_rdidx) < 0 )
1013: idx += rp->r_size;
1014: return( idx ); /* num ring entries */
1015: }
1016: return( 0 );
1017: }
1018:
1019: static
1020: ringget( rp )
1021: register RING *rp;
1022: {
1023: register int i = 0;
1024: long int v;
1025: register short *vp = (short *)&v,
1026: *sp;
1027:
1028: if( rp->r_rdidx != rp->r_wrtidx )
1029: {
1030: #ifdef TAHOE
1031: sp = (short *)&rp->r_slot[ rp->r_rdidx ];
1032: *vp = *sp; vp[1] = sp[1];
1033: i = v;
1034: #else
1035: i = rp->r_slot[ rp->r_rdidx ];
1036: #endif TAHOE
1037: rp->r_rdidx = (++rp->r_rdidx) & (rp->r_size-1);
1038: }
1039: return( i );
1040: }
1041:
1042: #ifdef notdef
1043: struct mbuf *
1044: m_tofree( rp )
1045: register RING *rp;
1046: {
1047: long int v = 0;
1048: register short *vp = (short *)&v,
1049: *sp;
1050:
1051: if( rp->r_rdidx != rp->r_wrtidx )
1052: {
1053: #ifdef TAHOE
1054: sp = (short *)&rp->r_slot[ rp->r_rdidx ];
1055: *vp = *sp; vp[1] = sp[1];
1056: /* *sp = 0xffff; sp[1] = 0xffff; */
1057: #else
1058: v = rp->r_slot[ rp->r_rdidx ];
1059: #endif TAHOE
1060: rp->r_rdidx = (++rp->r_rdidx) & (rp->r_size-1);
1061: }
1062: return( (struct mbuf *)v );
1063: }
1064: #endif
1065: static
1066: fir( rp )
1067: register RING *rp;
1068: {
1069: long int v;
1070: register short *vp = (short *)&v,
1071: *sp;
1072:
1073: if( rp->r_rdidx != rp->r_wrtidx )
1074: #ifdef TAHOE
1075: {
1076: sp = (short *)&rp->r_slot[ rp->r_rdidx ];
1077: *vp = *sp; vp[1] = sp[1];
1078: return( v );
1079: }
1080: #else
1081: return( rp->r_slot[ rp->r_rdidx ] );
1082: #endif TAHOE
1083: else
1084: return( 0 );
1085: }
1086:
1087:
1088: static
1089: prtbytes( addr )
1090: register char *addr;
1091: {
1092: register int i;
1093:
1094: for( i = 0; i < 12; i++ )
1095: {
1096: printf("%X ",*addr&0377);
1097: addr++;
1098: }
1099: printf("\n");
1100: }
1101:
1102: static
1103: enpcopy(from, to, cnt)
1104: register char *from, *to;
1105: register cnt;
1106: {
1107: register c;
1108: register short *f, *t;
1109:
1110: if (((int)from & 01) && ((int)to & 01)) {
1111: /* source & dest at odd addresses */
1112: *to++ = *from++;
1113: --cnt;
1114: }
1115: if (cnt > 1 && (((int)to & 01)==0) && (((int)from & 01)==0)) {
1116: t = (short *) to;
1117: f = (short *) from;
1118: for( c = cnt>>1; c; --c) /* even address copy */
1119: *t++ = *f++;
1120: cnt &= 1;
1121: if ( cnt ) { /* odd len */
1122: from = (char *) f;
1123: to = (char *) t;
1124: *to = *from;
1125: }
1126: }
1127: while (cnt-- > 0) /* one of the address(es) must be odd */
1128: *to++ = *from++;
1129:
1130: }
1131:
1132: static
1133: enpcopyin(userv, kernv, cnt)
1134: {
1135:
1136: if (useracc(userv, cnt, 1)) {
1137: enpcopy( userv, kernv, cnt );
1138: return( 0 );
1139: }
1140: else return( EFAULT );
1141: }
1142:
1143:
1144: static
1145: enpcopyout(kernv, userv, cnt)
1146: {
1147:
1148: if (useracc(userv, cnt, 0)) {
1149: enpcopy( kernv, userv, cnt );
1150: return( 0 );
1151: }
1152: else return( EFAULT );
1153: }
1154: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.