xref: /original-bsd/sys/vax/if/if_il.c (revision 2c26d2e3)
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 are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)if_il.c	7.3 (Berkeley) 08/04/88
18  */
19 
20 #include "il.h"
21 #if NIL > 0
22 
23 /*
24  * Interlan Ethernet Communications Controller interface
25  */
26 #include "../machine/pte.h"
27 
28 #include "param.h"
29 #include "systm.h"
30 #include "mbuf.h"
31 #include "buf.h"
32 #include "protosw.h"
33 #include "socket.h"
34 #include "vmmac.h"
35 #include "ioctl.h"
36 #include "errno.h"
37 #include "syslog.h"
38 
39 #include "../net/if.h"
40 #include "../net/netisr.h"
41 #include "../net/route.h"
42 
43 #ifdef INET
44 #include "../netinet/in.h"
45 #include "../netinet/in_systm.h"
46 #include "../netinet/in_var.h"
47 #include "../netinet/ip.h"
48 #include "../netinet/if_ether.h"
49 #endif
50 
51 #ifdef NS
52 #include "../netns/ns.h"
53 #include "../netns/ns_if.h"
54 #endif
55 
56 #include "../vax/cpu.h"
57 #include "../vax/mtpr.h"
58 #include "if_il.h"
59 #include "if_ilreg.h"
60 #include "if_uba.h"
61 #include "../vaxuba/ubareg.h"
62 #include "../vaxuba/ubavar.h"
63 
64 int	ilprobe(), ilattach(), ilrint(), ilcint();
65 struct	uba_device *ilinfo[NIL];
66 u_short ilstd[] = { 0 };
67 struct	uba_driver ildriver =
68 	{ ilprobe, 0, ilattach, 0, ilstd, "il", ilinfo };
69 #define	ILUNIT(x)	minor(x)
70 int	ilinit(),iloutput(),ilioctl(),ilreset(),ilwatch();
71 int	ildebug = 0;
72 
73 /*
74  * Ethernet software status per interface.
75  *
76  * Each interface is referenced by a network interface structure,
77  * is_if, which the routing code uses to locate the interface.
78  * This structure contains the output queue for the interface, its address, ...
79  * We also have, for each interface, a UBA interface structure, which
80  * contains information about the UNIBUS resources held by the interface:
81  * map registers, buffered data paths, etc.  Information is cached in this
82  * structure for use by the if_uba.c routines in running the interface
83  * efficiently.
84  */
85 struct	il_softc {
86 	struct	arpcom is_ac;		/* Ethernet common part */
87 #define	is_if	is_ac.ac_if		/* network-visible interface */
88 #define	is_addr	is_ac.ac_enaddr		/* hardware Ethernet address */
89 	struct	ifuba is_ifuba;		/* UNIBUS resources */
90 	int	is_flags;
91 #define	ILF_OACTIVE	0x1		/* output is active */
92 #define	ILF_RCVPENDING	0x2		/* start rcv in ilcint */
93 #define	ILF_STATPENDING	0x4		/* stat cmd pending */
94 #define	ILF_RUNNING	0x8		/* board is running */
95 #define	ILF_SETADDR	0x10		/* physical address is changed */
96 	short	is_lastcmd;		/* can't read csr, so must save it */
97 	short	is_scaninterval;	/* interval of stat collection */
98 #define	ILWATCHINTERVAL	60		/* once every 60 seconds */
99 	struct	il_stats is_stats;	/* holds on-board statistics */
100 	struct	il_stats is_sum;	/* summation over time */
101 	int	is_ubaddr;		/* mapping registers of is_stats */
102 } il_softc[NIL];
103 
104 ilprobe(reg)
105 	caddr_t reg;
106 {
107 	register int br, cvec;		/* r11, r10 value-result */
108 	register struct ildevice *addr = (struct ildevice *)reg;
109 	register i;
110 
111 #ifdef lint
112 	br = 0; cvec = br; br = cvec;
113 	i = 0; ilrint(i); ilcint(i); ilwatch(i);
114 #endif
115 
116 	addr->il_csr = ILC_OFFLINE|IL_CIE;
117 	DELAY(100000);
118 	i = addr->il_csr;		/* clear CDONE */
119 	if (cvec > 0 && cvec != 0x200)
120 		cvec -= 4;
121 	return (1);
122 }
123 
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.  A STATUS command is done to get the ethernet
128  * address and other interesting data.
129  */
130 ilattach(ui)
131 	struct uba_device *ui;
132 {
133 	register struct il_softc *is = &il_softc[ui->ui_unit];
134 	register struct ifnet *ifp = &is->is_if;
135 	register struct ildevice *addr = (struct ildevice *)ui->ui_addr;
136 
137 	ifp->if_unit = ui->ui_unit;
138 	ifp->if_name = "il";
139 	ifp->if_mtu = ETHERMTU;
140 	ifp->if_flags = IFF_BROADCAST;
141 
142 	/*
143 	 * Reset the board and map the statistics
144 	 * buffer onto the Unibus.
145 	 */
146 	addr->il_csr = ILC_RESET;
147 	(void)ilwait(ui, "reset");
148 
149 	is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_stats,
150 	    sizeof (struct il_stats), 0);
151 	addr->il_bar = is->is_ubaddr & 0xffff;
152 	addr->il_bcr = sizeof (struct il_stats);
153 	addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT;
154 	(void)ilwait(ui, "status");
155 	ubarelse(ui->ui_ubanum, &is->is_ubaddr);
156 	if (ildebug)
157 		printf("il%d: module=%s firmware=%s\n", ui->ui_unit,
158 			is->is_stats.ils_module, is->is_stats.ils_firmware);
159  	bcopy((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr,
160  	    sizeof (is->is_addr));
161 	printf("il%d: hardware address %s\n", ui->ui_unit,
162 		ether_sprintf(is->is_addr));
163 	ifp->if_init = ilinit;
164 	ifp->if_output = iloutput;
165 	ifp->if_ioctl = ilioctl;
166 	ifp->if_reset = ilreset;
167 	is->is_ifuba.ifu_flags = UBA_CANTWAIT;
168 	if_attach(ifp);
169 }
170 
171 ilwait(ui, op)
172 	struct uba_device *ui;
173 	char *op;
174 {
175 	register struct ildevice *addr = (struct ildevice *)ui->ui_addr;
176 
177 	while ((addr->il_csr&IL_CDONE) == 0)
178 		;
179 	if (addr->il_csr&IL_STATUS) {
180 		printf("il%d: %s failed, csr=%b\n", ui->ui_unit, op,
181 			addr->il_csr, IL_BITS);
182 		return (-1);
183 	}
184 	return (0);
185 }
186 
187 /*
188  * Reset of interface after UNIBUS reset.
189  * If interface is on specified uba, reset its state.
190  */
191 ilreset(unit, uban)
192 	int unit, uban;
193 {
194 	register struct uba_device *ui;
195 
196 	if (unit >= NIL || (ui = ilinfo[unit]) == 0 || ui->ui_alive == 0 ||
197 	    ui->ui_ubanum != uban)
198 		return;
199 	printf(" il%d", unit);
200 	il_softc[unit].is_if.if_flags &= ~IFF_RUNNING;
201 	il_softc[unit].is_flags &= ~ILF_RUNNING;
202 	ilinit(unit);
203 }
204 
205 /*
206  * Initialization of interface; clear recorded pending
207  * operations, and reinitialize UNIBUS usage.
208  */
209 ilinit(unit)
210 	int unit;
211 {
212 	register struct il_softc *is = &il_softc[unit];
213 	register struct uba_device *ui = ilinfo[unit];
214 	register struct ildevice *addr;
215 	register struct ifnet *ifp = &is->is_if;
216 	int s;
217 
218 	/* not yet, if address still unknown */
219 	if (ifp->if_addrlist == (struct ifaddr *)0)
220 		return;
221 	if (is->is_flags & ILF_RUNNING)
222 		return;
223 
224 	if ((ifp->if_flags & IFF_RUNNING) == 0) {
225 		if (if_ubainit(&is->is_ifuba, ui->ui_ubanum,
226 		    sizeof (struct il_rheader), (int)btoc(ETHERMTU)) == 0) {
227 			printf("il%d: can't initialize\n", unit);
228 			is->is_if.if_flags &= ~IFF_UP;
229 			return;
230 		}
231 		is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_stats,
232 		    sizeof (struct il_stats), 0);
233 	}
234 	ifp->if_watchdog = ilwatch;
235 	is->is_scaninterval = ILWATCHINTERVAL;
236 	ifp->if_timer = is->is_scaninterval;
237 	addr = (struct ildevice *)ui->ui_addr;
238 
239 	/*
240 	 * Turn off source address insertion (it's faster this way),
241 	 * and set board online.  Former doesn't work if board is
242 	 * already online (happens on ubareset), so we put it offline
243 	 * first.
244 	 */
245 	s = splimp();
246 	addr->il_csr = ILC_RESET;
247 	if (ilwait(ui, "hardware diag")) {
248  		is->is_if.if_flags &= ~IFF_UP;
249  		splx(s);
250  		return;
251  	}
252 	addr->il_csr = ILC_CISA;
253 	while ((addr->il_csr & IL_CDONE) == 0)
254 		;
255 	/*
256 	 * If we must reprogram this board's physical ethernet
257 	 * address (as for secondary XNS interfaces), we do so
258 	 * before putting it on line, and starting receive requests.
259 	 * If you try this on an older 1010 board, it will total
260 	 * wedge the board.
261 	 */
262 	if (is->is_flags & ILF_SETADDR) {
263 		bcopy((caddr_t)is->is_addr, (caddr_t)&is->is_stats,
264 							sizeof is->is_addr);
265 		addr->il_bar = is->is_ubaddr & 0xffff;
266 		addr->il_bcr = sizeof is->is_addr;
267 		addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_LDPA;
268 		if (ilwait(ui, "setaddr"))
269 			return;
270 		addr->il_bar = is->is_ubaddr & 0xffff;
271 		addr->il_bcr = sizeof (struct il_stats);
272 		addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT;
273 		if (ilwait(ui, "verifying setaddr"))
274 			return;
275 		if (bcmp((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr,
276 						sizeof (is->is_addr)) != 0) {
277 			printf("il%d: setaddr didn't work\n", ui->ui_unit);
278 			return;
279 		}
280 	}
281 	/*
282 	 * Set board online.
283 	 * Hang receive buffer and start any pending
284 	 * writes by faking a transmit complete.
285 	 * Receive bcr is not a multiple of 8 so buffer
286 	 * chaining can't happen.
287 	 */
288 	addr->il_csr = ILC_ONLINE;
289 	while ((addr->il_csr & IL_CDONE) == 0)
290 		;
291 	addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff;
292 	addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6;
293 	addr->il_csr =
294 	    ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE;
295 	while ((addr->il_csr & IL_CDONE) == 0)
296 		;
297 	is->is_flags = ILF_OACTIVE;
298 	is->is_if.if_flags |= IFF_RUNNING;
299 	is->is_flags |= ILF_RUNNING;
300 	is->is_lastcmd = 0;
301 	ilcint(unit);
302 	splx(s);
303 }
304 
305 /*
306  * Start output on interface.
307  * Get another datagram to send off of the interface queue,
308  * and map it to the interface before starting the output.
309  */
310 ilstart(dev)
311 	dev_t dev;
312 {
313         int unit = ILUNIT(dev), len;
314 	struct uba_device *ui = ilinfo[unit];
315 	register struct il_softc *is = &il_softc[unit];
316 	register struct ildevice *addr;
317 	struct mbuf *m;
318 	short csr;
319 
320 	IF_DEQUEUE(&is->is_if.if_snd, m);
321 	addr = (struct ildevice *)ui->ui_addr;
322 	if (m == 0) {
323 		if ((is->is_flags & ILF_STATPENDING) == 0)
324 			return;
325 		addr->il_bar = is->is_ubaddr & 0xffff;
326 		addr->il_bcr = sizeof (struct il_stats);
327 		csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT|IL_RIE|IL_CIE;
328 		is->is_flags &= ~ILF_STATPENDING;
329 		goto startcmd;
330 	}
331 	len = if_wubaput(&is->is_ifuba, m);
332 	/*
333 	 * Ensure minimum packet length.
334 	 * This makes the safe assumtion that there are no virtual holes
335 	 * after the data.
336 	 * For security, it might be wise to zero out the added bytes,
337 	 * but we're mainly interested in speed at the moment.
338 	 */
339 	if (len - sizeof(struct ether_header) < ETHERMIN)
340 		len = ETHERMIN + sizeof(struct ether_header);
341 	if (is->is_ifuba.ifu_flags & UBA_NEEDBDP)
342 		UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_w.ifrw_bdp);
343 	addr->il_bar = is->is_ifuba.ifu_w.ifrw_info & 0xffff;
344 	addr->il_bcr = len;
345 	csr =
346 	  ((is->is_ifuba.ifu_w.ifrw_info >> 2) & IL_EUA)|ILC_XMIT|IL_CIE|IL_RIE;
347 
348 startcmd:
349 	is->is_lastcmd = csr & IL_CMD;
350 	addr->il_csr = csr;
351 	is->is_flags |= ILF_OACTIVE;
352 }
353 
354 /*
355  * Command done interrupt.
356  */
357 ilcint(unit)
358 	int unit;
359 {
360 	register struct il_softc *is = &il_softc[unit];
361 	struct uba_device *ui = ilinfo[unit];
362 	register struct ildevice *addr = (struct ildevice *)ui->ui_addr;
363 	short csr;
364 
365 	if ((is->is_flags & ILF_OACTIVE) == 0) {
366 		printf("il%d: stray xmit interrupt, csr=%b\n", unit,
367 			addr->il_csr, IL_BITS);
368 		return;
369 	}
370 
371 	csr = addr->il_csr;
372 	/*
373 	 * Hang receive buffer if it couldn't
374 	 * be done earlier (in ilrint).
375 	 */
376 	if (is->is_flags & ILF_RCVPENDING) {
377 		int s;
378 
379 		addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff;
380 		addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6;
381 		addr->il_csr =
382 		  ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE;
383 		s = splhigh();
384 		while ((addr->il_csr & IL_CDONE) == 0)
385 			;
386 		splx(s);
387 		is->is_flags &= ~ILF_RCVPENDING;
388 	}
389 	is->is_flags &= ~ILF_OACTIVE;
390 	csr &= IL_STATUS;
391 	switch (is->is_lastcmd) {
392 
393 	case ILC_XMIT:
394 		is->is_if.if_opackets++;
395 		if (csr > ILERR_RETRIES)
396 			is->is_if.if_oerrors++;
397 		break;
398 
399 	case ILC_STAT:
400 		if (csr == ILERR_SUCCESS)
401 			iltotal(is);
402 		break;
403 	}
404 	if (is->is_ifuba.ifu_xtofree) {
405 		m_freem(is->is_ifuba.ifu_xtofree);
406 		is->is_ifuba.ifu_xtofree = 0;
407 	}
408 	ilstart(unit);
409 }
410 
411 /*
412  * Ethernet interface receiver interrupt.
413  * If input error just drop packet.
414  * Otherwise purge input buffered data path and examine
415  * packet to determine type.  If can't determine length
416  * from type, then have to drop packet.  Othewise decapsulate
417  * packet based on type and pass to type specific higher-level
418  * input routine.
419  */
420 ilrint(unit)
421 	int unit;
422 {
423 	register struct il_softc *is = &il_softc[unit];
424 	struct ildevice *addr = (struct ildevice *)ilinfo[unit]->ui_addr;
425 	register struct il_rheader *il;
426     	struct mbuf *m;
427 	int len, off, resid, s;
428 	register struct ifqueue *inq;
429 
430 	is->is_if.if_ipackets++;
431 	if (is->is_ifuba.ifu_flags & UBA_NEEDBDP)
432 		UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_r.ifrw_bdp);
433 	il = (struct il_rheader *)(is->is_ifuba.ifu_r.ifrw_addr);
434 	len = il->ilr_length - sizeof(struct il_rheader);
435 	if ((il->ilr_status&(ILFSTAT_A|ILFSTAT_C)) || len < 46 ||
436 	    len > ETHERMTU) {
437 		is->is_if.if_ierrors++;
438 #ifdef notdef
439 		if (is->is_if.if_ierrors % 100 == 0)
440 			printf("il%d: += 100 input errors\n", unit);
441 #endif
442 		goto setup;
443 	}
444 
445 	/*
446 	 * Deal with trailer protocol: if type is trailer type
447 	 * get true type from first 16-bit word past data.
448 	 * Remember that type was trailer by setting off.
449 	 */
450 	il->ilr_type = ntohs((u_short)il->ilr_type);
451 #define	ildataaddr(il, off, type)	((type)(((caddr_t)((il)+1)+(off))))
452 	if (il->ilr_type >= ETHERTYPE_TRAIL &&
453 	    il->ilr_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
454 		off = (il->ilr_type - ETHERTYPE_TRAIL) * 512;
455 		if (off >= ETHERMTU)
456 			goto setup;		/* sanity */
457 		il->ilr_type = ntohs(*ildataaddr(il, off, u_short *));
458 		resid = ntohs(*(ildataaddr(il, off+2, u_short *)));
459 		if (off + resid > len)
460 			goto setup;		/* sanity */
461 		len = off + resid;
462 	} else
463 		off = 0;
464 	if (len == 0)
465 		goto setup;
466 
467 	/*
468 	 * Pull packet off interface.  Off is nonzero if packet
469 	 * has trailing header; ilget will then force this header
470 	 * information to be at the front, but we still have to drop
471 	 * the type and length which are at the front of any trailer data.
472 	 */
473 	m = if_rubaget(&is->is_ifuba, len, off, &is->is_if);
474 	if (m == 0)
475 		goto setup;
476 	if (off) {
477 		struct ifnet *ifp;
478 
479 		ifp = *(mtod(m, struct ifnet **));
480 		m->m_off += 2 * sizeof (u_short);
481 		m->m_len -= 2 * sizeof (u_short);
482 		*(mtod(m, struct ifnet **)) = ifp;
483 	}
484 	switch (il->ilr_type) {
485 
486 #ifdef INET
487 	case ETHERTYPE_IP:
488 		schednetisr(NETISR_IP);
489 		inq = &ipintrq;
490 		break;
491 
492 	case ETHERTYPE_ARP:
493 		arpinput(&is->is_ac, m);
494 		goto setup;
495 #endif
496 #ifdef NS
497 	case ETHERTYPE_NS:
498 		schednetisr(NETISR_NS);
499 		inq = &nsintrq;
500 		break;
501 
502 #endif
503 	default:
504 		m_freem(m);
505 		goto setup;
506 	}
507 
508 	s = splimp();
509 	if (IF_QFULL(inq)) {
510 		IF_DROP(inq);
511 		m_freem(m);
512 	} else
513 		IF_ENQUEUE(inq, m);
514 	splx(s);
515 
516 setup:
517 	/*
518 	 * Reset for next packet if possible.
519 	 * If waiting for transmit command completion, set flag
520 	 * and wait until command completes.
521 	 */
522 	if (is->is_flags & ILF_OACTIVE) {
523 		is->is_flags |= ILF_RCVPENDING;
524 		return;
525 	}
526 	addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff;
527 	addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6;
528 	addr->il_csr =
529 		((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE;
530 	s = splhigh();
531 	while ((addr->il_csr & IL_CDONE) == 0)
532 		;
533 	splx(s);
534 }
535 
536 /*
537  * Ethernet output routine.
538  * Encapsulate a packet of type family for the local net.
539  * Use trailer local net encapsulation if enough data in first
540  * packet leaves a multiple of 512 bytes of data in remainder.
541  */
542 iloutput(ifp, m0, dst)
543 	struct ifnet *ifp;
544 	struct mbuf *m0;
545 	struct sockaddr *dst;
546 {
547 	int type, s, error;
548  	u_char edst[6];
549 	struct in_addr idst;
550 	register struct il_softc *is = &il_softc[ifp->if_unit];
551 	register struct mbuf *m = m0;
552 	register struct ether_header *il;
553 	register int off;
554 	int usetrailers;
555 
556 	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
557 		error = ENETDOWN;
558 		goto bad;
559 	}
560 	switch (dst->sa_family) {
561 
562 #ifdef INET
563 	case AF_INET:
564 		idst = ((struct sockaddr_in *)dst)->sin_addr;
565  		if (!arpresolve(&is->is_ac, m, &idst, edst, &usetrailers))
566 			return (0);	/* if not yet resolved */
567 		off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
568 		if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
569 		    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
570 			type = ETHERTYPE_TRAIL + (off>>9);
571 			m->m_off -= 2 * sizeof (u_short);
572 			m->m_len += 2 * sizeof (u_short);
573 			*mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
574 			*(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
575 			goto gottrailertype;
576 		}
577 		type = ETHERTYPE_IP;
578 		off = 0;
579 		goto gottype;
580 #endif
581 #ifdef NS
582 	case AF_NS:
583 		type = ETHERTYPE_NS;
584  		bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
585 		(caddr_t)edst, sizeof (edst));
586 		off = 0;
587 		goto gottype;
588 #endif
589 
590 	case AF_UNSPEC:
591 		il = (struct ether_header *)dst->sa_data;
592  		bcopy((caddr_t)il->ether_dhost, (caddr_t)edst, sizeof (edst));
593 		type = il->ether_type;
594 		goto gottype;
595 
596 	default:
597 		printf("il%d: can't handle af%d\n", ifp->if_unit,
598 			dst->sa_family);
599 		error = EAFNOSUPPORT;
600 		goto bad;
601 	}
602 
603 gottrailertype:
604 	/*
605 	 * Packet to be sent as trailer: move first packet
606 	 * (control information) to end of chain.
607 	 */
608 	while (m->m_next)
609 		m = m->m_next;
610 	m->m_next = m0;
611 	m = m0->m_next;
612 	m0->m_next = 0;
613 	m0 = m;
614 
615 gottype:
616 	/*
617 	 * Add local net header.  If no space in first mbuf,
618 	 * allocate another.
619 	 */
620 	if (m->m_off > MMAXOFF ||
621 	    MMINOFF + sizeof (struct ether_header) > m->m_off) {
622 		m = m_get(M_DONTWAIT, MT_HEADER);
623 		if (m == 0) {
624 			error = ENOBUFS;
625 			goto bad;
626 		}
627 		m->m_next = m0;
628 		m->m_off = MMINOFF;
629 		m->m_len = sizeof (struct ether_header);
630 	} else {
631 		m->m_off -= sizeof (struct ether_header);
632 		m->m_len += sizeof (struct ether_header);
633 	}
634 	il = mtod(m, struct ether_header *);
635 	il->ether_type = htons((u_short)type);
636  	bcopy((caddr_t)edst, (caddr_t)il->ether_dhost, sizeof (edst));
637  	bcopy((caddr_t)is->is_addr, (caddr_t)il->ether_shost,
638 	    sizeof(il->ether_shost));
639 
640 	/*
641 	 * Queue message on interface, and start output if interface
642 	 * not yet active.
643 	 */
644 	s = splimp();
645 	if (IF_QFULL(&ifp->if_snd)) {
646 		IF_DROP(&ifp->if_snd);
647 		splx(s);
648 		m_freem(m);
649 		return (ENOBUFS);
650 	}
651 	IF_ENQUEUE(&ifp->if_snd, m);
652 	if ((is->is_flags & ILF_OACTIVE) == 0)
653 		ilstart(ifp->if_unit);
654 	splx(s);
655 	return (0);
656 
657 bad:
658 	m_freem(m0);
659 	return (error);
660 }
661 
662 /*
663  * Watchdog routine, request statistics from board.
664  */
665 ilwatch(unit)
666 	int unit;
667 {
668 	register struct il_softc *is = &il_softc[unit];
669 	register struct ifnet *ifp = &is->is_if;
670 	int s;
671 
672 	if (is->is_flags & ILF_STATPENDING) {
673 		ifp->if_timer = is->is_scaninterval;
674 		return;
675 	}
676 	s = splimp();
677 	is->is_flags |= ILF_STATPENDING;
678 	if ((is->is_flags & ILF_OACTIVE) == 0)
679 		ilstart(ifp->if_unit);
680 	splx(s);
681 	ifp->if_timer = is->is_scaninterval;
682 }
683 
684 /*
685  * Total up the on-board statistics.
686  */
687 iltotal(is)
688 	register struct il_softc *is;
689 {
690 	register u_short *interval, *sum, *end;
691 
692 	interval = &is->is_stats.ils_frames;
693 	sum = &is->is_sum.ils_frames;
694 	end = is->is_sum.ils_fill2;
695 	while (sum < end)
696 		*sum++ += *interval++;
697 	is->is_if.if_collisions = is->is_sum.ils_collis;
698 	if ((is->is_flags & ILF_SETADDR) &&
699 	    (bcmp((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr,
700 					sizeof (is->is_addr)) != 0)) {
701 		log(LOG_ERR, "il%d: physaddr reverted\n", is->is_if.if_unit);
702 		is->is_flags &= ~ILF_RUNNING;
703 		ilinit(is->is_if.if_unit);
704 	}
705 }
706 
707 /*
708  * Process an ioctl request.
709  */
710 ilioctl(ifp, cmd, data)
711 	register struct ifnet *ifp;
712 	int cmd;
713 	caddr_t data;
714 {
715 	register struct ifaddr *ifa = (struct ifaddr *)data;
716 	register struct il_softc *is = &il_softc[ifp->if_unit];
717 	int s = splimp(), error = 0;
718 
719 	switch (cmd) {
720 
721 	case SIOCSIFADDR:
722 		ifp->if_flags |= IFF_UP;
723 		ilinit(ifp->if_unit);
724 
725 		switch (ifa->ifa_addr.sa_family) {
726 #ifdef INET
727 		case AF_INET:
728 			((struct arpcom *)ifp)->ac_ipaddr =
729 				IA_SIN(ifa)->sin_addr;
730 			arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
731 			break;
732 #endif
733 #ifdef NS
734 		case AF_NS:
735 		    {
736 			register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
737 
738 			if (ns_nullhost(*ina)) {
739 				ina->x_host = * (union ns_host *)
740 				     (il_softc[ifp->if_unit].is_addr);
741 			} else {
742 				il_setaddr(ina->x_host.c_host, ifp->if_unit);
743 				return (0);
744 			}
745 			break;
746 		    }
747 #endif
748 		}
749 		break;
750 
751 	case SIOCSIFFLAGS:
752 		if ((ifp->if_flags & IFF_UP) == 0 &&
753 		    is->is_flags & ILF_RUNNING) {
754 			((struct ildevice *)
755 			   (ilinfo[ifp->if_unit]->ui_addr))->il_csr = ILC_RESET;
756 			is->is_flags &= ~ILF_RUNNING;
757 		} else if (ifp->if_flags & IFF_UP &&
758 		    (is->is_flags & ILF_RUNNING) == 0)
759 			ilinit(ifp->if_unit);
760 		break;
761 
762 	default:
763 		error = EINVAL;
764 	}
765 	splx(s);
766 	return (error);
767 }
768 
769 /*
770  * set ethernet address for unit
771  */
772 il_setaddr(physaddr, unit)
773 u_char *physaddr;
774 int unit;
775 {
776 	register struct il_softc *is = &il_softc[unit];
777 
778 	if (! (is->is_flags & ILF_RUNNING))
779 		return;
780 
781 	bcopy((caddr_t)physaddr, (caddr_t)is->is_addr, sizeof is->is_addr);
782 	is->is_flags &= ~ILF_RUNNING;
783 	is->is_flags |= ILF_SETADDR;
784 	ilinit(unit);
785 }
786 #endif
787