|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)if_en.c 7.7 (Berkeley) 12/16/90
34: */
35:
36: #include "en.h"
37: #if NEN > 0
38:
39: /*
40: * Xerox prototype (3 Mb) Ethernet interface driver.
41: */
42: #include "../include/pte.h"
43:
44: #include "sys/param.h"
45: #include "sys/systm.h"
46: #include "sys/mbuf.h"
47: #include "sys/buf.h"
48: #include "sys/protosw.h"
49: #include "sys/socket.h"
50: #include "sys/vmmac.h"
51: #include "sys/errno.h"
52: #include "sys/ioctl.h"
53:
54: #include "net/if.h"
55: #include "net/netisr.h"
56: #include "net/route.h"
57:
58: #ifdef INET
59: #include "netinet/in.h"
60: #include "netinet/in_systm.h"
61: #include "netinet/in_var.h"
62: #include "netinet/ip.h"
63: #endif
64:
65: #ifdef PUP
66: #include "netpup/pup.h"
67: #include "netpup/ether.h"
68: #endif
69:
70: #ifdef NS
71: #include "netns/ns.h"
72: #include "netns/ns_if.h"
73: #endif
74:
75: #include "../include/cpu.h"
76: #include "../include/mtpr.h"
77: #include "if_en.h"
78: #include "if_enreg.h"
79: #include "if_uba.h"
80: #include "../uba/ubareg.h"
81: #include "../uba/ubavar.h"
82:
83: #define ENMTU (1024+512)
84: #define ENMRU (1024+512+16) /* 16 is enough to receive trailer */
85:
86: int enprobe(), enattach(), enrint(), enxint(), encollide();
87: struct uba_device *eninfo[NEN];
88: u_short enstd[] = { 0 };
89: struct uba_driver endriver =
90: { enprobe, 0, enattach, 0, enstd, "en", eninfo };
91: #define ENUNIT(x) minor(x)
92:
93: int eninit(),oldenoutput(),enreset(),enioctl(), enstart();
94:
95: #ifdef notdef
96: /*
97: * If you need to byte swap IP's in the system, define
98: * this and do a SIOCSIFFLAGS at boot time.
99: */
100: #define ENF_SWABIPS 0x1000
101: #endif
102:
103: /*
104: * Ethernet software status per interface.
105: *
106: * Each interface is referenced by a network interface structure,
107: * es_if, which the routing code uses to locate the interface.
108: * This structure contains the output queue for the interface, its address, ...
109: * We also have, for each interface, a UBA interface structure, which
110: * contains information about the UNIBUS resources held by the interface:
111: * map registers, buffered data paths, etc. Information is cached in this
112: * structure for use by the if_uba.c routines in running the interface
113: * efficiently.
114: */
115: struct en_softc {
116: struct ifnet es_if; /* network-visible interface */
117: struct ifuba es_ifuba; /* UNIBUS resources */
118: short es_host; /* hardware host number */
119: short es_delay; /* current output delay */
120: short es_mask; /* mask for current output delay */
121: short es_lastx; /* host last transmitted to */
122: short es_oactive; /* is output active? */
123: short es_olen; /* length of last output */
124: short es_nsactive; /* is interface enabled for ns? */
125: } en_softc[NEN];
126:
127: /*
128: * Do output DMA to determine interface presence and
129: * interrupt vector. DMA is too short to disturb other hosts.
130: */
131: enprobe(reg)
132: caddr_t reg;
133: {
134: register int br, cvec; /* r11, r10 value-result */
135: register struct endevice *addr = (struct endevice *)reg;
136:
137: #ifdef lint
138: br = 0; cvec = br; br = cvec;
139: enrint(0); enxint(0); encollide(0);
140: #endif
141: addr->en_istat = 0;
142: addr->en_owc = -1;
143: addr->en_oba = 0;
144: addr->en_ostat = EN_IEN|EN_GO;
145: DELAY(100000);
146: addr->en_ostat = 0;
147: return (1);
148: }
149:
150: /*
151: * Interface exists: make available by filling in network interface
152: * record. System will initialize the interface when it is ready
153: * to accept packets.
154: */
155: enattach(ui)
156: struct uba_device *ui;
157: {
158: register struct en_softc *es = &en_softc[ui->ui_unit];
159:
160: es->es_if.if_unit = ui->ui_unit;
161: es->es_if.if_name = "en";
162: es->es_if.if_mtu = ENMTU;
163: es->es_if.if_flags = IFF_BROADCAST;
164: es->es_if.if_init = eninit;
165: es->es_if.if_output = oldenoutput;
166: es->es_if.if_start = enstart;
167: es->es_if.if_ioctl = enioctl;
168: es->es_if.if_reset = enreset;
169: es->es_ifuba.ifu_flags = UBA_NEEDBDP | UBA_NEED16 | UBA_CANTWAIT;
170: #if defined(VAX750)
171: /* don't chew up 750 bdp's */
172: if (cpu == VAX_750 && ui->ui_unit > 0)
173: es->es_ifuba.ifu_flags &= ~UBA_NEEDBDP;
174: #endif
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. It doesn't
276: * belong here, but certain people depend on it, so...
277: *
278: * Should swab everybody, but this is a kludge anyway.
279: */
280: if (es->es_if.if_flags & ENF_SWABIPS) {
281: en = (struct en_header *)es->es_ifuba.ifu_w.ifrw_addr;
282: if (en->en_type == ENTYPE_IP)
283: enswab((caddr_t)(en + 1), (caddr_t)(en + 1),
284: es->es_olen - sizeof (struct en_header) + 1);
285: }
286: #endif
287:
288: /*
289: * Ethernet cannot take back-to-back packets (no
290: * buffering in interface. To help avoid overrunning
291: * receivers, enforce a small delay (about 1ms) in interface:
292: * * between all packets when enalldelay
293: * * whenever last packet was broadcast
294: * * whenever this packet is to same host as last packet
295: */
296: if (enalldelay || es->es_lastx == 0 || es->es_lastx == dest) {
297: es->es_delay = enlastdel;
298: es->es_mask = enlastmask;
299: }
300: es->es_lastx = dest;
301:
302: restart:
303: /*
304: * Have request mapped to UNIBUS for transmission.
305: * Purge any stale data from this BDP, and start the otput.
306: */
307: if (es->es_ifuba.ifu_flags & UBA_NEEDBDP)
308: UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_w.ifrw_bdp);
309: addr = (struct endevice *)ui->ui_addr;
310: addr->en_oba = (int)es->es_ifuba.ifu_w.ifrw_info;
311: addr->en_odelay = es->es_delay;
312: addr->en_owc = -((es->es_olen + 1) >> 1);
313: addr->en_ostat = EN_IEN|EN_GO;
314: es->es_oactive = 1;
315: }
316:
317: /*
318: * Ethernet interface transmitter interrupt.
319: * Start another output if more data to send.
320: */
321: enxint(unit)
322: int unit;
323: {
324: register struct uba_device *ui = eninfo[unit];
325: register struct en_softc *es = &en_softc[unit];
326: register struct endevice *addr = (struct endevice *)ui->ui_addr;
327:
328: if (es->es_oactive == 0)
329: return;
330: if (es->es_mask && (addr->en_ostat&EN_OERROR)) {
331: es->es_if.if_oerrors++;
332: endocoll(unit);
333: return;
334: }
335: es->es_if.if_opackets++;
336: es->es_oactive = 0;
337: es->es_delay = 0;
338: es->es_mask = ~0;
339: if (es->es_ifuba.ifu_xtofree) {
340: m_freem(es->es_ifuba.ifu_xtofree);
341: es->es_ifuba.ifu_xtofree = 0;
342: }
343: if (es->es_if.if_snd.ifq_head == 0) {
344: es->es_lastx = 256; /* putatively illegal */
345: return;
346: }
347: enstart(unit);
348: }
349:
350: /*
351: * Collision on ethernet interface. Do exponential
352: * backoff, and retransmit. If have backed off all
353: * the way print warning diagnostic, and drop packet.
354: */
355: encollide(unit)
356: int unit;
357: {
358: struct en_softc *es = &en_softc[unit];
359:
360: es->es_if.if_collisions++;
361: if (es->es_oactive == 0)
362: return;
363: endocoll(unit);
364: }
365:
366: endocoll(unit)
367: int unit;
368: {
369: register struct en_softc *es = &en_softc[unit];
370:
371: /*
372: * Es_mask is a 16 bit number with n low zero bits, with
373: * n the number of backoffs. When es_mask is 0 we have
374: * backed off 16 times, and give up.
375: */
376: if (es->es_mask == 0) {
377: printf("en%d: send error\n", unit);
378: enxint(unit);
379: return;
380: }
381: /*
382: * Another backoff. Restart with delay based on n low bits
383: * of the interval timer.
384: */
385: es->es_mask <<= 1;
386: es->es_delay = mfpr(ICR) &~ es->es_mask;
387: enstart(unit);
388: }
389:
390: #ifdef notdef
391: struct sockproto enproto = { AF_ETHERLINK };
392: struct sockaddr_en endst = { sizeof(endst), AF_ETHERLINK };
393: struct sockaddr_en ensrc = { sizeof(ensrc), AF_ETHERLINK };
394: #endif
395: /*
396: * Ethernet interface receiver interrupt.
397: * If input error just drop packet.
398: * Otherwise purge input buffered data path and examine
399: * packet to determine type. If can't determine length
400: * from type, then have to drop packet. Othewise decapsulate
401: * packet based on type and pass to type specific higher-level
402: * input routine.
403: */
404: enrint(unit)
405: int unit;
406: {
407: register struct en_softc *es = &en_softc[unit];
408: struct endevice *addr = (struct endevice *)eninfo[unit]->ui_addr;
409: register struct en_header *en;
410: struct mbuf *m;
411: int len; short resid;
412: register struct ifqueue *inq;
413: int off, s;
414:
415: es->es_if.if_ipackets++;
416:
417: /*
418: * Purge BDP; drop if input error indicated.
419: */
420: if (es->es_ifuba.ifu_flags & UBA_NEEDBDP)
421: UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_r.ifrw_bdp);
422: if (addr->en_istat&EN_IERROR) {
423: es->es_if.if_ierrors++;
424: goto setup;
425: }
426:
427: /*
428: * Calculate input data length.
429: * Get pointer to ethernet header (in input buffer).
430: * Deal with trailer protocol: if type is PUP trailer
431: * get true type from first 16-bit word past data.
432: * Remember that type was trailer by setting off.
433: */
434: resid = addr->en_iwc;
435: if (resid)
436: resid |= 0176000;
437: len = (((sizeof (struct en_header) + ENMRU) >> 1) + resid) << 1;
438: len -= sizeof (struct en_header);
439: if (len > ENMRU)
440: goto setup; /* sanity */
441: en = (struct en_header *)(es->es_ifuba.ifu_r.ifrw_addr);
442: en->en_type = ntohs(en->en_type);
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: en->en_type = ntohs(*endataaddr(en, off, u_short *));
450: resid = ntohs(*(endataaddr(en, off+2, u_short *)));
451: if (off + resid > len)
452: goto setup; /* sanity */
453: len = off + resid;
454: } else
455: off = 0;
456: if (len == 0)
457: goto setup;
458: #ifdef ENF_SWABIPS
459: if (es->es_if.if_flags & ENF_SWABIPS && en->en_type == ENTYPE_IP)
460: enswab((caddr_t)(en + 1), (caddr_t)(en + 1), len);
461: #endif
462: /*
463: * Pull packet off interface. Off is nonzero if packet
464: * has trailing header; if_rubaget will then force this header
465: * information to be at the front, but we still have to drop
466: * the type and length which are at the front of any trailer data.
467: */
468: m = if_rubaget(&es->es_ifuba, len, off, &es->es_if);
469: if (m == 0)
470: goto setup;
471: switch (en->en_type) {
472:
473: #ifdef INET
474: case ENTYPE_IP:
475: schednetisr(NETISR_IP);
476: inq = &ipintrq;
477: break;
478: #endif
479: #ifdef PUP
480: case ENTYPE_PUP:
481: rpup_input(m);
482: goto setup;
483: #endif
484: #ifdef NS
485: case ETHERTYPE_NS:
486: if (es->es_nsactive) {
487: schednetisr(NETISR_NS);
488: inq = &nsintrq;
489: } else {
490: m_freem(m);
491: goto setup;
492: }
493: break;
494: #endif
495:
496: default:
497: #ifdef notdef
498: enproto.sp_protocol = en->en_type;
499: endst.sen_host = en->en_dhost;
500: endst.sen_net = ensrc.sen_net = es->es_if.if_net;
501: ensrc.sen_host = en->en_shost;
502: raw_input(m, &enproto,
503: (struct sockaddr *)&ensrc, (struct sockaddr *)&endst);
504: #else
505: m_freem(m);
506: #endif
507: goto setup;
508: }
509:
510: s = splimp();
511: if (IF_QFULL(inq)) {
512: IF_DROP(inq);
513: m_freem(m);
514: } else
515: IF_ENQUEUE(inq, m);
516: splx(s);
517:
518: setup:
519: /*
520: * Reset for next packet.
521: */
522: addr->en_iba = es->es_ifuba.ifu_r.ifrw_info;
523: addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1;
524: addr->en_istat = EN_IEN|EN_GO;
525: }
526:
527: /*
528: * Ethernet output routine.
529: * Encapsulate a packet of type family for the local net.
530: * Use trailer local net encapsulation if enough data in first
531: * packet leaves a multiple of 512 bytes of data in remainder.
532: */
533: oldenoutput(ifp, m0, dst)
534: struct ifnet *ifp;
535: struct mbuf *m0;
536: struct sockaddr *dst;
537: {
538: int type, dest, s, error;
539: register struct mbuf *m = m0;
540: register struct en_header *en;
541: register int off;
542:
543: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
544: error = ENETDOWN;
545: goto bad;
546: }
547: switch (dst->sa_family) {
548:
549: #ifdef INET
550: case AF_INET:
551: {
552: struct in_addr in;
553:
554: in = ((struct sockaddr_in *)dst)->sin_addr;
555: if (in_broadcast(in))
556: dest = EN_BROADCAST;
557: else
558: dest = in_lnaof(in);
559: }
560: if (dest >= 0x100) {
561: error = EPERM; /* ??? */
562: goto bad;
563: }
564: off = m->m_pkthdr.len - m->m_len;
565: /* need per host negotiation */
566: if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
567: if (off > 0 && (off & 0x1ff) == 0 &&
568: (m->m_flags & M_EXT) == 0 &&
569: m->m_data >= m->m_pktdat + 2 * sizeof (u_short)) {
570: type = ENTYPE_TRAIL + (off>>9);
571: m->m_data -= 2 * sizeof (u_short);
572: m->m_len += 2 * sizeof (u_short);
573: *mtod(m, u_short *) = htons((u_short)ENTYPE_IP);
574: *(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len);
575: goto gottrailertype;
576: }
577: type = ENTYPE_IP;
578: off = 0;
579: goto gottype;
580: #endif
581: #ifdef NS
582: case AF_NS:
583: {
584: u_char *up;
585:
586: type = ETHERTYPE_NS;
587: up = ((struct sockaddr_ns *)dst)->sns_addr.x_host.c_host;
588: if (*up & 1)
589: dest = EN_BROADCAST;
590: else
591: dest = up[5];
592:
593: off = 0;
594: goto gottype;
595: }
596: #endif
597: #ifdef PUP
598: case AF_PUP:
599: dest = ((struct sockaddr_pup *)dst)->spup_host;
600: type = ENTYPE_PUP;
601: off = 0;
602: goto gottype;
603: #endif
604:
605: #ifdef notdef
606: case AF_ETHERLINK:
607: goto gotheader;
608: #endif
609:
610: default:
611: printf("en%d: can't handle af%d\n", ifp->if_unit,
612: dst->sa_family);
613: error = EAFNOSUPPORT;
614: goto bad;
615: }
616:
617: gottrailertype:
618: /*
619: * Packet to be sent as trailer: move first packet
620: * (control information) to end of chain.
621: */
622: while (m->m_next)
623: m = m->m_next;
624: m->m_next = m0;
625: m = m0->m_next;
626: m0->m_next = 0;
627: m0 = m;
628:
629: gottype:
630: /*
631: * Add local net header. If no space in first mbuf,
632: * allocate another.
633: */
634: M_PREPEND(m, sizeof (struct en_header), M_DONTWAIT);
635: if (m == NULL)
636: return (ENOBUFS);
637: en = mtod(m, struct en_header *);
638: /* add en_shost later */
639: en->en_dhost = dest;
640: en->en_type = htons((u_short)type);
641:
642: #ifdef notdef
643: gotheader:
644: #endif
645: /*
646: * Queue message on interface, and start output if interface
647: * not yet active.
648: */
649: s = splimp();
650: if (IF_QFULL(&ifp->if_snd)) {
651: IF_DROP(&ifp->if_snd);
652: error = ENOBUFS;
653: goto qfull;
654: }
655: IF_ENQUEUE(&ifp->if_snd, m);
656: if (en_softc[ifp->if_unit].es_oactive == 0)
657: enstart(ifp->if_unit);
658: splx(s);
659: return (0);
660: qfull:
661: m0 = m;
662: splx(s);
663: bad:
664: m_freem(m0);
665: return (error);
666: }
667:
668: /*
669: * Process an ioctl request.
670: */
671: enioctl(ifp, cmd, data)
672: register struct ifnet *ifp;
673: int cmd;
674: caddr_t data;
675: {
676: register struct en_softc *es = ((struct en_softc *)ifp);
677: struct ifaddr *ifa = (struct ifaddr *) data;
678: int s = splimp(), error = 0;
679: struct endevice *enaddr;
680:
681: switch (cmd) {
682:
683: case SIOCSIFADDR:
684: enaddr = (struct endevice *)eninfo[ifp->if_unit]->ui_addr;
685: es->es_host = (~enaddr->en_addr) & 0xff;
686: /*
687: * Attempt to check agreement of protocol address
688: * and board address.
689: */
690: switch (ifa->ifa_addr->sa_family) {
691: case AF_INET:
692: if (in_lnaof(IA_SIN(ifa)->sin_addr) != es->es_host)
693: return (EADDRNOTAVAIL);
694: break;
695: #ifdef NS
696: case AF_NS:
697: if (IA_SNS(ifa)->sns_addr.x_host.c_host[5]
698: != es->es_host)
699: return (EADDRNOTAVAIL);
700: es->es_nsactive = 1;
701: break;
702: #endif
703: }
704: ifp->if_flags |= IFF_UP;
705: if ((ifp->if_flags & IFF_RUNNING) == 0)
706: eninit(ifp->if_unit);
707: break;
708:
709: default:
710: error = EINVAL;
711: break;
712: }
713: splx(s);
714: return (error);
715: }
716:
717: #ifdef ENF_SWABIPS
718: /*
719: * Swab bytes
720: * Jeffrey Mogul, Stanford
721: */
722: enswab(from, to, n)
723: register unsigned char *from, *to;
724: register int n;
725: {
726: register unsigned long temp;
727:
728: if ((n <= 0) || (n > 0xFFFF)) {
729: printf("enswab: bad len %d\n", n);
730: return;
731: }
732:
733: n >>= 1; n++;
734: #define STEP {temp = *from++;*to++ = *from++;*to++ = temp;}
735: /* round to multiple of 8 */
736: while ((--n) & 07)
737: STEP;
738: n >>= 3;
739: while (--n >= 0) {
740: STEP; STEP; STEP; STEP;
741: STEP; STEP; STEP; STEP;
742: }
743: }
744: #endif
745: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.