xref: /original-bsd/sys/vax/if/if_il.c (revision 72b8f354)
1 /*
2  * Copyright (c) 1982, 1986 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)if_il.c	7.7 (Berkeley) 06/28/90
8  */
9 
10 #include "il.h"
11 #if NIL > 0
12 
13 /*
14  * Interlan Ethernet Communications Controller interface
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 "ioctl.h"
26 #include "errno.h"
27 #include "syslog.h"
28 
29 #include "../net/if.h"
30 #include "../net/netisr.h"
31 #include "../net/route.h"
32 
33 #ifdef INET
34 #include "../netinet/in.h"
35 #include "../netinet/in_systm.h"
36 #include "../netinet/in_var.h"
37 #include "../netinet/ip.h"
38 #include "../netinet/if_ether.h"
39 #endif
40 
41 #ifdef NS
42 #include "../netns/ns.h"
43 #include "../netns/ns_if.h"
44 #endif
45 
46 #include "../vax/cpu.h"
47 #include "../vax/mtpr.h"
48 #include "if_il.h"
49 #include "if_ilreg.h"
50 #include "if_uba.h"
51 #include "../vaxuba/ubareg.h"
52 #include "../vaxuba/ubavar.h"
53 
54 int	ilprobe(), ilattach(), ilrint(), ilcint();
55 struct	uba_device *ilinfo[NIL];
56 u_short ilstd[] = { 0 };
57 struct	uba_driver ildriver =
58 	{ ilprobe, 0, ilattach, 0, ilstd, "il", ilinfo };
59 #define	ILUNIT(x)	minor(x)
60 int	ilinit(),iloutput(),ilioctl(),ilreset(),ilwatch(),ilstart();
61 int	ildebug = 0;
62 
63 /*
64  * Ethernet software status per interface.
65  *
66  * Each interface is referenced by a network interface structure,
67  * is_if, which the routing code uses to locate the interface.
68  * This structure contains the output queue for the interface, its address, ...
69  * We also have, for each interface, a UBA interface structure, which
70  * contains information about the UNIBUS resources held by the interface:
71  * map registers, buffered data paths, etc.  Information is cached in this
72  * structure for use by the if_uba.c routines in running the interface
73  * efficiently.
74  */
75 
76 struct ether_addr {
77 	u_char	addr[6];
78 };
79 struct	il_softc {
80 	struct	arpcom is_ac;		/* Ethernet common part */
81 #define	is_if	is_ac.ac_if		/* network-visible interface */
82 #define	is_addr	is_ac.ac_enaddr		/* hardware Ethernet address */
83 	struct	ifuba is_ifuba;		/* UNIBUS resources */
84 	int	is_flags;
85 #define	ILF_RCVPENDING	0x2		/* start rcv in ilcint */
86 #define	ILF_STATPENDING	0x4		/* stat cmd pending */
87 #define	ILF_RUNNING	0x8		/* board is running */
88 #define	ILF_SETADDR	0x10		/* physical address is changed */
89 	short	is_lastcmd;		/* can't read csr, so must save it */
90 	short	is_scaninterval;	/* interval of stat collection */
91 #define	ILWATCHINTERVAL	60		/* once every 60 seconds */
92 	union {
93 	    struct	il_stats isu_stats;	/* holds on-board statistics */
94 	    struct	ether_addr isu_maddrs[63];	/* multicast addrs */
95 	}	is_isu;
96 #define is_stats	is_isu.isu_stats
97 #define is_maddrs	is_isu.isu_maddrs
98 	struct	il_stats is_sum;	/* summation over time */
99 	int	is_ubaddr;		/* mapping registers of is_stats */
100 } il_softc[NIL];
101 
102 ilprobe(reg)
103 	caddr_t reg;
104 {
105 	register int br, cvec;		/* r11, r10 value-result */
106 	register struct ildevice *addr = (struct ildevice *)reg;
107 	register i;
108 
109 #ifdef lint
110 	br = 0; cvec = br; br = cvec;
111 	i = 0; ilrint(i); ilcint(i); ilwatch(i);
112 #endif
113 
114 	addr->il_csr = ILC_OFFLINE|IL_CIE;
115 	DELAY(100000);
116 	i = addr->il_csr;		/* clear CDONE */
117 	if (cvec > 0 && cvec != 0x200)
118 		cvec -= 4;
119 	return (1);
120 }
121 
122 /*
123  * Interface exists: make available by filling in network interface
124  * record.  System will initialize the interface when it is ready
125  * to accept packets.  A STATUS command is done to get the ethernet
126  * address and other interesting data.
127  */
128 ilattach(ui)
129 	struct uba_device *ui;
130 {
131 	register struct il_softc *is = &il_softc[ui->ui_unit];
132 	register struct ifnet *ifp = &is->is_if;
133 	register struct ildevice *addr = (struct ildevice *)ui->ui_addr;
134 
135 	ifp->if_unit = ui->ui_unit;
136 	ifp->if_name = "il";
137 	ifp->if_mtu = ETHERMTU;
138 	ifp->if_flags = IFF_BROADCAST;
139 
140 	/*
141 	 * Reset the board and map the statistics
142 	 * buffer onto the Unibus.
143 	 */
144 	addr->il_csr = ILC_RESET;
145 	(void)ilwait(ui, "reset");
146 
147 	is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_stats,
148 	    sizeof (struct il_stats), 0);
149 	addr->il_bar = is->is_ubaddr & 0xffff;
150 	addr->il_bcr = sizeof (struct il_stats);
151 	addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT;
152 	(void)ilwait(ui, "status");
153 	ubarelse(ui->ui_ubanum, &is->is_ubaddr);
154 	if (ildebug)
155 		printf("il%d: module=%s firmware=%s\n", ui->ui_unit,
156 			is->is_stats.ils_module, is->is_stats.ils_firmware);
157  	bcopy((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr,
158  	    sizeof (is->is_addr));
159 	printf("il%d: hardware address %s\n", ui->ui_unit,
160 		ether_sprintf(is->is_addr));
161 	ifp->if_init = ilinit;
162 	ifp->if_output = ether_output;
163 	ifp->if_ioctl = ilioctl;
164 	ifp->if_reset = ilreset;
165 	ifp->if_start = ilstart;
166 	is->is_ifuba.ifu_flags = UBA_CANTWAIT;
167 	if_attach(ifp);
168 }
169 
170 ilwait(ui, op)
171 	struct uba_device *ui;
172 	char *op;
173 {
174 	register struct ildevice *addr = (struct ildevice *)ui->ui_addr;
175 
176 	while ((addr->il_csr&IL_CDONE) == 0)
177 		;
178 	if (addr->il_csr&IL_STATUS) {
179 		printf("il%d: %s failed, csr=%b\n", ui->ui_unit, op,
180 			addr->il_csr, IL_BITS);
181 		return (-1);
182 	}
183 	return (0);
184 }
185 
186 /*
187  * Reset of interface after UNIBUS reset.
188  * If interface is on specified uba, reset its state.
189  */
190 ilreset(unit, uban)
191 	int unit, uban;
192 {
193 	register struct uba_device *ui;
194 
195 	if (unit >= NIL || (ui = ilinfo[unit]) == 0 || ui->ui_alive == 0 ||
196 	    ui->ui_ubanum != uban)
197 		return;
198 	printf(" il%d", unit);
199 	il_softc[unit].is_if.if_flags &= ~IFF_RUNNING;
200 	il_softc[unit].is_flags &= ~ILF_RUNNING;
201 	ilinit(unit);
202 }
203 
204 /*
205  * Initialization of interface; clear recorded pending
206  * operations, and reinitialize UNIBUS usage.
207  */
208 ilinit(unit)
209 	int unit;
210 {
211 	register struct il_softc *is = &il_softc[unit];
212 	register struct uba_device *ui = ilinfo[unit];
213 	register struct ildevice *addr;
214 	register struct ifnet *ifp = &is->is_if;
215 	int s;
216 
217 	/* not yet, if address still unknown */
218 	if (ifp->if_addrlist == (struct ifaddr *)0)
219 		return;
220 	if (is->is_flags & ILF_RUNNING)
221 		return;
222 
223 	if ((ifp->if_flags & IFF_RUNNING) == 0) {
224 		if (if_ubainit(&is->is_ifuba, ui->ui_ubanum,
225 		    sizeof (struct il_rheader), (int)btoc(ETHERMTU)) == 0) {
226 			printf("il%d: can't initialize\n", unit);
227 			is->is_if.if_flags &= ~IFF_UP;
228 			return;
229 		}
230 		is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_isu,
231 		    sizeof (is->is_isu), 0);
232 	}
233 	ifp->if_watchdog = ilwatch;
234 	is->is_scaninterval = ILWATCHINTERVAL;
235 	ifp->if_timer = is->is_scaninterval;
236 	addr = (struct ildevice *)ui->ui_addr;
237 
238 	/*
239 	 * Turn off source address insertion (it's faster this way),
240 	 * and set board online.  Former doesn't work if board is
241 	 * already online (happens on ubareset), so we put it offline
242 	 * first.
243 	 */
244 	s = splimp();
245 	addr->il_csr = ILC_RESET;
246 	if (ilwait(ui, "hardware diag")) {
247  		is->is_if.if_flags &= ~IFF_UP;
248  		splx(s);
249  		return;
250  	}
251 	addr->il_csr = ILC_CISA;
252 	while ((addr->il_csr & IL_CDONE) == 0)
253 		;
254 	/*
255 	 * If we must reprogram this board's physical ethernet
256 	 * address (as for secondary XNS interfaces), we do so
257 	 * before putting it on line, and starting receive requests.
258 	 * If you try this on an older 1010 board, it will total
259 	 * wedge the board.
260 	 */
261 	if (is->is_flags & ILF_SETADDR) {
262 		bcopy((caddr_t)is->is_addr, (caddr_t)&is->is_isu,
263 							sizeof is->is_addr);
264 		addr->il_bar = is->is_ubaddr & 0xffff;
265 		addr->il_bcr = sizeof is->is_addr;
266 		addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_LDPA;
267 		if (ilwait(ui, "setaddr"))
268 			return;
269 		addr->il_bar = is->is_ubaddr & 0xffff;
270 		addr->il_bcr = sizeof (struct il_stats);
271 		addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT;
272 		if (ilwait(ui, "verifying setaddr"))
273 			return;
274 		if (bcmp((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr,
275 						sizeof (is->is_addr)) != 0) {
276 			printf("il%d: setaddr didn't work\n", ui->ui_unit);
277 			return;
278 		}
279 	}
280 #ifdef MULTICAST
281 	if (is->is_if.if_flags & IFF_PROMISC) {
282 		addr->il_csr = ILC_PRMSC;
283 		if (ilwait(ui, "all multi"))
284 			return;
285 	} else if (is->is_if.if_flags & IFF_ALLMULTI) {
286 	too_many_multis:
287 		addr->il_csr = ILC_ALLMC;
288 		if (ilwait(ui, "all multi"))
289 			return;
290 	else {
291 		int i;
292 		register struct ether_addr *ep = is->is_maddrs;
293 		struct ether_multi *enm;
294 		struct ether_multistep step;
295 		/*
296 		 * Step through our list of multicast addresses.  If we have
297 		 * too many multicast addresses, or if we have to listen to
298 		 * a range of multicast addresses, turn on reception of all
299 		 * multicasts.
300 		 */
301 		i = 0;
302 		ETHER_FIRST_MULTI(step, &is->is_ac, enm);
303 		while (enm != NULL) {
304 			if (++i > 63 && k != 0) {
305 				break;
306 			}
307 			*ep++ = *(struct ether_addr *)enm->enm_addrlo;
308 			ETHER_NEXT_MULTI(step, enm);
309 		}
310 		if (i = 0) {
311 			/* no multicasts! */
312 		} else if (i <= 63) {
313 			addr->il_bar = is->is_ubaddr & 0xffff;
314 			addr->il_bcr = i * sizeof (struct ether_addr);
315 			addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|
316 						LC_LDGRPS;
317 			if (ilwait(ui, "load multi"))
318 				return;
319 		} else {
320 		    is->is_if.if_flags |= IFF_ALLMULTI;
321 		    goto too_many_multis;
322 		}
323 	}
324 #endif MULTI
325 	/*
326 	 * Set board online.
327 	 * Hang receive buffer and start any pending
328 	 * writes by faking a transmit complete.
329 	 * Receive bcr is not a multiple of 8 so buffer
330 	 * chaining can't happen.
331 	 */
332 	addr->il_csr = ILC_ONLINE;
333 	while ((addr->il_csr & IL_CDONE) == 0)
334 		;
335 	addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff;
336 	addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6;
337 	addr->il_csr =
338 	    ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE;
339 	while ((addr->il_csr & IL_CDONE) == 0)
340 		;
341 	is->is_if.if_flags |= IFF_RUNNING | IFF_OACTIVE;
342 	is->is_flags |= ILF_RUNNING;
343 	is->is_lastcmd = 0;
344 	ilcint(unit);
345 	splx(s);
346 }
347 
348 /*
349  * Start output on interface.
350  * Get another datagram to send off of the interface queue,
351  * and map it to the interface before starting the output.
352  */
353 ilstart(ifp)
354 	register struct ifnet *ifp;
355 {
356         int unit = ifp->if_unit, len;
357 	struct uba_device *ui = ilinfo[unit];
358 	register struct il_softc *is = &il_softc[unit];
359 	register struct ildevice *addr;
360 	struct mbuf *m;
361 	short csr;
362 
363 	IF_DEQUEUE(&is->is_if.if_snd, m);
364 	addr = (struct ildevice *)ui->ui_addr;
365 	if (m == 0) {
366 		if ((is->is_flags & ILF_STATPENDING) == 0)
367 			return (0);
368 		addr->il_bar = is->is_ubaddr & 0xffff;
369 		addr->il_bcr = sizeof (struct il_stats);
370 		csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT|IL_RIE|IL_CIE;
371 		is->is_flags &= ~ILF_STATPENDING;
372 		goto startcmd;
373 	}
374 	len = if_wubaput(&is->is_ifuba, m);
375 	/*
376 	 * Ensure minimum packet length.
377 	 * This makes the safe assumtion that there are no virtual holes
378 	 * after the data.
379 	 * For security, it might be wise to zero out the added bytes,
380 	 * but we're mainly interested in speed at the moment.
381 	 */
382 	if (len - sizeof(struct ether_header) < ETHERMIN)
383 		len = ETHERMIN + sizeof(struct ether_header);
384 	if (is->is_ifuba.ifu_flags & UBA_NEEDBDP)
385 		UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_w.ifrw_bdp);
386 	addr->il_bar = is->is_ifuba.ifu_w.ifrw_info & 0xffff;
387 	addr->il_bcr = len;
388 	csr =
389 	  ((is->is_ifuba.ifu_w.ifrw_info >> 2) & IL_EUA)|ILC_XMIT|IL_CIE|IL_RIE;
390 
391 startcmd:
392 	is->is_lastcmd = csr & IL_CMD;
393 	addr->il_csr = csr;
394 	is->is_if.if_flags |= IFF_OACTIVE;
395 	return (0);
396 }
397 
398 /*
399  * Command done interrupt.
400  */
401 ilcint(unit)
402 	int unit;
403 {
404 	register struct il_softc *is = &il_softc[unit];
405 	struct uba_device *ui = ilinfo[unit];
406 	register struct ildevice *addr = (struct ildevice *)ui->ui_addr;
407 	short csr;
408 
409 	if ((is->is_if.if_flags & IFF_OACTIVE) == 0) {
410 		printf("il%d: stray xmit interrupt, csr=%b\n", unit,
411 			addr->il_csr, IL_BITS);
412 		return;
413 	}
414 
415 	csr = addr->il_csr;
416 	/*
417 	 * Hang receive buffer if it couldn't
418 	 * be done earlier (in ilrint).
419 	 */
420 	if (is->is_flags & ILF_RCVPENDING) {
421 		int s;
422 
423 		addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff;
424 		addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6;
425 		addr->il_csr =
426 		  ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE;
427 		s = splhigh();
428 		while ((addr->il_csr & IL_CDONE) == 0)
429 			;
430 		splx(s);
431 		is->is_flags &= ~ILF_RCVPENDING;
432 	}
433 	is->is_if.if_flags &= ~IFF_OACTIVE;
434 	csr &= IL_STATUS;
435 	switch (is->is_lastcmd) {
436 
437 	case ILC_XMIT:
438 		is->is_if.if_opackets++;
439 		if (csr > ILERR_RETRIES)
440 			is->is_if.if_oerrors++;
441 		break;
442 
443 	case ILC_STAT:
444 		if (csr == ILERR_SUCCESS)
445 			iltotal(is);
446 		break;
447 	}
448 	if (is->is_ifuba.ifu_xtofree) {
449 		m_freem(is->is_ifuba.ifu_xtofree);
450 		is->is_ifuba.ifu_xtofree = 0;
451 	}
452 	(void) ilstart(&is->is_if);
453 }
454 
455 /*
456  * Ethernet interface receiver interrupt.
457  * If input error just drop packet.
458  * Otherwise purge input buffered data path and examine
459  * packet to determine type.  If can't determine length
460  * from type, then have to drop packet.  Othewise decapsulate
461  * packet based on type and pass to type specific higher-level
462  * input routine.
463  */
464 ilrint(unit)
465 	int unit;
466 {
467 	register struct il_softc *is = &il_softc[unit];
468 	struct ildevice *addr = (struct ildevice *)ilinfo[unit]->ui_addr;
469 	register struct il_rheader *il;
470     	struct mbuf *m;
471 	int len, off, resid, s;
472 	register struct ifqueue *inq;
473 
474 	is->is_if.if_ipackets++;
475 	if (is->is_ifuba.ifu_flags & UBA_NEEDBDP)
476 		UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_r.ifrw_bdp);
477 	il = (struct il_rheader *)(is->is_ifuba.ifu_r.ifrw_addr);
478 	len = il->ilr_length - sizeof(struct il_rheader);
479 	if ((il->ilr_status&(ILFSTAT_A|ILFSTAT_C)) || len < 46 ||
480 	    len > ETHERMTU) {
481 		is->is_if.if_ierrors++;
482 #ifdef notdef
483 		if (is->is_if.if_ierrors % 100 == 0)
484 			printf("il%d: += 100 input errors\n", unit);
485 #endif
486 		goto setup;
487 	}
488 
489 	/*
490 	 * Deal with trailer protocol: if type is trailer type
491 	 * get true type from first 16-bit word past data.
492 	 * Remember that type was trailer by setting off.
493 	 */
494 	il->ilr_type = ntohs((u_short)il->ilr_type);
495 #define	ildataaddr(il, off, type)	((type)(((caddr_t)((il)+1)+(off))))
496 	if (il->ilr_type >= ETHERTYPE_TRAIL &&
497 	    il->ilr_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
498 		off = (il->ilr_type - ETHERTYPE_TRAIL) * 512;
499 		if (off >= ETHERMTU)
500 			goto setup;		/* sanity */
501 		il->ilr_type = ntohs(*ildataaddr(il, off, u_short *));
502 		resid = ntohs(*(ildataaddr(il, off+2, u_short *)));
503 		if (off + resid > len)
504 			goto setup;		/* sanity */
505 		len = off + resid;
506 	} else
507 		off = 0;
508 	if (len == 0)
509 		goto setup;
510 
511 	/*
512 	 * Pull packet off interface.  Off is nonzero if packet
513 	 * has trailing header; ilget will then force this header
514 	 * information to be at the front, but we still have to drop
515 	 * the type and length which are at the front of any trailer data.
516 	 */
517 	m = if_rubaget(&is->is_ifuba, len, off, &is->is_if);
518 	if (m)
519 		ether_input(&is->is_if, (struct ether_header *)il->ilr_dhost, m);
520 setup:
521 	/*
522 	 * Reset for next packet if possible.
523 	 * If waiting for transmit command completion, set flag
524 	 * and wait until command completes.
525 	 */
526 	if (is->is_if.if_flags & IFF_OACTIVE) {
527 		is->is_flags |= ILF_RCVPENDING;
528 		return;
529 	}
530 	addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff;
531 	addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6;
532 	addr->il_csr =
533 		((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE;
534 	s = splhigh();
535 	while ((addr->il_csr & IL_CDONE) == 0)
536 		;
537 	splx(s);
538 }
539 /*
540  * Watchdog routine, request statistics from board.
541  */
542 ilwatch(unit)
543 	int unit;
544 {
545 	register struct il_softc *is = &il_softc[unit];
546 	register struct ifnet *ifp = &is->is_if;
547 	int s;
548 
549 	if (is->is_flags & ILF_STATPENDING) {
550 		ifp->if_timer = is->is_scaninterval;
551 		return;
552 	}
553 	s = splimp();
554 	is->is_flags |= ILF_STATPENDING;
555 	if ((is->is_if.if_flags & IFF_OACTIVE) == 0)
556 		(void) ilstart(ifp);
557 	splx(s);
558 	ifp->if_timer = is->is_scaninterval;
559 }
560 
561 /*
562  * Total up the on-board statistics.
563  */
564 iltotal(is)
565 	register struct il_softc *is;
566 {
567 	register u_short *interval, *sum, *end;
568 
569 	interval = &is->is_stats.ils_frames;
570 	sum = &is->is_sum.ils_frames;
571 	end = is->is_sum.ils_fill2;
572 	while (sum < end)
573 		*sum++ += *interval++;
574 	is->is_if.if_collisions = is->is_sum.ils_collis;
575 	if ((is->is_flags & ILF_SETADDR) &&
576 	    (bcmp((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr,
577 					sizeof (is->is_addr)) != 0)) {
578 		log(LOG_ERR, "il%d: physaddr reverted\n", is->is_if.if_unit);
579 		is->is_flags &= ~ILF_RUNNING;
580 		ilinit(is->is_if.if_unit);
581 	}
582 }
583 
584 /*
585  * Process an ioctl request.
586  */
587 ilioctl(ifp, cmd, data)
588 	register struct ifnet *ifp;
589 	int cmd;
590 	caddr_t data;
591 {
592 	register struct ifaddr *ifa = (struct ifaddr *)data;
593 	register struct il_softc *is = &il_softc[ifp->if_unit];
594 	int s = splimp(), error = 0;
595 
596 	switch (cmd) {
597 
598 	case SIOCSIFADDR:
599 		ifp->if_flags |= IFF_UP;
600 		ilinit(ifp->if_unit);
601 
602 		switch (ifa->ifa_addr->sa_family) {
603 #ifdef INET
604 		case AF_INET:
605 			((struct arpcom *)ifp)->ac_ipaddr =
606 				IA_SIN(ifa)->sin_addr;
607 			arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
608 			break;
609 #endif
610 #ifdef NS
611 		case AF_NS:
612 		    {
613 			register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
614 
615 			if (ns_nullhost(*ina)) {
616 				ina->x_host = * (union ns_host *)
617 				     (il_softc[ifp->if_unit].is_addr);
618 			} else {
619 				il_setaddr(ina->x_host.c_host, ifp->if_unit);
620 				return (0);
621 			}
622 			break;
623 		    }
624 #endif
625 		}
626 		break;
627 
628 	case SIOCSIFFLAGS:
629 		if ((ifp->if_flags & IFF_UP) == 0 &&
630 		    is->is_flags & ILF_RUNNING) {
631 			((struct ildevice *)
632 			   (ilinfo[ifp->if_unit]->ui_addr))->il_csr = ILC_RESET;
633 			is->is_flags &= ~ILF_RUNNING;
634 		} else if (ifp->if_flags & IFF_UP &&
635 		    (is->is_flags & ILF_RUNNING) == 0)
636 			ilinit(ifp->if_unit);
637 		break;
638 
639 	default:
640 		error = EINVAL;
641 	}
642 	splx(s);
643 	return (error);
644 }
645 
646 /*
647  * set ethernet address for unit
648  */
649 il_setaddr(physaddr, unit)
650 u_char *physaddr;
651 int unit;
652 {
653 	register struct il_softc *is = &il_softc[unit];
654 
655 	if (! (is->is_flags & ILF_RUNNING))
656 		return;
657 
658 	bcopy((caddr_t)physaddr, (caddr_t)is->is_addr, sizeof is->is_addr);
659 	is->is_flags &= ~ILF_RUNNING;
660 	is->is_flags |= ILF_SETADDR;
661 	ilinit(unit);
662 }
663 #endif
664