X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/949a0907b43a85dd280bf72409a5816702ecf8ca..4fce3bf9816218d3cead81ad945ddd9e9f5f27e6:/usr/src/sys/vax/if/if_ec.c diff --git a/usr/src/sys/vax/if/if_ec.c b/usr/src/sys/vax/if/if_ec.c index 43038476f6..97526b4034 100644 --- a/usr/src/sys/vax/if/if_ec.c +++ b/usr/src/sys/vax/if/if_ec.c @@ -1,8 +1,6 @@ -/* if_ec.c 4.14 82/06/05 */ +/* if_ec.c 4.29 82/11/13 */ #include "ec.h" -#include "imp.h" -#include "loop.h" /* * 3Com Ethernet Controller interface @@ -15,24 +13,29 @@ #include "../h/buf.h" #include "../h/protosw.h" #include "../h/socket.h" -#include "../h/ubareg.h" -#include "../h/ubavar.h" -#include "../h/ecreg.h" -#include "../h/cpu.h" -#include "../h/mtpr.h" #include "../h/vmmac.h" -#include "../net/in.h" -#include "../net/in_systm.h" +#include + #include "../net/if.h" -#include "../net/if_ec.h" -#include "../net/if_uba.h" -#include "../net/ip.h" -#include "../net/ip_var.h" -#include "../net/pup.h" +#include "../net/netisr.h" #include "../net/route.h" -#include +#include "../netinet/in.h" +#include "../netinet/in_systm.h" +#include "../netinet/ip.h" +#include "../netinet/ip_var.h" +#include "../netpup/pup.h" + +#include "../vax/cpu.h" +#include "../vax/mtpr.h" +#include "../vaxif/if_ec.h" +#include "../vaxif/if_ecreg.h" +#include "../vaxif/if_uba.h" +#include "../vaxuba/ubareg.h" +#include "../vaxuba/ubavar.h" #define ECMTU 1500 +#define ECMIN (60-14) +#define ECMEM 0000000 int ecprobe(), ecattach(), ecrint(), ecxint(), eccollide(); struct uba_device *ecinfo[NEC]; @@ -43,7 +46,7 @@ u_char ec_iltop[3] = { 0x02, 0x07, 0x01 }; #define ECUNIT(x) minor(x) int ecinit(),ecoutput(),ecreset(); -struct mbuf *ecget(); +struct mbuf *ecget(); extern struct ifnet loif; @@ -64,7 +67,7 @@ struct ec_softc { struct ifuba es_ifuba; /* UNIBUS resources */ short es_mask; /* mask for current output delay */ short es_oactive; /* is output active? */ - caddr_t es_buf[16]; /* virtual addresses of buffers */ + u_char *es_buf[16]; /* virtual addresses of buffers */ u_char es_enaddr[6]; /* board's ethernet address */ } ec_softc[NEC]; @@ -77,9 +80,8 @@ ecprobe(reg) { register int br, cvec; /* r11, r10 value-result */ register struct ecdevice *addr = (struct ecdevice *)reg; - register caddr_t ecbuf = (caddr_t) &umem[0][0600000]; + register caddr_t ecbuf = (caddr_t) &umem[numuba][ECMEM]; -COUNT(ECPROBE); #ifdef lint br = 0; cvec = br; br = cvec; ecrint(0); ecxint(0); eccollide(0); @@ -88,20 +90,37 @@ COUNT(ECPROBE); * Make sure memory is turned on */ addr->ec_rcr = EC_AROM; + /* + * Disable map registers for ec unibus space, + * but don't allocate yet. + */ + (void) ubamem(numuba, ECMEM, 32*2, 0); /* * Check for existence of buffers on Unibus. - * This won't work on a 780 until more work is done. */ - if (badaddr((caddr_t) ecbuf, 2)) { - printf("ec: buffer mem not found"); + if (badaddr((caddr_t)ecbuf, 2)) { + bad1: + printf("ec: buffer mem not found\n"); + bad2: + (void) ubamem(numuba, 0, 0, 0); /* reenable map (780 only) */ + addr->ec_rcr = EC_MDISAB; /* disable memory */ return (0); } +#if VAX780 + if (cpu == VAX_780 && uba_hd[numuba].uh_uba->uba_sr) { + uba_hd[numuba].uh_uba->uba_sr = uba_hd[numuba].uh_uba->uba_sr; + goto bad1; + } +#endif /* * Tell the system that the board has memory here, so it won't * attempt to allocate the addresses later. */ - ubamem(0, 0600000, 32*2); + if (ubamem(numuba, ECMEM, 32*2, 1) == 0) { + printf("ecprobe: cannot reserve uba addresses\n"); + goto bad2; + } /* * Make a one byte packet in what should be buffer #0. @@ -114,9 +133,15 @@ COUNT(ECPROBE); addr->ec_xcr = EC_XINTEN|EC_XWBN; DELAY(100000); addr->ec_xcr = EC_XCLR; - if (cvec > 0 && cvec != 0x200) - cvec -= 010; - br += 2; + if (cvec > 0 && cvec != 0x200) { + if (cvec & 04) { /* collision interrupt */ + cvec -= 04; + br += 1; /* rcv is collision + 1 */ + } else { /* xmit interrupt */ + cvec -= 010; + br += 2; /* rcv is xmit + 2 */ + } + } return (1); } @@ -128,66 +153,56 @@ COUNT(ECPROBE); ecattach(ui) struct uba_device *ui; { - register struct ec_softc *es = &ec_softc[ui->ui_unit]; - register struct sockaddr_in *sin; + struct ec_softc *es = &ec_softc[ui->ui_unit]; + register struct ifnet *ifp = &es->es_if; register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr; - register int i, j; - register u_char *cp; -COUNT(ECATTACH); + struct sockaddr_in *sin; + int i, j; + u_char *cp; - es->es_if.if_unit = ui->ui_unit; - es->es_if.if_name = "ec"; - es->es_if.if_mtu = ECMTU; - es->es_if.if_net = ui->ui_flags & 0xff; + ifp->if_unit = ui->ui_unit; + ifp->if_name = "ec"; + ifp->if_mtu = ECMTU; + ifp->if_net = ui->ui_flags; /* - * Read the ethernet address off the board, - * one nibble at a time! + * Read the ethernet address off the board, one nibble at a time. */ addr->ec_xcr = EC_UECLR; addr->ec_rcr = EC_AROM; cp = es->es_enaddr; +#define NEXTBIT addr->ec_rcr = EC_AROM|EC_ASTEP; addr->ec_rcr = EC_AROM for (i=0; i<6; i++) { *cp = 0; for (j=0; j<=4; j+=4) { *cp |= ((addr->ec_rcr >> 8) & 0xf) << j; - addr->ec_rcr = EC_AROM|EC_ASTEP; - addr->ec_rcr = EC_AROM; - addr->ec_rcr = EC_AROM|EC_ASTEP; - addr->ec_rcr = EC_AROM; - addr->ec_rcr = EC_AROM|EC_ASTEP; - addr->ec_rcr = EC_AROM; - addr->ec_rcr = EC_AROM|EC_ASTEP; - addr->ec_rcr = EC_AROM; + NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT; } cp++; } +#ifdef notdef printf("ec%d: addr=%x:%x:%x:%x:%x:%x\n", ui->ui_unit, es->es_enaddr[0]&0xff, es->es_enaddr[1]&0xff, es->es_enaddr[2]&0xff, es->es_enaddr[3]&0xff, es->es_enaddr[4]&0xff, es->es_enaddr[5]&0xff); - es->es_if.if_host[0] = ((es->es_enaddr[3]&0xff)<<16) | +#endif + ifp->if_host[0] = ((es->es_enaddr[3]&0xff)<<16) | ((es->es_enaddr[4]&0xff)<<8) | (es->es_enaddr[5]&0xff); sin = (struct sockaddr_in *)&es->es_if.if_addr; sin->sin_family = AF_INET; - sin->sin_addr = if_makeaddr(es->es_if.if_net, es->es_if.if_host[0]); + sin->sin_addr = if_makeaddr(ifp->if_net, ifp->if_host[0]); - sin = (struct sockaddr_in *)&es->es_if.if_broadaddr; + sin = (struct sockaddr_in *)&ifp->if_broadaddr; sin->sin_family = AF_INET; - sin->sin_addr = if_makeaddr(es->es_if.if_net, 0); - es->es_if.if_flags = IFF_BROADCAST; + sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY); + ifp->if_flags = IFF_BROADCAST; - es->es_if.if_init = ecinit; - es->es_if.if_output = ecoutput; - es->es_if.if_ubareset = ecreset; + ifp->if_init = ecinit; + ifp->if_output = ecoutput; + ifp->if_reset = ecreset; for (i=0; i<16; i++) - es->es_buf[i] = &umem[ui->ui_ubanum][0600000+2048*i]; - if_attach(&es->es_if); -#if NIMP == 0 - /* here's one for you john baby.... */ - if (ui->ui_flags &~ 0xff) - eclhinit(&es->es_if, (ui->ui_flags &~ 0xff) | 0x0a); -#endif + es->es_buf[i] = (u_char *)&umem[ui->ui_ubanum][ECMEM+2048*i]; + if_attach(ifp); } /* @@ -198,12 +213,12 @@ ecreset(unit, uban) int unit, uban; { register struct uba_device *ui; -COUNT(ECRESET); if (unit >= NEC || (ui = ecinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" ec%d", unit); + (void) ubamem(uban, ECMEM, 32*2, 0); /* mr disable (no alloc) */ ecinit(unit); } @@ -214,28 +229,26 @@ COUNT(ECRESET); ecinit(unit) int unit; { - register struct ec_softc *es = &ec_softc[unit]; - register struct uba_device *ui = ecinfo[unit]; - register struct ecdevice *addr; - register i; - int s; - - addr = (struct ecdevice *)ui->ui_addr; + struct ec_softc *es = &ec_softc[unit]; + struct ecdevice *addr; + int i, s; /* - * Hang receive buffers and start any pending - * writes by faking a transmit complete. + * Hang receive buffers and start any pending writes. * Writing into the rcr also makes sure the memory * is turned on. */ + addr = (struct ecdevice *)ecinfo[unit]->ui_addr; s = splimp(); for (i=ECRHBF; i>=ECRLBF; i--) addr->ec_rcr = EC_READ|i; - es->es_oactive = 1; + es->es_oactive = 0; + es->es_mask = ~0; es->es_if.if_flags |= IFF_UP; - ecxint(unit); + if (es->es_if.if_snd.ifq_head) + ecstart(unit); splx(s); - if_rtinit(&es->es_if, RTF_DIRECT|RTF_UP); + if_rtinit(&es->es_if, RTF_UP); } /* @@ -250,22 +263,13 @@ ecstart(dev) dev_t dev; { int unit = ECUNIT(dev); - struct uba_device *ui = ecinfo[unit]; - register struct ec_softc *es = &ec_softc[unit]; - register struct ecdevice *addr; + struct ec_softc *es = &ec_softc[unit]; + struct ecdevice *addr; struct mbuf *m; - caddr_t ecbuf; - int dest; -COUNT(ECSTART); if (es->es_oactive) goto restart; - /* - * Not already active: dequeue another request - * and copy it into the buffer. If no more requests, - * just return. - */ IF_DEQUEUE(&es->es_if.if_snd, m); if (m == 0) { es->es_oactive = 0; @@ -274,10 +278,7 @@ COUNT(ECSTART); ecput(es->es_buf[ECTBF], m); restart: - /* - * Start the output. - */ - addr = (struct ecdevice *)ui->ui_addr; + addr = (struct ecdevice *)ecinfo[unit]->ui_addr; addr->ec_xcr = EC_WRITE|ECTBF; es->es_oactive = 1; } @@ -289,30 +290,25 @@ restart: ecxint(unit) int unit; { - register struct uba_device *ui = ecinfo[unit]; register struct ec_softc *es = &ec_softc[unit]; - register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr; -COUNT(ECXINT); + register struct ecdevice *addr = + (struct ecdevice *)ecinfo[unit]->ui_addr; if (es->es_oactive == 0) return; - if (addr->ec_xcr&EC_XDONE == 0 || addr->ec_xcr&EC_XBN != ECTBF) - printf("ec%d: strange xmit interrupt!\n", unit); + if ((addr->ec_xcr&EC_XDONE) == 0 || (addr->ec_xcr&EC_XBN) != ECTBF) { + printf("ec%d: stray xmit interrupt, xcr=%b\n", unit, + addr->ec_xcr, EC_XBITS); + es->es_oactive = 0; + addr->ec_xcr = EC_XCLR; + return; + } es->es_if.if_opackets++; es->es_oactive = 0; es->es_mask = ~0; addr->ec_xcr = EC_XCLR; - /* - * There shouldn't ever be any mbuf's to free, but just in case... - */ - if (es->es_ifuba.ifu_xtofree) { - m_freem(es->es_ifuba.ifu_xtofree); - es->es_ifuba.ifu_xtofree = 0; - } - if (es->es_if.if_snd.ifq_head == 0) { - return; - } - ecstart(unit); + if (es->es_if.if_snd.ifq_head) + ecstart(unit); } /* @@ -324,13 +320,10 @@ eccollide(unit) int unit; { struct ec_softc *es = &ec_softc[unit]; -COUNT(ECCOLLIDE); - printf("ec%d: collision\n", unit); es->es_if.if_collisions++; - if (es->es_oactive == 0) - return; - ecdocoll(unit); + if (es->es_oactive) + ecdocoll(unit); } ecdocoll(unit) @@ -380,7 +373,7 @@ ecdocoll(unit) /* * Clear the controller's collision flag, thus enabling retransmit. */ - addr->ec_xcr = EC_JINTEN|EC_XINTEN|EC_JCLR; + addr->ec_xcr = EC_CLEAR; } /* @@ -396,7 +389,6 @@ ecrint(unit) int unit; { struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr; -COUNT(ECRINT); while (addr->ec_rcr & EC_RDONE) ecread(unit); @@ -409,18 +401,15 @@ ecread(unit) struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr; register struct ec_header *ec; struct mbuf *m; - int len, off, resid; + int len, off, resid, ecoff, rbuf; register struct ifqueue *inq; - caddr_t ecbuf; - int ecoff; - int buf; -COUNT(ECREAD); + u_char *ecbuf; es->es_if.if_ipackets++; - buf = addr->ec_rcr & EC_RBN; - if (buf < ECRLBF || buf > ECRHBF) + rbuf = addr->ec_rcr & EC_RBN; + if (rbuf < ECRLBF || rbuf > ECRHBF) panic("ecrint"); - ecbuf = es->es_buf[buf]; + ecbuf = es->es_buf[rbuf]; ecoff = *(short *)ecbuf; if (ecoff <= ECRDOFF || ecoff > 2046) { es->es_if.if_ierrors++; @@ -428,7 +417,6 @@ COUNT(ECREAD); if (es->es_if.if_ierrors % 100 == 0) printf("ec%d: += 100 input errors\n", unit); #endif - printf("ec%d: input error (offset=%d)\n", unit, ecoff); goto setup; } @@ -486,14 +474,15 @@ COUNT(ECREAD); if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); - } else - IF_ENQUEUE(inq, m); + goto setup; + } + IF_ENQUEUE(inq, m); setup: /* * Reset for next packet. */ - addr->ec_rcr = EC_READ|EC_RCLR|buf; + addr->ec_rcr = EC_READ|EC_RCLR|rbuf; } /* @@ -514,18 +503,16 @@ ecoutput(ifp, m0, dst) register struct ec_softc *es = &ec_softc[ifp->if_unit]; register struct mbuf *m = m0; register struct ec_header *ec; - register int off; - register int i; + register int off, i; struct mbuf *mcopy = (struct mbuf *) 0; /* Null */ -COUNT(ECOUTPUT); switch (dst->sa_family) { #ifdef INET case AF_INET: dest = ((struct sockaddr_in *)dst)->sin_addr.s_addr; if ((dest &~ 0xff) == 0) - mcopy = m_copy(m, 0, M_COPYALL); + mcopy = m_copy(m, 0, (int)M_COPYALL); else if (dest == ((struct sockaddr_in *)&es->es_if.if_addr)-> sin_addr.s_addr) { mcopy = m; @@ -588,6 +575,7 @@ gottype: for (i=0; i<6; i++) ec->ec_shost[i] = es->es_enaddr[i]; if ((dest &~ 0xff) == 0) + /* broadcast address */ for (i=0; i<6; i++) ec->ec_dhost[i] = 0xff; else { @@ -620,11 +608,10 @@ gottype: if (es->es_oactive == 0) ecstart(ifp->if_unit); splx(s); + gotlocal: - if (mcopy) /* Kludge, but it works! */ - return(looutput(&loif, mcopy, dst)); - else - return (0); + return(mcopy ? looutput(&loif, mcopy, dst) : 0); + qfull: m0 = m; splx(s); @@ -634,45 +621,56 @@ bad: } /* - * Routine to copy from mbufs to UNIBUS memory. - * Similar in spirit to if_wubaput. + * Routine to copy from mbuf chain to transmit + * buffer in UNIBUS memory. + * If packet size is less than the minimum legal size, + * the buffer is expanded. We probably should zero out the extra + * bytes for security, but that would slow things down. */ ecput(ecbuf, m) - char *ecbuf; + u_char *ecbuf; struct mbuf *m; { - register int len; register struct mbuf *mp; - register char *bp, *mcp; - register int i; - -COUNT(ECPUT); - len = 0; - for (mp=m; mp; mp=mp->m_next) - len += mp->m_len; - *(u_short *)ecbuf = 2048 - len; - bp = ecbuf + 2048 - len; - mp = m; - while (mp) { - mcp = mtod(mp, char *); - i = 0; - if ((int)bp&1) { + register int off; + u_char *bp; + + for (off = 2048, mp = m; mp; mp = mp->m_next) + off -= mp->m_len; + if (2048 - off < ECMIN + sizeof (struct ec_header)) + off = 2048 - ECMIN - sizeof (struct ec_header); + *(u_short *)ecbuf = off; + bp = (u_char *)(ecbuf + off); + for (mp = m; mp; mp = mp->m_next) { + register unsigned len = mp->m_len; + u_char *mcp; + + if (len == 0) + continue; + mcp = mtod(mp, u_char *); + if ((unsigned)bp & 01) { *bp++ = *mcp++; - i++; + len--; } - for (i=0; im_len; i++) - while (i < mp->m_len) { - *(short *)bp = *(short *)mcp; - bp += 2; - mcp += 2; - i += 2; + if (off = (len >> 1)) { + register u_short *to, *from; + + to = (u_short *)bp; + from = (u_short *)mcp; + do + *to++ = *from++; + while (--off > 0); + bp = (u_char *)to, + mcp = (u_char *)from; } - if (mp->m_len&1) + if (len & 01) *bp++ = *mcp++; - mp = m_free(mp); } - if (bp != ecbuf+2048) - printf("ec: bad ecput!\n"); +#ifdef notdef + if (bp - ecbuf != 2048) + printf("ec: bad ecput, diff=%d\n", bp-ecbuf); +#endif + m_freem(m); } /* @@ -684,20 +682,19 @@ COUNT(ECPUT); */ struct mbuf * ecget(ecbuf, totlen, off0) - char *ecbuf; + u_char *ecbuf; int totlen, off0; { - struct mbuf *top, **mp, *m; - int off = off0; - int len; - register char *cp = ecbuf + ECRDOFF + sizeof (struct ec_header); - register char *mcp; - register int i; - -COUNT(ECGET); - top = 0; - mp = ⊤ + register struct mbuf *m; + struct mbuf *top = 0, **mp = ⊤ + register int off = off0, len; + u_char *cp; + + cp = ecbuf + ECRDOFF + sizeof (struct ec_header); while (totlen > 0) { + register int words; + u_char *mcp; + MGET(m, 0); if (m == 0) goto bad; @@ -721,69 +718,35 @@ COUNT(ECGET); m->m_len = len = MIN(MLEN, len); m->m_off = MMINOFF; } - mcp = mtod(m, char *); - for (i=0; i> 1)) { + register u_short *to, *from; + + to = (u_short *)mcp; + from = (u_short *)cp; + do + *to++ = *from++; + while (--words > 0); + mcp = (u_char *)to; + cp = (u_char *)from; } - if (len&1) + if (len & 01) *mcp++ = *cp++; *mp = m; mp = &m->m_next; - if (off) { - off += len; - if (off == totlen) { - cp = ecbuf + ECRDOFF + - sizeof (struct ec_header); - off = 0; - totlen = off0; - } - } else + if (off == 0) { totlen -= len; + continue; + } + off += len; + if (off == totlen) { + cp = ecbuf + ECRDOFF + sizeof (struct ec_header); + off = 0; + totlen = off0; + } } return (top); bad: m_freem(top); return (0); } - -#if NIMP == 0 && NEC > 0 -/* - * Logical host interface driver. - * Allows host to appear as an ARPAnet - * logical host. Must also have routing - * table entry set up to forward packets - * to appropriate gateway on localnet. - */ - -struct ifnet eclhif; -int looutput(); - -/* - * Called by localnet interface to allow logical - * host interface to "attach", it's purpose - * is simply to establish the host's arpanet address. - */ -eclhinit(ecifp, addr) - struct ifnet *ecifp; - int addr; -{ - register struct ifnet *ifp = &eclhif; - register struct sockaddr_in *sin; - -COUNT(ECLHINIT); - ifp->if_name = "lh"; - ifp->if_mtu = ECMTU; - sin = (struct sockaddr_in *)&ifp->if_addr; - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = addr; - sin->sin_addr.s_lh = ecifp->if_host[0]; - ifp->if_net = sin->sin_addr.s_net; - ifp->if_dstaddr = ifp->if_addr; - ifp->if_flags = IFF_UP|IFF_POINTOPOINT; - ifp->if_output = looutput; - if_attach(ifp); - rtinit(&ifp->if_addr, &ifp->if_addr, RTF_UP|RTF_DIRECT|RTF_HOST); -} -#endif