1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)if_en.c 7.1 (Berkeley) 6/5/86
7: */
8:
9: #include "en.h"
10: #include "enetfilter.h"
11: #if NEN > 0
12:
13: /*
14: * Xerox prototype (3 Mb) Ethernet interface driver.
15: */
16: #include "../machine/pte.h"
17:
18: #include "param.h"
19: #include "systm.h"
20: #include "mbuf.h"
21: #include "buf.h"
22: #include "protosw.h"
23: #include "socket.h"
24: #include "vmmac.h"
25: #include "errno.h"
26: #include "ioctl.h"
27:
28: #include "../net/if.h"
29: #include "../net/netisr.h"
30: #include "../net/route.h"
31:
32: #ifdef INET
33: #include "../netinet/in.h"
34: #include "../netinet/in_systm.h"
35: #include "../netinet/in_var.h"
36: #include "../netinet/ip.h"
37: #endif
38:
39: #ifdef PUP
40: #include "../netpup/pup.h"
41: #include "../netpup/ether.h"
42: #endif
43:
44: #ifdef NS
45: #include "../netns/ns.h"
46: #include "../netns/ns_if.h"
47: #endif
48:
49: #include "../vax/cpu.h"
50: #include "../vax/mtpr.h"
51: #include "if_en.h"
52: #include "if_enreg.h"
53: #include "if_uba.h"
54: #if NENETFILTER > 0
55: #include "../net/enet.h"
56: #endif NENETFILTER > 0
57: #include "../vaxuba/ubareg.h"
58: #include "../vaxuba/ubavar.h"
59:
60: #define ENMTU (1024+512)
61: #define ENMRU (1024+512+16) /* 16 is enough to receive trailer */
62:
63: int enprobe(), enattach(), enrint(), enxint(), encollide();
64: struct uba_device *eninfo[NEN];
65: u_short enstd[] = { 0 };
66: struct uba_driver endriver =
67: { enprobe, 0, enattach, 0, enstd, "en", eninfo };
68: #define ENUNIT(x) minor(x)
69:
70: int eninit(),enoutput(),enreset(),enioctl();
71:
72: #ifdef notdef
73: /*
74: * If you need to byte swap IP's in the system, define
75: * this and do a SIOCSIFFLAGS at boot time.
76: */
77: #define ENF_SWABIPS 0x1000
78: #endif
79:
80: /*
81: * Ethernet software status per interface.
82: *
83: * Each interface is referenced by a network interface structure,
84: * es_if, which the routing code uses to locate the interface.
85: * This structure contains the output queue for the interface, its address, ...
86: * We also have, for each interface, a UBA interface structure, which
87: * contains information about the UNIBUS resources held by the interface:
88: * map registers, buffered data paths, etc. Information is cached in this
89: * structure for use by the if_uba.c routines in running the interface
90: * efficiently.
91: */
92: struct en_softc {
93: struct ifnet es_if; /* network-visible interface */
94: struct ifuba es_ifuba; /* UNIBUS resources */
95: short es_host; /* hardware host number */
96: short es_delay; /* current output delay */
97: short es_mask; /* mask for current output delay */
98: short es_lastx; /* host last transmitted to */
99: short es_oactive; /* is output active? */
100: short es_olen; /* length of last output */
101: short es_nsactive; /* is interface enabled for ns? */
102: #if NENETFILTER > 0
103: short es_enetunit; /* unit number for enet filtering */
104: #endif NENETFILTER > 0
105: } en_softc[NEN];
106:
107: /*
108: * Do output DMA to determine interface presence and
109: * interrupt vector. DMA is too short to disturb other hosts.
110: */
111: enprobe(reg)
112: caddr_t reg;
113: {
114: register int br, cvec; /* r11, r10 value-result */
115: register struct endevice *addr = (struct endevice *)reg;
116:
117: #ifdef lint
118: br = 0; cvec = br; br = cvec;
119: enrint(0); enxint(0); encollide(0);
120: #endif
121: addr->en_istat = 0;
122: addr->en_owc = -1;
123: addr->en_oba = 0;
124: addr->en_ostat = EN_IEN|EN_GO;
125: DELAY(100000);
126: addr->en_ostat = 0;
127: return (1);
128: }
129:
130: /*
131: * Interface exists: make available by filling in network interface
132: * record. System will initialize the interface when it is ready
133: * to accept packets.
134: */
135: enattach(ui)
136: struct uba_device *ui;
137: {
138: register struct en_softc *es = &en_softc[ui->ui_unit];
139:
140: es->es_if.if_unit = ui->ui_unit;
141: es->es_if.if_name = "en";
142: es->es_if.if_mtu = ENMTU;
143: es->es_if.if_flags = IFF_BROADCAST;
144: es->es_if.if_init = eninit;
145: es->es_if.if_output = enoutput;
146: es->es_if.if_ioctl = enioctl;
147: es->es_if.if_reset = enreset;
148: es->es_ifuba.ifu_flags = UBA_NEEDBDP | UBA_NEED16 | UBA_CANTWAIT;
149: #if defined(VAX750)
150: /* don't chew up 750 bdp's */
151: if (cpu == VAX_750 && ui->ui_unit > 0)
152: es->es_ifuba.ifu_flags &= ~UBA_NEEDBDP;
153: #endif
154: #if NENETFILTER > 0
155: {
156: struct endevp enp;
157: struct en_header dummy;
158: struct endevice *enaddr = (struct endevice *)ui->ui_addr;
159:
160: #ifdef SWABALL
161: enp.end_dev_type = ENDT_3MB;
162: #else
163: enp.end_dev_type = ENDT_BS3MB; /* packets appear byte-swapped */
164: #endif
165:
166: enp.end_addr_len = sizeof(dummy.en_shost);
167: enp.end_hdr_len = sizeof(struct en_header);
168: enp.end_MTU = ENMTU;
169: enp.end_addr[0] = (~enaddr->en_addr) & 0xFF;
170: enp.end_broadaddr[0] = 0;
171:
172: es->es_enetunit = enetattach(&es->es_if, &enp);
173: }
174: #endif NENETFILTER > 0
175: if_attach(&es->es_if);
176: }
177:
178: /*
179: * Reset of interface after UNIBUS reset.
180: * If interface is on specified uba, reset its state.
181: */
182: enreset(unit, uban)
183: int unit, uban;
184: {
185: register struct uba_device *ui;
186:
187: if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0 ||
188: ui->ui_ubanum != uban)
189: return;
190: printf(" en%d", unit);
191: eninit(unit);
192: }
193:
194: /*
195: * Initialization of interface; clear recorded pending
196: * operations, and reinitialize UNIBUS usage.
197: */
198: eninit(unit)
199: int unit;
200: {
201: register struct en_softc *es = &en_softc[unit];
202: register struct uba_device *ui = eninfo[unit];
203: register struct endevice *addr;
204: int s;
205:
206: if (es->es_if.if_addrlist == (struct ifaddr *)0)
207: return;
208: if (if_ubainit(&es->es_ifuba, ui->ui_ubanum,
209: sizeof (struct en_header), (int)btoc(ENMRU)) == 0) {
210: printf("en%d: can't initialize\n", unit);
211: es->es_if.if_flags &= ~IFF_UP;
212: return;
213: }
214: addr = (struct endevice *)ui->ui_addr;
215: addr->en_istat = addr->en_ostat = 0;
216:
217: /*
218: * Hang a receive and start any
219: * pending writes by faking a transmit complete.
220: */
221: s = splimp();
222: addr->en_iba = es->es_ifuba.ifu_r.ifrw_info;
223: addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1;
224: addr->en_istat = EN_IEN|EN_GO;
225: es->es_oactive = 1;
226: es->es_if.if_flags |= IFF_RUNNING;
227: enxint(unit);
228: splx(s);
229: }
230:
231: int enalldelay = 0;
232: int enlastdel = 50;
233: int enlastmask = (~0) << 5;
234:
235: /*
236: * Start or restart output on interface.
237: * If interface is already active, then this is a retransmit
238: * after a collision, and just restuff registers and delay.
239: * If interface is not already active, get another datagram
240: * to send off of the interface queue, and map it to the interface
241: * before starting the output.
242: */
243: enstart(dev)
244: dev_t dev;
245: {
246: int unit = ENUNIT(dev);
247: struct uba_device *ui = eninfo[unit];
248: register struct en_softc *es = &en_softc[unit];
249: register struct endevice *addr;
250: register struct en_header *en;
251: struct mbuf *m;
252: int dest;
253:
254: if (es->es_oactive)
255: goto restart;
256:
257: /*
258: * Not already active: dequeue another request
259: * and map it to the UNIBUS. If no more requests,
260: * just return.
261: */
262: IF_DEQUEUE(&es->es_if.if_snd, m);
263: if (m == 0) {
264: es->es_oactive = 0;
265: return;
266: }
267: en = mtod(m, struct en_header *);
268: dest = en->en_dhost;
269: en->en_shost = es->es_host;
270: es->es_olen = if_wubaput(&es->es_ifuba, m);
271: #ifdef ENF_SWABIPS
272: /*
273: * The Xerox interface does word at a time DMA, so
274: * someone must do byte swapping of user data if high
275: * and low ender machines are to communicate.
276: */
277: if (es->es_if.if_flags & ENF_SWABIPS) {
278: en = (struct en_header *)es->es_ifuba.ifu_w.ifrw_addr;
279: enswab((caddr_t)(en + 1), (caddr_t)(en + 1),
280: es->es_olen - sizeof (struct en_header) + 1);
281: }
282: #endif
283:
284: /*
285: * Ethernet cannot take back-to-back packets (no
286: * buffering in interface. To help avoid overrunning
287: * receivers, enforce a small delay (about 1ms) in interface:
288: * * between all packets when enalldelay
289: * * whenever last packet was broadcast
290: * * whenever this packet is to same host as last packet
291: */
292: if (enalldelay || es->es_lastx == 0 || es->es_lastx == dest) {
293: es->es_delay = enlastdel;
294: es->es_mask = enlastmask;
295: }
296: es->es_lastx = dest;
297:
298: restart:
299: /*
300: * Have request mapped to UNIBUS for transmission.
301: * Purge any stale data from this BDP, and start the otput.
302: */
303: if (es->es_ifuba.ifu_flags & UBA_NEEDBDP)
304: UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_w.ifrw_bdp);
305: addr = (struct endevice *)ui->ui_addr;
306: addr->en_oba = (int)es->es_ifuba.ifu_w.ifrw_info;
307: addr->en_odelay = es->es_delay;
308: addr->en_owc = -((es->es_olen + 1) >> 1);
309: addr->en_ostat = EN_IEN|EN_GO;
310: es->es_oactive = 1;
311: }
312:
313: /*
314: * Ethernet interface transmitter interrupt.
315: * Start another output if more data to send.
316: */
317: enxint(unit)
318: int unit;
319: {
320: register struct uba_device *ui = eninfo[unit];
321: register struct en_softc *es = &en_softc[unit];
322: register struct endevice *addr = (struct endevice *)ui->ui_addr;
323:
324: if (es->es_oactive == 0)
325: return;
326: if (es->es_mask && (addr->en_ostat&EN_OERROR)) {
327: es->es_if.if_oerrors++;
328: endocoll(unit);
329: return;
330: }
331: es->es_if.if_opackets++;
332: es->es_oactive = 0;
333: es->es_delay = 0;
334: es->es_mask = ~0;
335: if (es->es_ifuba.ifu_xtofree) {
336: m_freem(es->es_ifuba.ifu_xtofree);
337: es->es_ifuba.ifu_xtofree = 0;
338: }
339: if (es->es_if.if_snd.ifq_head == 0) {
340: es->es_lastx = 256; /* putatively illegal */
341: return;
342: }
343: enstart(unit);
344: }
345:
346: /*
347: * Collision on ethernet interface. Do exponential
348: * backoff, and retransmit. If have backed off all
349: * the way print warning diagnostic, and drop packet.
350: */
351: encollide(unit)
352: int unit;
353: {
354: struct en_softc *es = &en_softc[unit];
355:
356: es->es_if.if_collisions++;
357: if (es->es_oactive == 0)
358: return;
359: endocoll(unit);
360: }
361:
362: endocoll(unit)
363: int unit;
364: {
365: register struct en_softc *es = &en_softc[unit];
366:
367: /*
368: * Es_mask is a 16 bit number with n low zero bits, with
369: * n the number of backoffs. When es_mask is 0 we have
370: * backed off 16 times, and give up.
371: */
372: if (es->es_mask == 0) {
373: printf("en%d: send error\n", unit);
374: enxint(unit);
375: return;
376: }
377: /*
378: * Another backoff. Restart with delay based on n low bits
379: * of the interval timer.
380: */
381: es->es_mask <<= 1;
382: es->es_delay = mfpr(ICR) &~ es->es_mask;
383: enstart(unit);
384: }
385:
386: #ifdef notdef
387: struct sockproto enproto = { AF_ETHERLINK };
388: struct sockaddr_en endst = { AF_ETHERLINK };
389: struct sockaddr_en ensrc = { AF_ETHERLINK };
390: #endif
391: /*
392: * Ethernet interface receiver interrupt.
393: * If input error just drop packet.
394: * Otherwise purge input buffered data path and examine
395: * packet to determine type. If can't determine length
396: * from type, then have to drop packet. Othewise decapsulate
397: * packet based on type and pass to type specific higher-level
398: * input routine.
399: */
400: enrint(unit)
401: int unit;
402: {
403: register struct en_softc *es = &en_softc[unit];
404: struct endevice *addr = (struct endevice *)eninfo[unit]->ui_addr;
405: register struct en_header *en;
406: struct mbuf *m;
407: int len; short resid;
408: register struct ifqueue *inq;
409: int off, s;
410:
411: es->es_if.if_ipackets++;
412:
413: /*
414: * Purge BDP; drop if input error indicated.
415: */
416: if (es->es_ifuba.ifu_flags & UBA_NEEDBDP)
417: UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_r.ifrw_bdp);
418: if (addr->en_istat&EN_IERROR) {
419: es->es_if.if_ierrors++;
420: goto setup;
421: }
422:
423: /*
424: * Calculate input data length.
425: * Get pointer to ethernet header (in input buffer).
426: * Deal with trailer protocol: if type is PUP trailer
427: * get true type from first 16-bit word past data.
428: * Remember that type was trailer by setting off.
429: */
430: resid = addr->en_iwc;
431: if (resid)
432: resid |= 0176000;
433: len = (((sizeof (struct en_header) + ENMRU) >> 1) + resid) << 1;
434: len -= sizeof (struct en_header);
435: if (len > ENMRU || len <= 0)
436: goto setup; /* sanity */
437: en = (struct en_header *)(es->es_ifuba.ifu_r.ifrw_addr);
438: #ifdef SWABALL
439: enswab((caddr_t)(en + 1), (caddr_t)(en + 1), len);
440: #else
441: en->en_type = ntohs(en->en_type);
442: #endif SWABALL
443: #define endataaddr(en, off, type) ((type)(((caddr_t)((en)+1)+(off))))
444: if (en->en_type >= ENTYPE_TRAIL &&
445: en->en_type < ENTYPE_TRAIL+ENTYPE_NTRAILER) {
446: off = (en->en_type - ENTYPE_TRAIL) * 512;
447: if (off > ENMTU)
448: goto setup; /* sanity */
449: #ifndef SWABALL
450: en->en_type = *endataaddr(en, off, u_short *);
451: resid = *(endataaddr(en, off+2, u_short *));
452: #else SWABALL
453: en->en_type = ntohs(*endataaddr(en, off, u_short *));
454: resid = ntohs(*(endataaddr(en, off+2, u_short *)));
455: #endif SWABALL
456: if (off + resid > len)
457: goto setup; /* sanity */
458: len = off + resid;
459: } else
460: off = 0;
461: if (len == 0)
462: goto setup;
463: #ifdef ENF_SWABIPS
464: if (es->es_if.if_flags & ENF_SWABIPS && en->en_type == ENTYPE_IP)
465: enswab((caddr_t)(en + 1), (caddr_t)(en + 1), len);
466: #endif
467: /*
468: * Pull packet off interface. Off is nonzero if packet
469: * has trailing header; if_rubaget will then force this header
470: * information to be at the front, but we still have to drop
471: * the type and length which are at the front of any trailer data.
472: */
473: m = if_rubaget(&es->es_ifuba, len, off, &es->es_if);
474: if (m == 0)
475: goto setup;
476: if (off) {
477: struct ifnet *ifp;
478:
479: ifp = *(mtod(m, struct ifnet **));
480: m->m_off += 2 * sizeof (u_short);
481: m->m_len -= 2 * sizeof (u_short);
482: *(mtod(m, struct ifnet **)) = ifp;
483: }
484: switch (en->en_type) {
485:
486: #ifdef INET
487: case ENTYPE_IP:
488: schednetisr(NETISR_IP);
489: inq = &ipintrq;
490: break;
491: #endif
492: #ifdef PUP
493: case ENTYPE_PUP:
494: rpup_input(m);
495: goto setup;
496: #endif
497: #ifdef NS
498: case ETHERTYPE_NS:
499: if (es->es_nsactive) {
500: schednetisr(NETISR_NS);
501: inq = &nsintrq;
502: } else {
503: m_freem(m);
504: goto setup;
505: }
506: break;
507: #endif
508:
509: #if NENETFILTER > 0
510: default:
511: {
512: register struct mbuf *mtop;
513: /*
514: * We need the local net header after all. Oh well,
515: * this could be improved.
516: */
517: MGET(mtop, M_DONTWAIT, MT_DATA);
518: if (mtop == 0) { /* no more mbufs? */
519: m_freem(m); /* wasted effort */
520: goto setup;
521: }
522: #ifdef SWABALL
523: /*
524: * the interface has put en_type in host order and we
525: * want it in net order.
526: */
527: en->en_type = htons(en->en_type);
528: #endif SWABALL
529: bcopy(en, mtod(mtop, struct en_header *),
530: sizeof(struct en_header));
531: mtop->m_len = sizeof(struct en_header);
532: IF_ADJ(m);
533: mtop->m_next = m;
534: enetFilter(es->es_enetunit, mtop,
535: (len + sizeof(struct en_header)) );
536: goto setup;
537: }
538: #else
539: default:
540: #ifdef notdef
541: enproto.sp_protocol = en->en_type;
542: endst.sen_host = en->en_dhost;
543: endst.sen_net = ensrc.sen_net = es->es_if.if_net;
544: ensrc.sen_host = en->en_shost;
545: raw_input(m, &enproto,
546: (struct sockaddr *)&ensrc, (struct sockaddr *)&endst);
547: #else
548: m_freem(m);
549: #endif
550: goto setup;
551: #endif NENETFILTER > 0
552: }
553:
554: s = splimp();
555: if (IF_QFULL(inq)) {
556: IF_DROP(inq);
557: m_freem(m);
558: } else
559: IF_ENQUEUE(inq, m);
560: splx(s);
561:
562: setup:
563: /*
564: * Reset for next packet.
565: */
566: addr->en_iba = es->es_ifuba.ifu_r.ifrw_info;
567: addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1;
568: addr->en_istat = EN_IEN|EN_GO;
569: }
570:
571: /*
572: * Ethernet output routine.
573: * Encapsulate a packet of type family for the local net.
574: * Use trailer local net encapsulation if enough data in first
575: * packet leaves a multiple of 512 bytes of data in remainder.
576: */
577: enoutput(ifp, m0, dst)
578: struct ifnet *ifp;
579: struct mbuf *m0;
580: struct sockaddr *dst;
581: {
582: int type, dest, s, error;
583: register struct mbuf *m = m0;
584: register struct en_header *en;
585: register int off;
586:
587: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
588: error = ENETDOWN;
589: goto bad;
590: }
591: switch (dst->sa_family) {
592:
593: #ifdef INET
594: case AF_INET:
595: {
596: struct in_addr in;
597:
598: in = ((struct sockaddr_in *)dst)->sin_addr;
599: if (in_broadcast(in))
600: dest = EN_BROADCAST;
601: else
602: dest = in_lnaof(in);
603: }
604: if (dest >= 0x100) {
605: error = EPERM; /* ??? */
606: goto bad;
607: }
608: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
609: /* need per host negotiation */
610: if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
611: if (off > 0 && (off & 0x1ff) == 0 &&
612: m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
613: type = ENTYPE_TRAIL + (off>>9);
614: m->m_off -= 2 * sizeof (u_short);
615: m->m_len += 2 * sizeof (u_short);
616: *mtod(m, u_short *) = htons((u_short)ENTYPE_IP);
617: *(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len);
618: goto gottrailertype;
619: }
620: type = ENTYPE_IP;
621: off = 0;
622: goto gottype;
623: #endif
624: #ifdef NS
625: case AF_NS:
626: {
627: u_char *up;
628:
629: type = ETHERTYPE_NS;
630: up = ((struct sockaddr_ns *)dst)->sns_addr.x_host.c_host;
631: if (*up & 1)
632: dest = EN_BROADCAST;
633: else
634: dest = up[5];
635:
636: off = 0;
637: goto gottype;
638: }
639: #endif
640: #ifdef PUP
641: case AF_PUP:
642: dest = ((struct sockaddr_pup *)dst)->spup_host;
643: type = ENTYPE_PUP;
644: off = 0;
645: goto gottype;
646: #endif
647:
648: #if NENETFILTER > 0
649: case AF_IMPLINK:
650: en = mtod(m, struct en_header *);
651: #ifdef SWABALL
652: /*
653: * enstart doesn't swab header fields; en_type is in
654: * net order and interface expects host order.
655: */
656: en->en_type = ntohs(en->en_type);
657: #endif SWABALL
658: goto gotheader;
659: #endif
660:
661: default:
662: printf("en%d: can't handle af%d\n", ifp->if_unit,
663: dst->sa_family);
664: error = EAFNOSUPPORT;
665: goto bad;
666: }
667:
668: gottrailertype:
669: /*
670: * Packet to be sent as trailer: move first packet
671: * (control information) to end of chain.
672: */
673: while (m->m_next)
674: m = m->m_next;
675: m->m_next = m0;
676: m = m0->m_next;
677: m0->m_next = 0;
678: m0 = m;
679:
680: gottype:
681: /*
682: * Add local net header. If no space in first mbuf,
683: * allocate another.
684: */
685: if (m->m_off > MMAXOFF ||
686: MMINOFF + sizeof (struct en_header) > m->m_off) {
687: MGET(m, M_DONTWAIT, MT_HEADER);
688: if (m == 0) {
689: error = ENOBUFS;
690: goto bad;
691: }
692: m->m_next = m0;
693: m->m_off = MMINOFF;
694: m->m_len = sizeof (struct en_header);
695: } else {
696: m->m_off -= sizeof (struct en_header);
697: m->m_len += sizeof (struct en_header);
698: }
699: en = mtod(m, struct en_header *);
700: /* add en_shost later */
701: en->en_dhost = dest;
702: #ifdef SWABALL
703: en->en_type = type;
704: #else
705: en->en_type = htons((u_short)type);
706: #endif
707: #if NENETFILTER > 0
708: : /* will add en_shost later, in enstart() */
709: #endif
710: /*
711: * Queue message on interface, and start output if interface
712: * not yet active.
713: */
714: s = splimp();
715: if (IF_QFULL(&ifp->if_snd)) {
716: IF_DROP(&ifp->if_snd);
717: error = ENOBUFS;
718: goto qfull;
719: }
720: IF_ENQUEUE(&ifp->if_snd, m);
721: if (en_softc[ifp->if_unit].es_oactive == 0)
722: enstart(ifp->if_unit);
723: splx(s);
724: return (0);
725: qfull:
726: m0 = m;
727: splx(s);
728: bad:
729: m_freem(m0);
730: return (error);
731: }
732:
733: /*
734: * Process an ioctl request.
735: */
736: enioctl(ifp, cmd, data)
737: register struct ifnet *ifp;
738: int cmd;
739: caddr_t data;
740: {
741: register struct en_softc *es = ((struct en_softc *)ifp);
742: struct ifaddr *ifa = (struct ifaddr *) data;
743: int s = splimp(), error = 0;
744: struct endevice *enaddr;
745:
746: switch (cmd) {
747:
748: case SIOCSIFADDR:
749: enaddr = (struct endevice *)eninfo[ifp->if_unit]->ui_addr;
750: es->es_host = (~enaddr->en_addr) & 0xff;
751: /*
752: * Attempt to check agreement of protocol address
753: * and board address.
754: */
755: switch (ifa->ifa_addr.sa_family) {
756: case AF_INET:
757: if (in_lnaof(IA_SIN(ifa)->sin_addr) != es->es_host)
758: return (EADDRNOTAVAIL);
759: break;
760: #ifdef NS
761: case AF_NS:
762: if (IA_SNS(ifa)->sns_addr.x_host.c_host[5]
763: != es->es_host)
764: return (EADDRNOTAVAIL);
765: es->es_nsactive = 1;
766: break;
767: #endif
768: }
769: ifp->if_flags |= IFF_UP;
770: if ((ifp->if_flags & IFF_RUNNING) == 0)
771: eninit(ifp->if_unit);
772: break;
773:
774: default:
775: error = EINVAL;
776: break;
777: }
778: splx(s);
779: return (error);
780: }
781:
782: #if defined(SWABALL) || defined(ENF_SWABIPS)
783: /*
784: * Swab bytes
785: * Jeffrey Mogul, Stanford
786: */
787: enswab(from, to, n)
788: register unsigned char *from, *to;
789: register int n;
790: {
791: register unsigned long temp;
792:
793: if ((n <= 0) || (n > 0xFFFF)) {
794: printf("enswab: bad len %d\n", n);
795: return;
796: }
797:
798: n >>= 1; n++;
799: #define STEP {temp = *from++;*to++ = *from++;*to++ = temp;}
800: /* round to multiple of 8 */
801: while ((--n) & 07)
802: STEP;
803: n >>= 3;
804: while (--n >= 0) {
805: STEP; STEP; STEP; STEP;
806: STEP; STEP; STEP; STEP;
807: }
808: }
809: #endif
810: #endif