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