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