X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/e699d09f7b36ab156f75acbb95acbe206ed49849..af359dea2e5ab3e937b62107ecd6a51d78189ed7:/usr/src/sys/tahoe/if/if_enp.c diff --git a/usr/src/sys/tahoe/if/if_enp.c b/usr/src/sys/tahoe/if/if_enp.c index 674e7a1d5a..cd1235c3d7 100644 --- a/usr/src/sys/tahoe/if/if_enp.c +++ b/usr/src/sys/tahoe/if/if_enp.c @@ -2,14 +2,38 @@ * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and that due credit is given - * to the University of California at Berkeley. The name of the University - * may not be used to endorse or promote products derived from this - * software without specific prior written permission. This software - * is provided ``as is'' without express or implied warranty. + * This code is derived from software contributed to Berkeley by + * Computer Consoles Inc. * - * @(#)if_enp.c 7.1 (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_enp.c 7.8 (Berkeley) 12/16/90 */ #include "enp.h" @@ -17,41 +41,41 @@ /* * CMC ENP-20 Ethernet Controller. */ -#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 "vmparam.h" -#include "syslog.h" -#include "uio.h" - -#include "../net/if.h" -#include "../net/netisr.h" -#include "../net/route.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/vmparam.h" +#include "sys/syslog.h" +#include "sys/uio.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" +#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 NS -#include "../netns/ns.h" -#include "../netns/ns_if.h" +#include "netns/ns.h" +#include "netns/ns_if.h" #endif -#include "../tahoe/cpu.h" -#include "../tahoe/pte.h" -#include "../tahoe/mtpr.h" +#include "../include/cpu.h" +#include "../include/pte.h" +#include "../include/mtpr.h" -#include "../tahoevba/vbavar.h" -#include "../tahoeif/if_enpreg.h" +#include "../vba/vbavar.h" +#include "../if/if_enpreg.h" #define ENPSTART 0xf02000 /* standard enp start addr */ #define ENPUNIT(dev) (minor(dev)) /* for enp ram devices */ @@ -67,7 +91,7 @@ struct vba_device *enpinfo[NENP]; struct vba_driver enpdriver = { enpprobe, 0, enpattach, 0, enpstd, "enp", enpinfo, "enp-20", 0 }; -int enpinit(), enpioctl(), enpreset(), enpoutput(); +int enpinit(), enpioctl(), enpreset(), enpoutput(), enpstart(); struct mbuf *enpget(); /* @@ -121,9 +145,10 @@ enpattach(ui) ifp->if_mtu = ETHERMTU; ifp->if_init = enpinit; ifp->if_ioctl = enpioctl; - ifp->if_output = enpoutput; + ifp->if_output = ether_output; + ifp->if_start = enpstart; ifp->if_reset = enpreset; - ifp->if_flags = IFF_BROADCAST; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; if_attach(ifp); } @@ -182,7 +207,7 @@ enpintr(unit) ACK_ENP_INTR(addr); #endif while ((bcbp = (BCB *)ringget((RING *)&addr->enp_tohost )) != 0) { - (void) enpread(&enp_softc[unit], bcbp); + enpread(&enp_softc[unit], bcbp); (void) ringput((RING *)&addr->enp_enpfree, bcbp); } } @@ -197,7 +222,6 @@ enpread(es, bcbp) register struct ether_header *enp; struct mbuf *m; int s, len, off, resid; - register struct ifqueue *inq; es->es_if.if_ipackets++; /* @@ -216,219 +240,63 @@ enpread(es, bcbp) enp->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { off = (enp->ether_type - ETHERTYPE_TRAIL) * 512; if (off >= ETHERMTU) - goto setup; + return; enp->ether_type = ntohs(*enpdataaddr(enp, off, u_short *)); resid = ntohs(*(enpdataaddr(enp, off+2, u_short *))); if (off + resid > len) - goto setup; + return; len = off + resid; } else off = 0; if (len == 0) - goto setup; + return; /* * Pull packet off interface. Off is nonzero if packet * has trailing header; enpget will then force this header - * information to be at the front, but we still have to drop - * the type and length which are at the front of any trailer data. + * information to be at the front. */ m = enpget((u_char *)enp, len, off, &es->es_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 (enp->ether_type) { - -#ifdef INET - case ETHERTYPE_IP: - schednetisr(NETISR_IP); - inq = &ipintrq; - break; -#endif - case ETHERTYPE_ARP: - arpinput(&es->es_ac, m); - goto setup; - -#ifdef NS - case ETHERTYPE_NS: - schednetisr(NETISR_NS); - inq = &nsintrq; - break; -#endif - default: - m_freem(m); - goto setup; - } - if (IF_QFULL(inq)) { - IF_DROP(inq); - m_freem(m); - goto setup; - } - s = splimp(); - IF_ENQUEUE(inq, m); - splx(s); -setup: - return (0); + return; + ether_input(&es->es_if, enp, m); } -/* - * Ethernet output routine. (called by user) - * 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. - * If destination is this address or broadcast, send packet to - * loop device to kludge around the fact that 3com interfaces can't - * talk to themselves. - */ -enpoutput(ifp, m0, dst) +enpstart(ifp) struct ifnet *ifp; - struct mbuf *m0; - struct sockaddr *dst; { - register struct enp_softc *es = &enp_softc[ifp->if_unit]; - register struct mbuf *m = m0; - register struct ether_header *enp; - register int off; - struct mbuf *mcopy = (struct mbuf *)0; - int type, s, error, usetrailers; - u_char edst[6]; - struct in_addr idst; - - if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { - error = ENETDOWN; - goto bad; - } - switch (dst->sa_family) { -#ifdef INET - case AF_INET: - idst = ((struct sockaddr_in *)dst)->sin_addr; - if (!arpresolve(&es->es_ac, m, &idst, edst, &usetrailers)) - return (0); /* if not yet resolved */ - if (!bcmp((caddr_t)edst, (caddr_t)etherbroadcastaddr, - sizeof (edst))) - mcopy = m_copy(m, 0, (int)M_COPYALL); - off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; - if (usetrailers && 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: - bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), - (caddr_t)edst, sizeof (edst)); - if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof (edst))) - mcopy = m_copy(m, 0, (int)M_COPYALL); - else if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, - sizeof (edst))) - return (looutput(&loif, m, dst)); - type = ETHERTYPE_NS; - off = 0; - goto gottype; -#endif - case AF_UNSPEC: - enp = (struct ether_header *)dst->sa_data; - bcopy((caddr_t)enp->ether_dhost, (caddr_t)edst, sizeof (edst)); - type = enp->ether_type; - goto gottype; - - default: - log(LOG_ERR, "enp%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); - } - enp = mtod(m, struct ether_header *); - bcopy((caddr_t)edst, (caddr_t)enp->ether_dhost, sizeof (edst)); - bcopy((caddr_t)es->es_addr, (caddr_t)enp->ether_shost, - sizeof (es->es_addr)); - enp->ether_type = htons((u_short)type); - - /* - * Queue message on interface if possible - */ - s = splimp(); - if (enpput(ifp->if_unit, m)) { - error = ENOBUFS; - goto qfull; - } - splx(s); - es->es_if.if_opackets++; - return (mcopy ? looutput(&loif, mcopy, dst) : 0); -qfull: - splx(s); - m0 = m; -bad: - m_freem(m0); - if (mcopy) - m_freem(mcopy); - return (error); + if (enpput(ifp)) + return (ENOBUFS); + else + return (0); } /* * Routine to copy from mbuf chain to transmitter buffer on the VERSAbus. */ -enpput(unit, m) - int unit; - struct mbuf *m; +enpput(ifp) +struct ifnet *ifp; { register BCB *bcbp; register struct enpdevice *addr; register struct mbuf *mp; register u_char *bp; register u_int len; - u_char *mcp; + int unit = ifp->if_unit, ret = 1; + struct mbuf *m; addr = (struct enpdevice *)enpinfo[unit]->ui_addr; - if (ringempty((RING *)&addr->enp_hostfree)) - return (1); +again: + if (ringempty((RING *)&addr->enp_hostfree)) { + /* ifp->if_flags |= IFF_OACTIVE; */ + return (ret); + } + IF_DEQUEUE(&ifp->if_snd, m); + if (m == 0) { + ifp->if_flags &= ~IFF_OACTIVE; + return (0); + } bcbp = (BCB *)ringget((RING *)&addr->enp_hostfree); bcbp->b_len = 0; bp = (u_char *)ENPGETLONG(&bcbp->b_addr); @@ -436,17 +304,17 @@ enpput(unit, m) len = mp->m_len; if (len == 0) continue; - mcp = mtod(mp, u_char *); - enpcopy(mcp, bp, len); + enpcopy(mtod(mp, u_char *), bp, len); bp += len; bcbp->b_len += len; } - bcbp->b_len = MAX(ETHERMIN+sizeof (struct ether_header), bcbp->b_len); + bcbp->b_len = max(ETHERMIN+sizeof (struct ether_header), bcbp->b_len); bcbp->b_reserved = 0; if (ringput((RING *)&addr->enp_toenp, bcbp) == 1) INTR_ENP(addr); m_freem(m); - return (0); + ret = 0; + goto again; } /* @@ -456,65 +324,69 @@ enpput(unit, m) * mbufs have even lengths. */ struct mbuf * -enpget(rxbuf, totlen, off0, ifp) +enpget(rxbuf, totlen, off, ifp) u_char *rxbuf; - int totlen, off0; + int totlen, off; struct ifnet *ifp; { - register u_char *cp, *mcp; + register u_char *cp; register struct mbuf *m; struct mbuf *top = 0, **mp = ⊤ - int len, off = off0; + int len; + u_char *packet_end; + + rxbuf += sizeof (struct ether_header); + cp = rxbuf; + packet_end = cp + totlen; + if (off) { + off += 2 * sizeof(u_short); + totlen -= 2 *sizeof(u_short); + cp = rxbuf + off; + } + + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == 0) + return (0); + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = totlen; + m->m_len = MHLEN; - cp = rxbuf + sizeof (struct ether_header); while (totlen > 0) { - MGET(m, M_DONTWAIT, MT_DATA); - if (m == 0) - goto bad; - if (off) { - len = totlen - off; - cp = rxbuf + sizeof (struct ether_header) + off; - } else - len = totlen; - if (len >= NBPG) { - MCLGET(m); - if (m->m_len == CLBYTES) - m->m_len = len = MIN(len, CLBYTES); + if (top) { + MGET(m, M_DONTWAIT, MT_DATA); + if (m == 0) { + m_freem(top); + return (0); + } + m->m_len = MLEN; + } + len = min(totlen, (packet_end - cp)); + if (len >= MINCLSIZE) { + MCLGET(m, M_DONTWAIT); + if (m->m_flags & M_EXT) + m->m_len = len = min(len, MCLBYTES); else - m->m_len = len = MIN(MLEN, len); + len = m->m_len; } else { - m->m_len = len = MIN(MLEN, len); - m->m_off = MMINOFF; - } - mcp = mtod(m, u_char *); - if (ifp) { /* - * Prepend interface pointer to first mbuf. + * Place initial small packet/header at end of mbuf. */ - *(mtod(m, struct ifnet **)) = ifp; - mcp += sizeof (ifp); - len -= sizeof (ifp); - ifp = (struct ifnet *)0; + if (len < m->m_len) { + if (top == 0 && len + max_linkhdr <= m->m_len) + m->m_data += max_linkhdr; + m->m_len = len; + } else + len = m->m_len; } - enpcopy(cp, mcp, (u_int)len); - cp += len; + enpcopy(cp, mtod(m, u_char *), (u_int)len); *mp = m; mp = &m->m_next; - if (off == 0) { - totlen -= len; - continue; - } - off += len; - if (off == totlen) { - cp = rxbuf + sizeof (struct ether_header); - off = 0; - totlen = off0; - } + totlen -= len; + cp += len; + if (cp == packet_end) + cp = rxbuf; } return (top); -bad: - m_freem(top); - return (0); } enpcopy(from, to, cnt) @@ -561,7 +433,7 @@ enpioctl(ifp, cmd, data) case SIOCSIFADDR: ifp->if_flags |= IFF_UP; - switch (ifa->ifa_addr.sa_family) { + switch (ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: enpinit(ifp->if_unit); @@ -770,6 +642,7 @@ enpr_write(dev, uio) enpcopy((u_char *)iov->iov_base, (u_char *)&addr->enp_ram[uio->uio_offset], (u_int)iov->iov_len); uio->uio_resid -= iov->iov_len; + uio->uio_offset += iov->iov_len; iov->iov_len = 0; return (0); }