X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/67eb627727b973c57bb8262be2310f22e2919e61..refs/tags/BSD-4_3_Net_2:/usr/src/sys/vax/if/if_il.c diff --git a/usr/src/sys/vax/if/if_il.c b/usr/src/sys/vax/if/if_il.c index f63f54ffaf..13b5d34b5f 100644 --- a/usr/src/sys/vax/if/if_il.c +++ b/usr/src/sys/vax/if/if_il.c @@ -1,59 +1,81 @@ /* - * Copyright (c) 1982 Regents of the University of California. - * All rights reserved. The Berkeley software License Agreement - * specifies the terms and conditions for redistribution. + * Copyright (c) 1982, 1986 Regents of the University of California. + * All rights reserved. * - * @(#)if_il.c 6.9 (Berkeley) %G% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_il.c 7.8 (Berkeley) 12/16/90 */ #include "il.h" +#if NIL > 0 /* * Interlan Ethernet Communications Controller interface */ -#include "../machine/pte.h" - -#include "param.h" -#include "systm.h" -#include "mbuf.h" -#include "buf.h" -#include "protosw.h" -#include "socket.h" -#include "vmmac.h" -#include "ioctl.h" -#include "errno.h" - -#include "../net/if.h" -#include "../net/netisr.h" -#include "../net/route.h" - -#ifdef BBNNET -#define INET -#endif -#ifdef INET -#include "../netinet/in.h" -#include "../netinet/in_systm.h" -#include "../netinet/in_var.h" -#include "../netinet/ip.h" -#include "../netinet/if_ether.h" -#endif +#include "../include/pte.h" + +#include "sys/param.h" +#include "sys/systm.h" +#include "sys/mbuf.h" +#include "sys/buf.h" +#include "sys/protosw.h" +#include "sys/socket.h" +#include "sys/vmmac.h" +#include "sys/ioctl.h" +#include "sys/errno.h" +#include "sys/syslog.h" + +#include "net/if.h" +#include "net/netisr.h" +#include "net/route.h" -#ifdef PUP -#include "../netpup/pup.h" +#ifdef INET +#include "netinet/in.h" +#include "netinet/in_systm.h" +#include "netinet/in_var.h" +#include "netinet/ip.h" +#include "netinet/if_ether.h" #endif #ifdef NS -#include "../netns/ns.h" -#include "../netns/ns_if.h" +#include "netns/ns.h" +#include "netns/ns_if.h" #endif -#include "../vax/cpu.h" -#include "../vax/mtpr.h" +#include "../include/cpu.h" +#include "../include/mtpr.h" #include "if_il.h" #include "if_ilreg.h" #include "if_uba.h" -#include "../vaxuba/ubareg.h" -#include "../vaxuba/ubavar.h" +#include "../uba/ubareg.h" +#include "../uba/ubavar.h" int ilprobe(), ilattach(), ilrint(), ilcint(); struct uba_device *ilinfo[NIL]; @@ -61,7 +83,8 @@ u_short ilstd[] = { 0 }; struct uba_driver ildriver = { ilprobe, 0, ilattach, 0, ilstd, "il", ilinfo }; #define ILUNIT(x) minor(x) -int ilinit(),iloutput(),ilioctl(),ilreset(),ilwatch(); +int ilinit(),iloutput(),ilioctl(),ilreset(),ilwatch(),ilstart(); +int ildebug = 0; /* * Ethernet software status per interface. @@ -75,19 +98,29 @@ int ilinit(),iloutput(),ilioctl(),ilreset(),ilwatch(); * structure for use by the if_uba.c routines in running the interface * efficiently. */ + +struct ether_addr { + u_char addr[6]; +}; struct il_softc { struct arpcom is_ac; /* Ethernet common part */ #define is_if is_ac.ac_if /* network-visible interface */ #define is_addr is_ac.ac_enaddr /* hardware Ethernet address */ struct ifuba is_ifuba; /* UNIBUS resources */ int is_flags; -#define ILF_OACTIVE 0x1 /* output is active */ #define ILF_RCVPENDING 0x2 /* start rcv in ilcint */ #define ILF_STATPENDING 0x4 /* stat cmd pending */ +#define ILF_RUNNING 0x8 /* board is running */ +#define ILF_SETADDR 0x10 /* physical address is changed */ short is_lastcmd; /* can't read csr, so must save it */ short is_scaninterval; /* interval of stat collection */ #define ILWATCHINTERVAL 60 /* once every 60 seconds */ - struct il_stats is_stats; /* holds on-board statistics */ + union { + struct il_stats isu_stats; /* holds on-board statistics */ + struct ether_addr isu_maddrs[63]; /* multicast addrs */ + } is_isu; +#define is_stats is_isu.isu_stats +#define is_maddrs is_isu.isu_maddrs struct il_stats is_sum; /* summation over time */ int is_ubaddr; /* mapping registers of is_stats */ } il_softc[NIL]; @@ -135,44 +168,47 @@ ilattach(ui) * buffer onto the Unibus. */ addr->il_csr = ILC_RESET; - while ((addr->il_csr&IL_CDONE) == 0) - ; - if (addr->il_csr&IL_STATUS) - printf("il%d: reset failed, csr=%b\n", ui->ui_unit, - addr->il_csr, IL_BITS); + (void)ilwait(ui, "reset"); is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_stats, sizeof (struct il_stats), 0); addr->il_bar = is->is_ubaddr & 0xffff; addr->il_bcr = sizeof (struct il_stats); addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT; - while ((addr->il_csr&IL_CDONE) == 0) - ; - if (addr->il_csr&IL_STATUS) - printf("il%d: status failed, csr=%b\n", ui->ui_unit, - addr->il_csr, IL_BITS); + (void)ilwait(ui, "status"); ubarelse(ui->ui_ubanum, &is->is_ubaddr); -#ifdef notdef - printf("il%d: addr=%x:%x:%x:%x:%x:%x module=%s firmware=%s\n", - ui->ui_unit, - is->is_stats.ils_addr[0]&0xff, is->is_stats.ils_addr[1]&0xff, - is->is_stats.ils_addr[2]&0xff, is->is_stats.ils_addr[3]&0xff, - is->is_stats.ils_addr[4]&0xff, is->is_stats.ils_addr[5]&0xff, - is->is_stats.ils_module, is->is_stats.ils_firmware); -#endif + if (ildebug) + printf("il%d: module=%s firmware=%s\n", ui->ui_unit, + is->is_stats.ils_module, is->is_stats.ils_firmware); bcopy((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr, sizeof (is->is_addr)); + printf("il%d: hardware address %s\n", ui->ui_unit, + ether_sprintf(is->is_addr)); ifp->if_init = ilinit; - ifp->if_output = iloutput; + ifp->if_output = ether_output; ifp->if_ioctl = ilioctl; ifp->if_reset = ilreset; + ifp->if_start = ilstart; is->is_ifuba.ifu_flags = UBA_CANTWAIT; -#ifdef notdef - is->is_ifuba.ifu_flags |= UBA_NEEDBDP; -#endif if_attach(ifp); } +ilwait(ui, op) + struct uba_device *ui; + char *op; +{ + register struct ildevice *addr = (struct ildevice *)ui->ui_addr; + + while ((addr->il_csr&IL_CDONE) == 0) + ; + if (addr->il_csr&IL_STATUS) { + printf("il%d: %s failed, csr=%b\n", ui->ui_unit, op, + addr->il_csr, IL_BITS); + return (-1); + } + return (0); +} + /* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. @@ -186,6 +222,8 @@ ilreset(unit, uban) ui->ui_ubanum != uban) return; printf(" il%d", unit); + il_softc[unit].is_if.if_flags &= ~IFF_RUNNING; + il_softc[unit].is_flags &= ~ILF_RUNNING; ilinit(unit); } @@ -205,17 +243,19 @@ ilinit(unit) /* not yet, if address still unknown */ if (ifp->if_addrlist == (struct ifaddr *)0) return; - - if (ifp->if_flags & IFF_RUNNING) - return; - if (if_ubainit(&is->is_ifuba, ui->ui_ubanum, - sizeof (struct il_rheader), (int)btoc(ETHERMTU)) == 0) { - printf("il%d: can't initialize\n", unit); - is->is_if.if_flags &= ~IFF_UP; + if (is->is_flags & ILF_RUNNING) return; + + if ((ifp->if_flags & IFF_RUNNING) == 0) { + if (if_ubainit(&is->is_ifuba, ui->ui_ubanum, + sizeof (struct il_rheader), (int)btoc(ETHERMTU)) == 0) { + printf("il%d: can't initialize\n", unit); + is->is_if.if_flags &= ~IFF_UP; + return; + } + is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_isu, + sizeof (is->is_isu), 0); } - is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_stats, - sizeof (struct il_stats), 0); ifp->if_watchdog = ilwatch; is->is_scaninterval = ILWATCHINTERVAL; ifp->if_timer = is->is_scaninterval; @@ -228,17 +268,91 @@ ilinit(unit) * first. */ s = splimp(); - addr->il_csr = ILC_OFFLINE; - while ((addr->il_csr & IL_CDONE) == 0) - ; + addr->il_csr = ILC_RESET; + if (ilwait(ui, "hardware diag")) { + is->is_if.if_flags &= ~IFF_UP; + splx(s); + return; + } addr->il_csr = ILC_CISA; while ((addr->il_csr & IL_CDONE) == 0) ; + /* + * If we must reprogram this board's physical ethernet + * address (as for secondary XNS interfaces), we do so + * before putting it on line, and starting receive requests. + * If you try this on an older 1010 board, it will total + * wedge the board. + */ + if (is->is_flags & ILF_SETADDR) { + bcopy((caddr_t)is->is_addr, (caddr_t)&is->is_isu, + sizeof is->is_addr); + addr->il_bar = is->is_ubaddr & 0xffff; + addr->il_bcr = sizeof is->is_addr; + addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_LDPA; + if (ilwait(ui, "setaddr")) + return; + addr->il_bar = is->is_ubaddr & 0xffff; + addr->il_bcr = sizeof (struct il_stats); + addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT; + if (ilwait(ui, "verifying setaddr")) + return; + if (bcmp((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr, + sizeof (is->is_addr)) != 0) { + printf("il%d: setaddr didn't work\n", ui->ui_unit); + return; + } + } +#ifdef MULTICAST + if (is->is_if.if_flags & IFF_PROMISC) { + addr->il_csr = ILC_PRMSC; + if (ilwait(ui, "all multi")) + return; + } else if (is->is_if.if_flags & IFF_ALLMULTI) { + too_many_multis: + addr->il_csr = ILC_ALLMC; + if (ilwait(ui, "all multi")) + return; + else { + int i; + register struct ether_addr *ep = is->is_maddrs; + struct ether_multi *enm; + struct ether_multistep step; + /* + * Step through our list of multicast addresses. If we have + * too many multicast addresses, or if we have to listen to + * a range of multicast addresses, turn on reception of all + * multicasts. + */ + i = 0; + ETHER_FIRST_MULTI(step, &is->is_ac, enm); + while (enm != NULL) { + if (++i > 63 && k != 0) { + break; + } + *ep++ = *(struct ether_addr *)enm->enm_addrlo; + ETHER_NEXT_MULTI(step, enm); + } + if (i = 0) { + /* no multicasts! */ + } else if (i <= 63) { + addr->il_bar = is->is_ubaddr & 0xffff; + addr->il_bcr = i * sizeof (struct ether_addr); + addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)| + LC_LDGRPS; + if (ilwait(ui, "load multi")) + return; + } else { + is->is_if.if_flags |= IFF_ALLMULTI; + goto too_many_multis; + } + } +#endif MULTI /* * Set board online. * Hang receive buffer and start any pending * writes by faking a transmit complete. - * Receive bcr is not a muliple of 4 so buffer + * Receive bcr is not a multiple of 8 so buffer * chaining can't happen. */ addr->il_csr = ILC_ONLINE; @@ -250,8 +364,8 @@ ilinit(unit) ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE; while ((addr->il_csr & IL_CDONE) == 0) ; - is->is_flags = ILF_OACTIVE; - is->is_if.if_flags |= IFF_RUNNING; + is->is_if.if_flags |= IFF_RUNNING | IFF_OACTIVE; + is->is_flags |= ILF_RUNNING; is->is_lastcmd = 0; ilcint(unit); splx(s); @@ -262,10 +376,10 @@ ilinit(unit) * Get another datagram to send off of the interface queue, * and map it to the interface before starting the output. */ -ilstart(dev) - dev_t dev; +ilstart(ifp) + register struct ifnet *ifp; { - int unit = ILUNIT(dev), len; + int unit = ifp->if_unit, len; struct uba_device *ui = ilinfo[unit]; register struct il_softc *is = &il_softc[unit]; register struct ildevice *addr; @@ -276,7 +390,7 @@ ilstart(dev) addr = (struct ildevice *)ui->ui_addr; if (m == 0) { if ((is->is_flags & ILF_STATPENDING) == 0) - return; + return (0); addr->il_bar = is->is_ubaddr & 0xffff; addr->il_bcr = sizeof (struct il_stats); csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT|IL_RIE|IL_CIE; @@ -303,7 +417,8 @@ ilstart(dev) startcmd: is->is_lastcmd = csr & IL_CMD; addr->il_csr = csr; - is->is_flags |= ILF_OACTIVE; + is->is_if.if_flags |= IFF_OACTIVE; + return (0); } /* @@ -317,7 +432,7 @@ ilcint(unit) register struct ildevice *addr = (struct ildevice *)ui->ui_addr; short csr; - if ((is->is_flags & ILF_OACTIVE) == 0) { + if ((is->is_if.if_flags & IFF_OACTIVE) == 0) { printf("il%d: stray xmit interrupt, csr=%b\n", unit, addr->il_csr, IL_BITS); return; @@ -329,15 +444,19 @@ ilcint(unit) * be done earlier (in ilrint). */ if (is->is_flags & ILF_RCVPENDING) { + int s; + addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff; addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6; addr->il_csr = ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE; + s = splhigh(); while ((addr->il_csr & IL_CDONE) == 0) ; + splx(s); is->is_flags &= ~ILF_RCVPENDING; } - is->is_flags &= ~ILF_OACTIVE; + is->is_if.if_flags &= ~IFF_OACTIVE; csr &= IL_STATUS; switch (is->is_lastcmd) { @@ -356,7 +475,7 @@ ilcint(unit) m_freem(is->is_ifuba.ifu_xtofree); is->is_ifuba.ifu_xtofree = 0; } - ilstart(unit); + (void) ilstart(&is->is_if); } /* @@ -422,55 +541,15 @@ ilrint(unit) * the type and length which are at the front of any trailer data. */ m = if_rubaget(&is->is_ifuba, len, off, &is->is_if); - if (m == 0) - goto setup; - if (off) { - struct ifnet *ifp; - - ifp = *(mtod(m, struct ifnet **)); - m->m_off += 2 * sizeof (u_short); - m->m_len -= 2 * sizeof (u_short); - *(mtod(m, struct ifnet **)) = ifp; - } - switch (il->ilr_type) { - -#ifdef INET - case ETHERTYPE_IP: - schednetisr(NETISR_IP); - inq = &ipintrq; - break; - - case ETHERTYPE_ARP: - arpinput(&is->is_ac, m); - goto setup; -#endif -#ifdef NS - case ETHERTYPE_NS: - schednetisr(NETISR_NS); - inq = &nsintrq; - break; - -#endif - default: - m_freem(m); - goto setup; - } - - s = splimp(); - if (IF_QFULL(inq)) { - IF_DROP(inq); - m_freem(m); - } else - IF_ENQUEUE(inq, m); - splx(s); - + if (m) + ether_input(&is->is_if, (struct ether_header *)il->ilr_dhost, m); setup: /* * Reset for next packet if possible. * If waiting for transmit command completion, set flag * and wait until command completes. */ - if (is->is_flags & ILF_OACTIVE) { + if (is->is_if.if_flags & IFF_OACTIVE) { is->is_flags |= ILF_RCVPENDING; return; } @@ -478,133 +557,11 @@ setup: addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6; addr->il_csr = ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE; + s = splhigh(); while ((addr->il_csr & IL_CDONE) == 0) ; -} - -/* - * Ethernet output routine. - * Encapsulate a packet of type family for the local net. - * Use trailer local net encapsulation if enough data in first - * packet leaves a multiple of 512 bytes of data in remainder. - */ -iloutput(ifp, m0, dst) - struct ifnet *ifp; - struct mbuf *m0; - struct sockaddr *dst; -{ - int type, s, error; - u_char edst[6]; - struct in_addr idst; - register struct il_softc *is = &il_softc[ifp->if_unit]; - register struct mbuf *m = m0; - register struct ether_header *il; - register int off; - - switch (dst->sa_family) { - -#ifdef INET - case AF_INET: - idst = ((struct sockaddr_in *)dst)->sin_addr; - if (!arpresolve(&is->is_ac, m, &idst, edst)) - return (0); /* if not yet resolved */ - off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; - /* need per host negotiation */ - if ((ifp->if_flags & IFF_NOTRAILERS) == 0) - if (off > 0 && (off & 0x1ff) == 0 && - m->m_off >= MMINOFF + 2 * sizeof (u_short)) { - type = ETHERTYPE_TRAIL + (off>>9); - m->m_off -= 2 * sizeof (u_short); - m->m_len += 2 * sizeof (u_short); - *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); - *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); - goto gottrailertype; - } - type = ETHERTYPE_IP; - off = 0; - goto gottype; -#endif -#ifdef NS - case AF_NS: - type = ETHERTYPE_NS; - bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), - (caddr_t)edst, sizeof (edst)); - off = 0; - goto gottype; -#endif - - case AF_UNSPEC: - il = (struct ether_header *)dst->sa_data; - bcopy((caddr_t)il->ether_dhost, (caddr_t)edst, sizeof (edst)); - type = il->ether_type; - goto gottype; - - default: - printf("il%d: can't handle af%d\n", ifp->if_unit, - dst->sa_family); - error = EAFNOSUPPORT; - goto bad; - } - -gottrailertype: - /* - * Packet to be sent as trailer: move first packet - * (control information) to end of chain. - */ - while (m->m_next) - m = m->m_next; - m->m_next = m0; - m = m0->m_next; - m0->m_next = 0; - m0 = m; - -gottype: - /* - * Add local net header. If no space in first mbuf, - * allocate another. - */ - if (m->m_off > MMAXOFF || - MMINOFF + sizeof (struct ether_header) > m->m_off) { - m = m_get(M_DONTWAIT, MT_HEADER); - if (m == 0) { - error = ENOBUFS; - goto bad; - } - m->m_next = m0; - m->m_off = MMINOFF; - m->m_len = sizeof (struct ether_header); - } else { - m->m_off -= sizeof (struct ether_header); - m->m_len += sizeof (struct ether_header); - } - il = mtod(m, struct ether_header *); - il->ether_type = htons((u_short)type); - bcopy((caddr_t)edst, (caddr_t)il->ether_dhost, sizeof (edst)); - bcopy((caddr_t)is->is_addr, (caddr_t)il->ether_shost, - sizeof(il->ether_shost)); - - /* - * Queue message on interface, and start output if interface - * not yet active. - */ - s = splimp(); - if (IF_QFULL(&ifp->if_snd)) { - IF_DROP(&ifp->if_snd); - splx(s); - m_freem(m); - return (ENOBUFS); - } - IF_ENQUEUE(&ifp->if_snd, m); - if ((is->is_flags & ILF_OACTIVE) == 0) - ilstart(ifp->if_unit); splx(s); - return (0); - -bad: - m_freem(m0); - return (error); } - /* * Watchdog routine, request statistics from board. */ @@ -621,8 +578,8 @@ ilwatch(unit) } s = splimp(); is->is_flags |= ILF_STATPENDING; - if ((is->is_flags & ILF_OACTIVE) == 0) - ilstart(ifp->if_unit); + if ((is->is_if.if_flags & IFF_OACTIVE) == 0) + (void) ilstart(ifp); splx(s); ifp->if_timer = is->is_scaninterval; } @@ -641,6 +598,13 @@ iltotal(is) while (sum < end) *sum++ += *interval++; is->is_if.if_collisions = is->is_sum.ils_collis; + if ((is->is_flags & ILF_SETADDR) && + (bcmp((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr, + sizeof (is->is_addr)) != 0)) { + log(LOG_ERR, "il%d: physaddr reverted\n", is->is_if.if_unit); + is->is_flags &= ~ILF_RUNNING; + ilinit(is->is_if.if_unit); + } } /* @@ -652,6 +616,7 @@ ilioctl(ifp, cmd, data) caddr_t data; { register struct ifaddr *ifa = (struct ifaddr *)data; + register struct il_softc *is = &il_softc[ifp->if_unit]; int s = splimp(), error = 0; switch (cmd) { @@ -660,7 +625,7 @@ ilioctl(ifp, cmd, data) ifp->if_flags |= IFF_UP; ilinit(ifp->if_unit); - switch (ifa->ifa_addr.sa_family) { + switch (ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: ((struct arpcom *)ifp)->ac_ipaddr = @@ -670,17 +635,55 @@ ilioctl(ifp, cmd, data) #endif #ifdef NS case AF_NS: - IA_SNS(ifa)->sns_addr.x_host = - * (union ns_host *) + { + register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); + + if (ns_nullhost(*ina)) { + ina->x_host = * (union ns_host *) (il_softc[ifp->if_unit].is_addr); + } else { + il_setaddr(ina->x_host.c_host, ifp->if_unit); + return (0); + } break; + } #endif } break; + case SIOCSIFFLAGS: + if ((ifp->if_flags & IFF_UP) == 0 && + is->is_flags & ILF_RUNNING) { + ((struct ildevice *) + (ilinfo[ifp->if_unit]->ui_addr))->il_csr = ILC_RESET; + is->is_flags &= ~ILF_RUNNING; + } else if (ifp->if_flags & IFF_UP && + (is->is_flags & ILF_RUNNING) == 0) + ilinit(ifp->if_unit); + break; + default: error = EINVAL; } splx(s); return (error); } + +/* + * set ethernet address for unit + */ +il_setaddr(physaddr, unit) +u_char *physaddr; +int unit; +{ + register struct il_softc *is = &il_softc[unit]; + + if (! (is->is_flags & ILF_RUNNING)) + return; + + bcopy((caddr_t)physaddr, (caddr_t)is->is_addr, sizeof is->is_addr); + is->is_flags &= ~ILF_RUNNING; + is->is_flags |= ILF_SETADDR; + ilinit(unit); +} +#endif