-/* 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
#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 <errno.h>
+
#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 <errno.h>
+#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];
#define ECUNIT(x) minor(x)
int ecinit(),ecoutput(),ecreset();
-struct mbuf *ecget();
+struct mbuf *ecget();
extern struct ifnet loif;
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];
{
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);
* 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.
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);
}
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);
}
/*
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);
}
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);
}
/*
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;
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;
}
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);
}
/*
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)
/*
* Clear the controller's collision flag, thus enabling retransmit.
*/
- addr->ec_xcr = EC_JINTEN|EC_XINTEN|EC_JCLR;
+ addr->ec_xcr = EC_CLEAR;
}
/*
int unit;
{
struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
-COUNT(ECRINT);
while (addr->ec_rcr & EC_RDONE)
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++;
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;
}
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;
}
/*
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;
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 {
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);
}
/*
- * 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; i<mp->m_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);
}
/*
*/
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;
m->m_len = len = MIN(MLEN, len);
m->m_off = MMINOFF;
}
- mcp = mtod(m, char *);
- for (i=0; i<len; i+=2) {
- *(short *)mcp = *(short *)cp;
- mcp += 2;
- cp += 2;
+ mcp = mtod(m, u_char *);
+ if (words = (len >> 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