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