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