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