X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/51595ca22093666a8ba6b09214e4cf8aad770db4..667b32867c6dffc35ca4222282de798640f1aaf2:/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 e26c04927f..57802c78fd 100644 --- a/usr/src/sys/vax/if/if_il.c +++ b/usr/src/sys/vax/if/if_il.c @@ -1,49 +1,65 @@ -/* if_il.c 4.13 82/10/31 */ +/* + * Copyright (c) 1982 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + * + * @(#)if_il.c 6.8 (Berkeley) %G% + */ #include "il.h" /* * Interlan Ethernet Communications Controller interface */ -#include "../h/param.h" -#include "../h/systm.h" -#include "../h/mbuf.h" -#include "../h/pte.h" -#include "../h/buf.h" -#include "../h/protosw.h" -#include "../h/socket.h" -#include "../h/vmmac.h" -#include +#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 INET #include "../netinet/in.h" #include "../netinet/in_systm.h" +#include "../netinet/in_var.h" #include "../netinet/ip.h" #include "../netinet/ip_var.h" +#include "../netinet/if_ether.h" +#endif + +#ifdef PUP #include "../netpup/pup.h" +#endif + +#ifdef NS +#include "../netns/ns.h" +#include "../netns/ns_if.h" +#endif #include "../vax/cpu.h" #include "../vax/mtpr.h" -#include "../vaxif/if_ilreg.h" -#include "../vaxif/if_il.h" -#include "../vaxif/if_uba.h" +#include "if_il.h" +#include "if_ilreg.h" +#include "if_uba.h" #include "../vaxuba/ubareg.h" #include "../vaxuba/ubavar.h" -#define ILMTU 1500 - int ilprobe(), ilattach(), ilrint(), ilcint(); struct uba_device *ilinfo[NIL]; u_short ilstd[] = { 0 }; struct uba_driver ildriver = { ilprobe, 0, ilattach, 0, ilstd, "il", ilinfo }; #define ILUNIT(x) minor(x) -int ilinit(),iloutput(),ilreset(),ilwatch(); - -u_char il_ectop[3] = { 0x02, 0x60, 0x8c }; -u_char ilbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +int ilinit(),iloutput(),ilioctl(),ilreset(),ilwatch(); /* * Ethernet software status per interface. @@ -58,7 +74,9 @@ u_char ilbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; * efficiently. */ struct il_softc { - struct ifnet is_if; /* network-visible interface */ + 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 */ @@ -81,7 +99,7 @@ ilprobe(reg) #ifdef lint br = 0; cvec = br; br = cvec; - ilrint(0); ilcint(0); ilwatch(0); + i = 0; ilrint(i); ilcint(i); ilwatch(i); #endif addr->il_csr = ILC_OFFLINE|IL_CIE; @@ -104,12 +122,11 @@ ilattach(ui) register struct il_softc *is = &il_softc[ui->ui_unit]; register struct ifnet *ifp = &is->is_if; register struct ildevice *addr = (struct ildevice *)ui->ui_addr; - struct sockaddr_in *sin; ifp->if_unit = ui->ui_unit; ifp->if_name = "il"; - ifp->if_mtu = ILMTU; - ifp->if_net = ui->ui_flags; + ifp->if_mtu = ETHERMTU; + ifp->if_flags = IFF_BROADCAST; /* * Reset the board and map the statistics @@ -122,8 +139,8 @@ ilattach(ui) printf("il%d: reset failed, csr=%b\n", ui->ui_unit, addr->il_csr, IL_BITS); - is->is_ubaddr = uballoc(ui->ui_ubanum, &is->is_stats, - sizeof (struct il_stats), 0); + 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; @@ -133,31 +150,20 @@ ilattach(ui) printf("il%d: status failed, csr=%b\n", ui->ui_unit, addr->il_csr, IL_BITS); 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); - ifp->if_host[0] = - ((is->is_stats.ils_addr[3]&0xff)<<16) | 0x800000 | - ((is->is_stats.ils_addr[4]&0xff)<<8) | - (is->is_stats.ils_addr[5]&0xff); - sin = (struct sockaddr_in *)&ifp->if_addr; - sin->sin_family = AF_INET; - sin->sin_addr = if_makeaddr(ifp->if_net, ifp->if_host[0]); - - sin = (struct sockaddr_in *)&ifp->if_broadaddr; - sin->sin_family = AF_INET; - sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY); - ifp->if_flags = IFF_BROADCAST; - +#endif + bcopy((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr, + sizeof (is->is_addr)); ifp->if_init = ilinit; ifp->if_output = iloutput; + ifp->if_ioctl = ilioctl; ifp->if_reset = ilreset; - ifp->if_watchdog = ilwatch; - is->is_scaninterval = ILWATCHINTERVAL; - ifp->if_timer = is->is_scaninterval; is->is_ifuba.ifu_flags = UBA_CANTWAIT; #ifdef notdef is->is_ifuba.ifu_flags |= UBA_NEEDBDP; @@ -191,18 +197,41 @@ ilinit(unit) register struct il_softc *is = &il_softc[unit]; register struct uba_device *ui = ilinfo[unit]; register struct ildevice *addr; + register struct ifnet *ifp = &is->is_if; int s; + /* 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(ILMTU)) == 0) { + 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, &is->is_stats, - sizeof (struct il_stats), 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; addr = (struct ildevice *)ui->ui_addr; + /* + * Turn off source address insertion (it's faster this way), + * and set board online. Former doesn't work if board is + * already online (happens on ubareset), so we put it offline + * first. + */ + s = splimp(); + addr->il_csr = ILC_OFFLINE; + while ((addr->il_csr & IL_CDONE) == 0) + ; + addr->il_csr = ILC_CISA; + while ((addr->il_csr & IL_CDONE) == 0) + ; /* * Set board online. * Hang receive buffer and start any pending @@ -210,22 +239,20 @@ ilinit(unit) * Receive bcr is not a muliple of 4 so buffer * chaining can't happen. */ - s = splimp(); addr->il_csr = ILC_ONLINE; while ((addr->il_csr & IL_CDONE) == 0) ; addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff; - addr->il_bcr = sizeof(struct il_rheader) + ILMTU + 6; + 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; + ((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_UP; + is->is_if.if_flags |= IFF_RUNNING; is->is_lastcmd = 0; ilcint(unit); splx(s); - if_rtinit(&is->is_if, RTF_UP); } /* @@ -236,7 +263,7 @@ ilinit(unit) ilstart(dev) dev_t dev; { - int unit = ILUNIT(dev), dest, len; + int unit = ILUNIT(dev), len; struct uba_device *ui = ilinfo[unit]; register struct il_softc *is = &il_softc[unit]; register struct ildevice *addr; @@ -248,13 +275,22 @@ ilstart(dev) if (m == 0) { if ((is->is_flags & ILF_STATPENDING) == 0) return; - addr->il_bar = is->is_ubaddr & 0xfff; + 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; is->is_flags &= ~ILF_STATPENDING; goto startcmd; } len = if_wubaput(&is->is_ifuba, m); + /* + * Ensure minimum packet length. + * This makes the safe assumtion that there are no virtual holes + * after the data. + * For security, it might be wise to zero out the added bytes, + * but we're mainly interested in speed at the moment. + */ + if (len - sizeof(struct ether_header) < ETHERMIN) + len = ETHERMIN + sizeof(struct ether_header); if (is->is_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_w.ifrw_bdp); addr->il_bar = is->is_ifuba.ifu_w.ifrw_info & 0xffff; @@ -292,7 +328,7 @@ ilcint(unit) */ if (is->is_flags & ILF_RCVPENDING) { addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff; - addr->il_bcr = sizeof(struct il_rheader) + ILMTU + 6; + 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; while ((addr->il_csr & IL_CDONE) == 0) @@ -337,7 +373,7 @@ ilrint(unit) struct ildevice *addr = (struct ildevice *)ilinfo[unit]->ui_addr; register struct il_rheader *il; struct mbuf *m; - int len, off, resid; + int len, off, resid, s; register struct ifqueue *inq; is->is_if.if_ipackets++; @@ -345,7 +381,8 @@ ilrint(unit) UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_r.ifrw_bdp); il = (struct il_rheader *)(is->is_ifuba.ifu_r.ifrw_addr); len = il->ilr_length - sizeof(struct il_rheader); - if ((il->ilr_status&(ILFSTAT_A|ILFSTAT_C)) || len < 46 || len > ILMTU) { + if ((il->ilr_status&(ILFSTAT_A|ILFSTAT_C)) || len < 46 || + len > ETHERMTU) { is->is_if.if_ierrors++; #ifdef notdef if (is->is_if.if_ierrors % 100 == 0) @@ -355,18 +392,19 @@ ilrint(unit) } /* - * Deal with trailer protocol: if type is PUP trailer + * Deal with trailer protocol: if type is trailer type * get true type from first 16-bit word past data. * Remember that type was trailer by setting off. */ + il->ilr_type = ntohs((u_short)il->ilr_type); #define ildataaddr(il, off, type) ((type)(((caddr_t)((il)+1)+(off)))) - if (il->ilr_type >= ILPUP_TRAIL && - il->ilr_type < ILPUP_TRAIL+ILPUP_NTRAILER) { - off = (il->ilr_type - ILPUP_TRAIL) * 512; - if (off >= ILMTU) + if (il->ilr_type >= ETHERTYPE_TRAIL && + il->ilr_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { + off = (il->ilr_type - ETHERTYPE_TRAIL) * 512; + if (off >= ETHERMTU) goto setup; /* sanity */ - il->ilr_type = *ildataaddr(il, off, u_short *); - resid = *(ildataaddr(il, off+2, u_short *)); + il->ilr_type = ntohs(*ildataaddr(il, off, u_short *)); + resid = ntohs(*(ildataaddr(il, off+2, u_short *))); if (off + resid > len) goto setup; /* sanity */ len = off + resid; @@ -391,22 +429,34 @@ ilrint(unit) switch (il->ilr_type) { #ifdef INET - case ILPUP_IPTYPE: + 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); - goto setup; - } - IF_ENQUEUE(inq, m); + } else + IF_ENQUEUE(inq, m); + splx(s); setup: /* @@ -419,7 +469,7 @@ setup: return; } addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff; - addr->il_bcr = sizeof(struct il_rheader) + ILMTU + 6; + 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; while ((addr->il_csr & IL_CDONE) == 0) @@ -437,31 +487,51 @@ iloutput(ifp, m0, dst) struct mbuf *m0; struct sockaddr *dst; { - int type, dest, s, error; + 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 il_xheader *il; - register int off, i; + register struct ether_header *il; + register int off; switch (dst->sa_family) { #ifdef INET case AF_INET: - dest = ((struct sockaddr_in *)dst)->sin_addr.s_addr; + 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 = ILPUP_TRAIL + (off>>9); + type = ETHERTYPE_TRAIL + (off>>9); m->m_off -= 2 * sizeof (u_short); m->m_len += 2 * sizeof (u_short); - *mtod(m, u_short *) = ILPUP_IPTYPE; - *(mtod(m, u_short *) + 1) = m->m_len; + *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); + *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); goto gottrailertype; } - type = ILPUP_IPTYPE; + 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, @@ -488,31 +558,24 @@ gottype: * allocate another. */ if (m->m_off > MMAXOFF || - MMINOFF + sizeof (struct il_xheader) > m->m_off) { - m = m_get(M_DONTWAIT); + 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 il_xheader); + m->m_len = sizeof (struct ether_header); } else { - m->m_off -= sizeof (struct il_xheader); - m->m_len += sizeof (struct il_xheader); - } - il = mtod(m, struct il_xheader *); - if ((dest &~ 0xff) == 0) - bcopy(ilbroadcastaddr, il->ilx_dhost, 6); - else { - u_char *to = dest & 0x8000 ? is->is_stats.ils_addr : il_ectop; - - bcopy(to, il->ilx_dhost, 3); - il->ilx_dhost[3] = (dest>>8) & 0x7f; - il->ilx_dhost[4] = (dest>>16) & 0xff; - il->ilx_dhost[5] = (dest>>24) & 0xff; + m->m_off -= sizeof (struct ether_header); + m->m_len += sizeof (struct ether_header); } - il->ilx_type = type; + 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 @@ -573,3 +636,45 @@ iltotal(is) *sum++ += *interval++; is->is_if.if_collisions = is->is_sum.ils_collis; } + +/* + * Process an ioctl request. + */ +ilioctl(ifp, cmd, data) + register struct ifnet *ifp; + int cmd; + caddr_t data; +{ + register struct ifaddr *ifa = (struct ifaddr *)data; + int s = splimp(), error = 0; + + switch (cmd) { + + case SIOCSIFADDR: + ifp->if_flags |= IFF_UP; + ilinit(ifp->if_unit); + + switch (ifa->ifa_addr.sa_family) { +#ifdef INET + case AF_INET: + ((struct arpcom *)ifp)->ac_ipaddr = + IA_SIN(ifa)->sin_addr; + arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); + break; +#endif +#ifdef NS + case AF_NS: + IA_SNS(ifa)->sns_addr.x_host = + * (union ns_host *) + (il_softc[ifp->if_unit].is_addr); + break; +#endif + } + break; + + default: + error = EINVAL; + } + splx(s); + return (error); +}