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