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