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