-/* if_en.c 4.40 82/03/15 */
+/* if_en.c 4.49 82/04/01 */
#include "en.h"
+#include "imp.h"
/*
* Xerox prototype (3 Mb) Ethernet interface driver.
#include "../net/ip.h"
#include "../net/ip_var.h"
#include "../net/pup.h"
+#include "../net/route.h"
#define ENMTU (1024+512)
struct uba_device *ui;
{
register struct en_softc *es = &en_softc[ui->ui_unit];
+ register struct sockaddr_in *sin;
COUNT(ENATTACH);
es->es_if.if_unit = ui->ui_unit;
es->es_if.if_name = "en";
es->es_if.if_mtu = ENMTU;
- es->es_if.if_net = ui->ui_flags;
+ es->es_if.if_net = ui->ui_flags & 0xff;
es->es_if.if_host[0] =
- (~(((struct endevice *)eninfo[ui->ui_unit]->ui_addr)->en_addr)) & 0xff;
-#ifdef ENKLUDGE
- if (es->es_if.if_net == 10) {
- es->es_if.if_host[0] <<= 16;
- es->es_if.if_host[0] |= 0x4e;
- }
-#endif
- es->es_if.if_addr =
- if_makeaddr(es->es_if.if_net, es->es_if.if_host[0]);
- es->es_if.if_broadaddr =
- if_makeaddr(es->es_if.if_net, 0);
+ (~(((struct endevice *)eninfo[ui->ui_unit]->ui_addr)->en_addr)) & 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 = (struct sockaddr_in *)&es->es_if.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;
es->es_if.if_init = eninit;
es->es_if.if_output = enoutput;
es->es_if.if_ubareset = enreset;
es->es_ifuba.ifu_flags = UBA_NEEDBDP | UBA_NEED16;
if_attach(&es->es_if);
+#if NIMP == 0
+ /* here's one for you john baby.... */
+ enlhinit((ui->ui_flags &~ 0xff) | 0x0a);
+#endif
}
/*
if (if_ubainit(&es->es_ifuba, ui->ui_ubanum,
sizeof (struct en_header), (int)btoc(ENMTU)) == 0) {
printf("en%d: can't initialize\n", unit);
+ es->es_if.if_flags &= ~IFF_UP;
return;
}
addr = (struct endevice *)ui->ui_addr;
addr->en_iwc = -(sizeof (struct en_header) + ENMTU) >> 1;
addr->en_istat = EN_IEN|EN_GO;
es->es_oactive = 1;
+ es->es_if.if_flags |= IFF_UP;
enxint(unit);
splx(s);
+ if_rtinit(&es->es_if, RTF_DIRECT|RTF_UP);
}
int enlastdel = 25;
* Have request mapped to UNIBUS for transmission.
* Purge any stale data from this BDP, and start the otput.
*/
- UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_w.ifrw_bdp);
+ if (es->es_ifuba.ifu_flags & UBA_NEEDBDP)
+ UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_w.ifrw_bdp);
addr = (struct endevice *)ui->ui_addr;
addr->en_oba = (int)es->es_ifuba.ifu_w.ifrw_info;
addr->en_odelay = es->es_delay;
{
register struct uba_device *ui = eninfo[unit];
register struct en_softc *es = &en_softc[unit];
- register struct endevice *addr;
+ register struct endevice *addr = (struct endevice *)ui->ui_addr;
COUNT(ENXINT);
if (es->es_oactive == 0)
return;
- addr = (struct endevice *)ui->ui_addr;
+ if (es->es_mask && (addr->en_ostat&EN_OERROR)) {
+ es->es_if.if_oerrors++;
+ if (es->es_if.if_oerrors % 100 == 0)
+ printf("en%d: += 100 output errors\n", unit);
+ endocoll(unit);
+ return;
+ }
es->es_if.if_opackets++;
es->es_oactive = 0;
es->es_delay = 0;
es->es_mask = ~0;
- if (addr->en_ostat&EN_OERROR) {
- es->es_if.if_oerrors++;
- printf("en%d: output error\n", unit);
- }
if (es->es_ifuba.ifu_xtofree) {
m_freem(es->es_ifuba.ifu_xtofree);
es->es_ifuba.ifu_xtofree = 0;
/*
* Collision on ethernet interface. Do exponential
* backoff, and retransmit. If have backed off all
- * the way printing warning diagnostic, and drop packet.
+ * the way print warning diagnostic, and drop packet.
*/
encollide(unit)
int unit;
{
- register struct en_softc *es = &en_softc[unit];
+ struct en_softc *es = &en_softc[unit];
COUNT(ENCOLLIDE);
es->es_if.if_collisions++;
if (es->es_oactive == 0)
return;
+ endocoll(unit);
+}
+
+endocoll(unit)
+ int unit;
+{
+ register struct en_softc *es = &en_softc[unit];
+
/*
* Es_mask is a 16 bit number with n low zero bits, with
* n the number of backoffs. When es_mask is 0 we have
enstart(unit);
}
-int enprintierrors;
struct sockaddr_pup pupsrc = { AF_PUP };
struct sockaddr_pup pupdst = { AF_PUP };
struct sockproto pupproto = { PF_PUP };
/*
* Purge BDP; drop if input error indicated.
*/
- UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_r.ifrw_bdp);
+ if (es->es_ifuba.ifu_flags & UBA_NEEDBDP)
+ UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_r.ifrw_bdp);
if (addr->en_istat&EN_IERROR) {
es->es_if.if_ierrors++;
- if (enprintierrors)
- printf("en%d: input error\n", unit);
+ if (es->es_if.if_ierrors % 100 == 0)
+ printf("en%d: += 100 input errors\n", unit);
goto setup;
}
#ifdef INET
case ENPUP_IPTYPE:
- len = htons((u_short)endataaddr(en, off ? off+2 : 0, struct ip *)->ip_len);
- if (off)
- len += 2;
+ len = htons((u_short)endataaddr(en,
+ off ? off + sizeof (u_short) : 0, struct ip *)->ip_len);
break;
#endif
#ifdef PUP
case ENPUP_PUPTYPE:
- len = endataaddr(en, off, struct pup_header *)->pup_length;
- if (off)
- len -= 2;
+ len = endataaddr(en, off ? off + sizeof (u_short) : 0,
+ struct pup_header *)->pup_length;
break;
#endif
printf("en%d: unknown pkt type 0x%x\n", unit, en->en_type);
goto setup;
}
+ if (off)
+ len += sizeof (u_short);
if (len == 0)
goto setup;
if (m == 0)
goto setup;
if (off) {
- m->m_off += 2;
- m->m_len -= 2;
+ m->m_off += sizeof (u_short);
+ m->m_len -= sizeof (u_short);
}
switch (en->en_type) {
#ifdef INET
case ENPUP_IPTYPE:
- setipintr();
+ schednetisr(NETISR_IP);
inq = &ipintrq;
break;
#endif
+#ifdef PUP
case ENPUP_PUPTYPE: {
struct pup_header *pup = mtod(m, struct pup_header *);
pupdst.spup_addr = pup->pup_dport;
pupsrc.spup_addr = pup->pup_sport;
raw_input(m, &pupproto, (struct sockaddr *)&pupdst,
- (struct sockaddr *)&pupsrc);
+ (struct sockaddr *)&pupsrc);
goto setup;
- }
}
+#endif
+ }
+
if (IF_QFULL(inq)) {
IF_DROP(inq);
- (void) m_freem(m);
+ m_freem(m);
} else
IF_ENQUEUE(inq, m);
* Use trailer local net encapsulation if enough data in first
* packet leaves a multiple of 512 bytes of data in remainder.
*/
-enoutput(ifp, m0, pf)
+enoutput(ifp, m0, dst)
struct ifnet *ifp;
struct mbuf *m0;
- int pf;
+ struct sockaddr *dst;
{
- int type, dest, s, off;
+ int type, dest, s;
register struct mbuf *m = m0;
register struct en_header *en;
+ register int off;
COUNT(ENOUTPUT);
- switch (pf) {
+ switch (dst->sa_family) {
#ifdef INET
- case PF_INET: {
- register struct ip *ip = mtod(m0, struct ip *);
-
-#ifndef ENKLUDGE
- dest = ip->ip_dst.s_addr >> 24;
-#else
- dest = (ip->ip_dst.s_addr >> 8) & 0xff;
-#endif
- off = ntohs((u_short)ip->ip_len) - m->m_len;
-#ifndef ENKLUDGE
- if (off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2) {
+ case AF_INET:
+ dest = ((struct sockaddr_in *)dst)->sin_addr.s_addr >> 24;
+ off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
+ if (off > 0 && (off & 0x1ff) == 0 &&
+ m->m_off >= MMINOFF + sizeof (u_short)) {
type = ENPUP_TRAIL + (off>>9);
- m->m_off -= 2;
- m->m_len += 2;
+ m->m_off -= sizeof (u_short);
+ m->m_len += sizeof (u_short);
*mtod(m, u_short *) = ENPUP_IPTYPE;
goto gottrailertype;
}
-#endif
type = ENPUP_IPTYPE;
off = 0;
goto gottype;
- }
#endif
#ifdef PUP
- case PF_PUP: {
- register struct pup_header *pup = mtod(m, struct pup_header *);
-
- dest = pup->pup_dhost;
- off = pup->pup_length - m->m_len;
- if (off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2) {
+ case AF_PUP:
+ dest = ((struct sockaddr_pup *)dst)->spup_addr.pp_host;
+ off = mtod(m, struct pup_header *)->pup_length - m->m_len;
+ if (off > 0 && (off & 0x1ff) == 0 &&
+ m->m_off >= MMINOFF + sizeof (u_short)) {
type = ENPUP_TRAIL + (off>>9);
- m->m_off -= 2;
- m->m_len += 2;
+ m->m_off -= sizeof (u_short);
+ m->m_len += sizeof (u_short);
*mtod(m, u_short *) = ENPUP_PUPTYPE;
goto gottrailertype;
}
type = ENPUP_PUPTYPE;
off = 0;
goto gottype;
- }
#endif
default:
- printf("en%d: can't encapsulate pf%d\n", ifp->if_unit, pf);
+ printf("en%d: can't handle af%d\n", ifp->if_unit,
+ dst->sa_family);
m_freem(m0);
return (0);
}
splx(s);
return (1);
}
+
+#if NIMP == 0 && NEN > 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 enlhif;
+int enlhoutput();
+
+/*
+ * Called by localnet interface to allow logical
+ * host interface to "attach". Nothing should ever
+ * be sent locally to this interface, it's purpose
+ * is simply to establish the host's arpanet address.
+ */
+enlhinit(addr)
+ int addr;
+{
+ register struct ifnet *ifp = &enlhif;
+ register struct sockaddr_in *sin;
+
+COUNT(ENLHINIT);
+ ifp->if_name = "lh";
+ ifp->if_mtu = ENMTU;
+ sin = (struct sockaddr_in *)&ifp->if_addr;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = addr;
+ ifp->if_net = sin->sin_addr.s_net;
+ ifp->if_flags = IFF_UP;
+ ifp->if_output = enlhoutput; /* should never be used */
+ if_attach(ifp);
+}
+
+enlhoutput(ifp, m0, dst)
+ struct ifnet *ifp;
+ struct mbuf *m0;
+ struct sockaddr *dst;
+{
+COUNT(ENLHOUTPUT);
+ ifp->if_oerrors++;
+ m_freem(m0);
+ return (0);
+}
+#endif