Return to BSD News archive
Newsgroups: comp.os.386bsd.bugs
Path: sserve!newshost.anu.edu.au!munnari.oz.au!hp9000.csc.cuhk.hk!saimiri.primate.wisc.edu!zaphod.mps.ohio-state.edu!cs.utexas.edu!uunet!email!mbirgmei
From: mbirgmei@email.tuwien.ac.at (Martin BIRGMEIER)
Subject: Patches for if_ec.* to work with BPF
Message-ID: <1993Apr26.071622.3817@email.tuwien.ac.at>
Organization: Technical University of Vienna
Date: Mon, 26 Apr 1993 07:16:22 GMT
Lines: 907
Below are the patches I hacked up to get my 3c503 card to work with the
Berkeley Packet Filter. I have been using them for a while now (since
well before pk 0.2 came along) and they seem to be running fine. To
arrive at them, I simply diffed the old and new versions of if_we*, and
manually applied the resulting changes to if_ec.* (these interfaces are
the same for all practical purposes, the chip being the same as I
understood from the comments in if_ec.c). So basically if_ec.* should
now offer all of the functionality of if_we* (I hope :-)).
Enjoy,
Martin
P.S. One more thing - cut out that silly printf() statement in if_ec.c -
this should have made it into the patchkit a long time ago. I let it
follow as my first diff, thereafter the BPF diff stuff.
============================== cut here ==============================
*** /usr/src/sys.386bsd/i386/isa/if_ec.c.ECINIT_ORIG Sun May 31 00:09:06 1992
--- /usr/src/sys.386bsd/i386/isa/if_ec.c Tue Jan 26 10:15:44 1993
***************
*** 261,267 ****
u_short ax, cx;
Bdry=0;
- printf("ecinit");
/*
* Address not known.
*/
--- 261,266 ----
============================== cut here ==============================
*** /usr/src/sys.386bsd/i386/isa/if_ec.h.BPF_ORIG Mon May 25 12:18:40 1992
--- /usr/src/sys.386bsd/i386/isa/if_ec.h Wed Mar 24 10:12:58 1993
***************
*** 169,177 ****
*/
#define ENRXCR_MON 0x20 /* Monitor mode (no packets rcvd) */
#define ENRXCR_PROMP 0x10 /* Promiscuous phys addresses. */
! #define ENRXCR_MULTI 0x8 /* Multicast (if pass filter) */
! #define ENRXCR_BCST 0x4 /* Accept broadcasts */
! #define ENRXCR_BAD 0x3 /* Accept runts and bad CRC frames */
/*
* Commands for TX control reg
*/
--- 169,179 ----
*/
#define ENRXCR_MON 0x20 /* Monitor mode (no packets rcvd) */
#define ENRXCR_PROMP 0x10 /* Promiscuous phys addresses. */
! #define ENRXCR_MULTI 0x08 /* Multicast (if pass filter) */
! #define ENRXCR_BCST 0x04 /* Accept broadcasts */
! #define ENRXCR_RUNT 0x02 /* Accept runts */
! #define ENRXCR_CRC 0x01 /* Accept bad CRC frames */
! #define ENRXCR_BAD (ENRXCR_RUNT | ENRXCR_CRC)
/*
* Commands for TX control reg
*/
*** /usr/src/sys.386bsd/i386/isa/if_ec.c.BPF_ORIG Mon Mar 22 15:08:26 1993
--- /usr/src/sys.386bsd/i386/isa/if_ec.c Wed Mar 24 10:12:57 1993
***************
*** 64,69 ****
--- 64,73 ----
* repairs this bit after obtaining it's information since I didn't know
* what else within the depths of the kernel would freak out if I left it.
*/
+ /*
+ * BPF filter support added by MB 03/16/93, modeled after the changes
+ * made to if_we.c by Marc Frajola and David Greenman
+ */
#include "param.h"
#include "mbuf.h"
#include "socket.h"
***************
*** 71,76 ****
--- 75,82 ----
#include "errno.h"
#include "syslog.h"
#include "net/if.h"
+ #include "net/if_types.h"
+ #include "net/if_dl.h"
#include "net/netisr.h"
#ifdef INET
#include "netinet/in.h"
***************
*** 85,90 ****
--- 91,103 ----
#endif
#include "i386/isa/isa_device.h"
#include "i386/isa/if_ec.h"
+ #include "bpfilter.h"
+ #if NBPFILTER > 0
+ #include "net/bpf.h"
+ #include "net/bpfdesc.h"
+ #endif /* NBPFILTER > 0 */
+
+ static inline caddr_t ec_ring_copy();
/*
* Ethernet software status per interface.
***************
*** 101,106 ****
--- 114,122 ----
u_char ec_flags; /* software state */
#define EC_RUNNING 0x01
#define EC_TXBUSY 0x02
+ #if NBPFILTER > 0
+ #define EC_ATTACHED 0x80
+ #endif
u_char ec_type; /* interface type code */
u_short ec_vector; /* interrupt vector */
***************
*** 111,122 ****
caddr_t ec_vmem_addr; /* card RAM virtual memory base */
u_long ec_vmem_size; /* card RAM bytes */
caddr_t ec_vmem_ring; /* receive ring RAM vaddress */
! caddr_t ec_vmem_end; /* receive ring RAM end */
} ec_softc[NEC];
! #define PAGE0 outb(sc->ec_io_nic_addr + EN_CCMD, ENC_NODMA|ENC_PAGE0);
! #define PAGE1 outb(sc->ec_io_nic_addr + EN_CCMD, ENC_NODMA|ENC_PAGE1);
! static Bdry;
int ether_output(),
ecprobe(),
--- 127,141 ----
caddr_t ec_vmem_addr; /* card RAM virtual memory base */
u_long ec_vmem_size; /* card RAM bytes */
caddr_t ec_vmem_ring; /* receive ring RAM vaddress */
! caddr_t ec_vmem_end; /* receive ring RAM end */
! #if NBPFILTER > 0
! caddr_t ec_bpf; /* Magic Cookie for BPF */
! #endif
} ec_softc[NEC];
! #define PAGE0 { outb(sc->ec_io_nic_addr + EN_CCMD, ENC_NODMA|ENC_PAGE0); }
! #define PAGE1 { outb(sc->ec_io_nic_addr + EN_CCMD, ENC_NODMA|ENC_PAGE1); }
! static Bdry[NEC];
int ether_output(),
ecprobe(),
***************
*** 166,172 ****
* Stop the chip just in case.
*/
DELAY(1000);
! PAGE0
outb(sc->ec_io_nic_addr + EN_CCMD, ENC_NODMA|ENC_STOP);
DELAY(1000);
--- 185,191 ----
* Stop the chip just in case.
*/
DELAY(1000);
! PAGE0;
outb(sc->ec_io_nic_addr + EN_CCMD, ENC_NODMA|ENC_STOP);
DELAY(1000);
***************
*** 198,203 ****
--- 217,224 ----
{
register struct ec_softc *sc = &ec_softc[is->id_unit];
register struct ifnet *ifp = &sc->ec_if;
+ struct ifaddr *ifa;
+ struct sockaddr_dl *sdl;
/**
** Initialize the ASIC in same order as Clarkson driver.
***************
*** 247,252 ****
--- 268,293 ----
*/
if_attach(ifp);
/*
+ * Search down the ifa address list looking for the AF_LINK type entry
+ */
+ ifa = ifp->if_addrlist;
+ while ((ifa != 0) && (ifa->ifa_addr != 0) &&
+ (ifa->ifa_addr->sa_family != AF_LINK))
+ ifa = ifa->ifa_next;
+ /*
+ * If we found an AF_LINK type entry, we fill in the hardware (link level) addr
+ */
+ if ((ifa != 0) && (ifa->ifa_addr != 0)) {
+ sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+ sdl->sdl_type = IFT_ETHER;
+ sdl->sdl_alen = ETHER_ADDR_LEN;
+ sdl->sdl_slen = 0;
+ bcopy(sc->ec_addr, LLADDR(sdl), ETHER_ADDR_LEN);
+ }
+ #if NBPFILTER > 0
+ sc->ec_flags &= ~EC_ATTACHED; /* Make sure BPF attach flag clear */
+ #endif
+ /*
* Weeee.. We get to tell people we exist...
*/
printf(" address %s", ether_sprintf(sc->ec_addr));
***************
*** 260,266 ****
int i, s;
u_short ax, cx;
! Bdry=0;
/*
* Address not known.
*/
--- 301,316 ----
int i, s;
u_short ax, cx;
! Bdry[unit] = 0;
!
! #if NBPFILTER > 0
! if ((sc->ec_flags & EC_ATTACHED) == 0) {
! bpfattach(&sc->ec_bpf, ifp, DLT_EN10MB,
! sizeof(struct ether_header));
! sc->ec_flags |= EC_ATTACHED;
! }
! #endif /* NBPFILTER > 0 */
!
/*
* Address not known.
*/
***************
*** 281,287 ****
* (Use sequence recommended by 3Com. )
*/
s=splhigh();
! PAGE0
outb(sc->ec_io_nic_addr + EN_CCMD, ENC_NODMA|ENC_PAGE0|ENC_STOP);
outb(sc->ec_io_nic_addr + EN0_DCFG, ENDCFG_BM8);
outb(sc->ec_io_nic_addr + EN0_RCNTLO, 0x0);
--- 331,337 ----
* (Use sequence recommended by 3Com. )
*/
s=splhigh();
! PAGE0;
outb(sc->ec_io_nic_addr + EN_CCMD, ENC_NODMA|ENC_PAGE0|ENC_STOP);
outb(sc->ec_io_nic_addr + EN0_DCFG, ENDCFG_BM8);
outb(sc->ec_io_nic_addr + EN0_RCNTLO, 0x0);
***************
*** 297,303 ****
/*
* Copy Ethernet address from SA_PROM into 8390 chip registers.
*/
! PAGE1
for(i=0;i<6;i++)
outb(sc->ec_io_nic_addr + EN1_PHYS+i, sc->ec_addr[i]);
/*
--- 347,353 ----
/*
* Copy Ethernet address from SA_PROM into 8390 chip registers.
*/
! PAGE1;
for(i=0;i<6;i++)
outb(sc->ec_io_nic_addr + EN1_PHYS+i, sc->ec_addr[i]);
/*
***************
*** 317,322 ****
--- 367,378 ----
outb(sc->ec_io_nic_addr + EN_CCMD, ENC_START|ENC_PAGE0|ENC_NODMA);
outb(sc->ec_io_nic_addr + EN0_ISR, 0xff);
outb(sc->ec_io_nic_addr + EN0_TXCR, 0x0);
+ #if NBPFILTER > 0
+ if (sc->ec_if.if_flags & IFF_PROMISC)
+ outb(sc->ec_io_nic_addr + EN0_RXCR,
+ ENRXCR_BAD | ENRXCR_PROMP | ENRXCR_BCST);
+ else
+ #endif
outb(sc->ec_io_nic_addr + EN0_RXCR, ENRXCR_BCST);
/*
* Take interface out of reset, program the vector,
***************
*** 357,362 ****
--- 413,481 ----
sc->ec_flags |= EC_TXBUSY;
(void) splx(s);
+ #if NBPFILTER > 0
+ if (sc->ec_bpf) {
+ u_short etype;
+ int off, datasize, resid;
+ struct ether_header *eh;
+ struct trailer_header {
+ u_short ether_type;
+ u_short ether_residual;
+ } trailer_header;
+ char ether_packet[ETHERMTU+100];
+ char *ep;
+
+ ep = ether_packet;
+
+ /*
+ * We handle trailers below:
+ * Copy ether header first, then residual data,
+ * then data. Put all this in a temporary buffer
+ * 'ether_packet' and send off to bpf. Since the
+ * system has generated this packet, we assume
+ * that all of the offsets in the packet are
+ * correct; if they're not, the system will almost
+ * certainly crash in m_copydata.
+ * We make no assumptions about how the data is
+ * arranged in the mbuf chain (i.e. how much
+ * data is in each mbuf, if mbuf clusters are
+ * used, etc.), which is why we use m_copydata
+ * to get the ether header rather than assume
+ * that this is located in the first mbuf.
+ */
+ /* copy ether header */
+ m_copydata(m, 0, sizeof(struct ether_header), ep);
+ eh = (struct ether_header *) ep;
+ ep += sizeof(struct ether_header);
+ etype = ntohs(eh->ether_type);
+ if (etype >= ETHERTYPE_TRAIL &&
+ etype < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
+ datasize = ((etype - ETHERTYPE_TRAIL) << 9);
+ off = datasize + sizeof(struct ether_header);
+
+ /* copy trailer_header into a data structure */
+ m_copydata(m, off, sizeof(struct trailer_header),
+ &trailer_header.ether_type);
+
+ /* copy residual data */
+ m_copydata(m, off+sizeof(struct trailer_header),
+ resid = ntohs(trailer_header.ether_residual) -
+ sizeof(struct trailer_header), ep);
+ ep += resid;
+
+ /* copy data */
+ m_copydata(m, sizeof(struct ether_header), datasize, ep);
+ ep += datasize;
+
+ /* restore original ether packet type */
+ eh->ether_type = trailer_header.ether_type;
+
+ bpf_tap(sc->ec_bpf, ether_packet, ep - ether_packet);
+ } else
+ bpf_mtap(sc->ec_bpf, m);
+ }
+ #endif /* NBPFILTER > 0 */
+
/*
* Copy the mbuf chain into the transmit buffer
*/
***************
*** 375,385 ****
*/
s=splhigh();
len = MAX(len, ETHER_MIN_LEN);
! PAGE0
outb(sc->ec_io_nic_addr + EN0_TCNTLO, len & 0xff);
outb(sc->ec_io_nic_addr + EN0_TCNTHI, len >> 8);
ec_cmd_reg = inb(sc->ec_io_nic_addr + EN_CCMD);
outb(sc->ec_io_nic_addr + EN_CCMD, ec_cmd_reg|ENC_TRANS);
(void) splx(s);
}
--- 494,505 ----
*/
s=splhigh();
len = MAX(len, ETHER_MIN_LEN);
! PAGE0;
outb(sc->ec_io_nic_addr + EN0_TCNTLO, len & 0xff);
outb(sc->ec_io_nic_addr + EN0_TCNTHI, len >> 8);
ec_cmd_reg = inb(sc->ec_io_nic_addr + EN_CCMD);
outb(sc->ec_io_nic_addr + EN_CCMD, ec_cmd_reg|ENC_TRANS);
+ sc->ec_if.if_timer = 3;
(void) splx(s);
}
***************
*** 399,405 ****
* Turn off interrupts while we take care of things.
*/
ec_cmd_reg = inb(sc->ec_io_nic_addr + EN_CCMD);
! PAGE0
ec_sts_reg = inb(sc->ec_io_nic_addr + EN0_ISR);
outb(sc->ec_io_nic_addr + EN0_IMR, 0x0);
loop:
--- 519,525 ----
* Turn off interrupts while we take care of things.
*/
ec_cmd_reg = inb(sc->ec_io_nic_addr + EN_CCMD);
! PAGE0;
ec_sts_reg = inb(sc->ec_io_nic_addr + EN0_ISR);
outb(sc->ec_io_nic_addr + EN0_IMR, 0x0);
loop:
***************
*** 445,451 ****
/*
* Reenable onboard interrupts.
*/
! /*PAGE0*/
outb(sc->ec_io_nic_addr + EN_CCMD, ec_cmd_reg);
outb(sc->ec_io_nic_addr + EN0_IMR, 0x3f);
if(ec_sts_reg=inb(sc->ec_io_nic_addr + EN0_ISR))
--- 565,571 ----
/*
* Reenable onboard interrupts.
*/
! /*PAGE0;*/
outb(sc->ec_io_nic_addr + EN_CCMD, ec_cmd_reg);
outb(sc->ec_io_nic_addr + EN0_IMR, 0x3f);
if(ec_sts_reg=inb(sc->ec_io_nic_addr + EN0_ISR))
***************
*** 462,468 ****
/*
* Do some statistics.
*/
! PAGE0
sc->ec_flags &= ~EC_TXBUSY;
sc->ec_if.if_timer = 0;
++sc->ec_if.if_opackets;
--- 582,588 ----
/*
* Do some statistics.
*/
! PAGE0;
sc->ec_flags &= ~EC_TXBUSY;
sc->ec_if.if_timer = 0;
++sc->ec_if.if_opackets;
***************
*** 485,496 ****
* Traverse the receive ring looking for packets to pass back.
* The search is complete when we find a descriptor not in use.
*/
! PAGE0
bnry = inb(sc->ec_io_nic_addr + EN0_BOUNDARY);
! PAGE1
curr = inb(sc->ec_io_nic_addr + EN1_CURPAG);
! if(Bdry)
! bnry =Bdry;
while (bnry != curr)
{
--- 605,616 ----
* Traverse the receive ring looking for packets to pass back.
* The search is complete when we find a descriptor not in use.
*/
! PAGE0;
bnry = inb(sc->ec_io_nic_addr + EN0_BOUNDARY);
! PAGE1;
curr = inb(sc->ec_io_nic_addr + EN1_CURPAG);
! if(Bdry[unit])
! bnry = Bdry[unit];
while (bnry != curr)
{
***************
*** 499,509 ****
/* count includes CRC */
len = ecr->ec_count - 4;
! /*if (len > 30 && len <= ETHERMTU+100) */
ecread(sc, (caddr_t)(ecr + 1), len);
! /*else printf("reject:%x bnry:%x curr:%x", len, bnry, curr);*/
outofbufs:
! PAGE0
/* advance on chip Boundry register */
if((caddr_t) ecr + EC_PAGE_SIZE - 1 > sc->ec_vmem_end) {
bnry = EC_RXBUF_OFFSET;
--- 619,630 ----
/* count includes CRC */
len = ecr->ec_count - 4;
! if (len > 30 && len <= ETHERMTU+100)
ecread(sc, (caddr_t)(ecr + 1), len);
! else
! printf("ec%d: reject - bad length %d\n", unit, len);
outofbufs:
! PAGE0;
/* advance on chip Boundry register */
if((caddr_t) ecr + EC_PAGE_SIZE - 1 > sc->ec_vmem_end) {
bnry = EC_RXBUF_OFFSET;
***************
*** 524,541 ****
}
/* refresh our copy of CURR */
! PAGE1
curr = inb(sc->ec_io_nic_addr + EN1_CURPAG);
}
! Bdry = bnry;
! PAGE0
}
! #define ecdataaddr(sc, eh, off, type) \
! ((type) ((caddr_t)((eh)+1)+(off) >= (sc)->ec_vmem_end) ? \
! (((caddr_t)((eh)+1)+(off))) - (sc)->ec_vmem_end \
+ (sc)->ec_vmem_ring: \
! ((caddr_t)((eh)+1)+(off)))
ecread(sc, buf, len)
register struct ec_softc *sc;
--- 645,662 ----
}
/* refresh our copy of CURR */
! PAGE1;
curr = inb(sc->ec_io_nic_addr + EN1_CURPAG);
}
! Bdry[unit] = bnry;
! PAGE0;
}
! #define ringoffset(sc, eh, off, type) \
! ((type) (((caddr_t)(eh)+(off) >= (sc)->ec_vmem_end) ? \
! (((caddr_t)(eh)+(off))) - (sc)->ec_vmem_end \
+ (sc)->ec_vmem_ring: \
! ((caddr_t)(eh)+(off))))
ecread(sc, buf, len)
register struct ec_softc *sc;
***************
*** 542,581 ****
char *buf;
int len;
{
! register struct ether_header *eh;
! struct mbuf *m, *ecget();
int off, resid;
! /*
! * 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.
! */
eh = (struct ether_header *)buf;
! eh->ether_type = ntohs((u_short)eh->ether_type);
! if (eh->ether_type >= ETHERTYPE_TRAIL &&
! eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
! off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
! if (off >= ETHERMTU) return; /* sanity */
! eh->ether_type = ntohs(*ecdataaddr(sc, eh, off, u_short *));
! resid = ntohs(*(ecdataaddr(sc, eh, off+2, u_short *)));
! if (off + resid > len) return; /* sanity */
! len = off + resid;
! } else off = 0;
len -= sizeof(struct ether_header);
! if (len <= 0) return;
/*
! * Pull packet off interface. Off is nonzero if packet
! * has trailing header; neget 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.
*/
! m = ecget(buf, len, off, &sc->ec_if, sc);
! if (m == 0) return;
! ether_input(&sc->ec_if, eh, m);
}
ec_ioctl(ifp, cmd, data)
register struct ifnet *ifp;
int cmd;
--- 663,791 ----
char *buf;
int len;
{
! struct ether_header *eh;
! struct mbuf *m, *head, *ec_ring_to_mbuf();
int off, resid;
+ u_short etype;
+ struct trailer_header {
+ u_short trail_type;
+ u_short trail_residual;
+ } trailer_header;
! ++sc->ec_if.if_ipackets;
!
! /* Allocate a header mbuf */
! MGETHDR(m, M_DONTWAIT, MT_DATA);
! if (m == 0)
! goto bad;
! m->m_pkthdr.rcvif = &sc->ec_if;
! m->m_pkthdr.len = len;
! m->m_len = 0;
! head = m;
!
eh = (struct ether_header *)buf;
!
! #define EROUND ((sizeof(struct ether_header) + 3) & ~3)
! #define EOFF (EROUND - sizeof(struct ether_header))
+ /*
+ * The following assumes there is room for
+ * the ether header in the header mbuf
+ */
+ head->m_data += EOFF;
+ bcopy(buf, mtod(head, caddr_t), sizeof(struct ether_header));
+ buf += sizeof(struct ether_header);
+ head->m_len += sizeof(struct ether_header);
len -= sizeof(struct ether_header);
!
! etype = ntohs((u_short) eh->ether_type);
!
! /*
! * Deal with trailer protocol:
! * If trailer protocol, calculate the datasize as 'off',
! * which is also the offset to the trailer header.
! * Set resid to the amount of packet data following the
! * trailer header.
! * Finally, copy residual data into mbuf chain.
! */
! if (etype >= ETHERTYPE_TRAIL &&
! etype < ETHERTYPE_TRAIL + ETHERTYPE_NTRAILER) {
!
! off = (etype - ETHERTYPE_TRAIL) << 9;
! if ((off + sizeof(struct trailer_header)) > len)
! goto bad; /* insanity */
!
! eh->ether_type = *ringoffset(sc, buf, off, u_short *);
! resid = ntohs(*ringoffset(sc, buf, off+2, u_short *));
!
! if ((off + resid) > len)
! goto bad; /* insanity */
!
! resid -= sizeof(struct trailer_header);
! if (resid < 0)
! goto bad; /* insanity */
!
! m = ec_ring_to_mbuf(sc,
! ringoffset(sc, buf, off+4, char *), head, resid);
! if (m == 0)
! goto bad;
!
! len = off;
! head->m_pkthdr.len -= 4; /* subtract trailer header */
! }
!
! /*
! * Pull packet off interface. Or if this was a trailer packet,
! * the data portion is appended.
! */
! m = ec_ring_to_mbuf(sc, buf, m, len);
! if (m == 0)
! goto bad;
!
! #if NBPFILTER > 0
! /*
! * Check if there's a bpf filter listening on this interface.
! * If so, hand off the raw packet to bpf.
! */
! if (sc->ec_bpf) {
! bpf_mtap(sc->ec_bpf, head);
! }
!
! /*
! * Note that the interface cannot be in promiscuous mode if
! * there are no bpf listeners. And if we are in promiscuous
! * mode, we have to check if this packet is really ours.
! *
! * XXX This test does not support multicasts.
! */
! if ((sc->ec_if.if_flags & IFF_PROMISC) &&
! bcmp(eh->ether_dhost, sc->ec_addr, sizeof(eh->ether_dhost)) != 0 &&
! bcmp(eh->ether_dhost, etherbroadcastaddr,
! sizeof(eh->ether_dhost)) != 0) {
! m_freem(head);
! return;
! }
! #endif
!
! /*
! * Fix up data start offset in mbuf to point past ether header
! */
! m_adj(head, sizeof(struct ether_header));
/*
! * silly ether_input routine needs 'type' in host byte order
*/
! eh->ether_type = ntohs(eh->ether_type);
!
! ether_input(&sc->ec_if, eh, head);
! return;
!
! bad:
! if (head)
! m_freem(head);
! return;
}
+
ec_ioctl(ifp, cmd, data)
register struct ifnet *ifp;
int cmd;
***************
*** 632,637 ****
--- 842,854 ----
} else if (ifp->if_flags & IFF_UP &&
(ifp->if_flags & IFF_RUNNING) == 0)
ec_init(ifp->if_unit);
+ #if NBPFILTER > 0
+ if (sc->ec_if.if_flags & IFF_PROMISC)
+ outb(sc->ec_io_nic_addr + EN0_RXCR,
+ ENRXCR_BAD | ENRXCR_PROMP | ENRXCR_BCST);
+ else
+ #endif /* NBPFILTER > 0 */
+ outb(sc->ec_io_nic_addr + EN0_RXCR, ENRXCR_BCST);
break;
#ifdef notdef
***************
*** 660,668 ****
--- 877,889 ----
ec_watchdog(unit)
int unit;
{
+ #if 1
+ ecintr(unit);
+ #else
log(LOG_WARNING, "ec%d: soft reset\n", unit);
ec_stop(unit);
ec_init(unit);
+ #endif
}
ec_stop(unit)
***************
*** 672,678 ****
int s;
s=splimp();
! PAGE0
outb(sc->ec_io_nic_addr + EN_CCMD, ENC_NODMA|ENC_STOP);
outb(sc->ec_io_nic_addr + EN0_IMR, 0x0);
sc->ec_flags &= ~EC_RUNNING;
--- 893,899 ----
int s;
s=splimp();
! PAGE0;
outb(sc->ec_io_nic_addr + EN_CCMD, ENC_NODMA|ENC_STOP);
outb(sc->ec_io_nic_addr + EN0_IMR, 0x0);
sc->ec_flags &= ~EC_RUNNING;
***************
*** 683,776 ****
}
/*
! * Pull read data off a interface.
! * Len is length of data, with local net header stripped.
! * Off is non-zero if a trailer protocol was used, and
! * gives the offset of the trailer information.
! * We copy the trailer information and then all the normal
! * data into mbufs. When full cluster sized units are present
! * we copy into clusters.
*/
struct mbuf *
! ecget(buf, totlen, off0, ifp, sc)
! caddr_t buf;
! int totlen, off0;
! struct ifnet *ifp;
struct ec_softc *sc;
{
! struct mbuf *top, **mp, *m, *p;
! int off = off0, len;
! register caddr_t cp = buf;
! char *epkt;
! int tc =totlen;
! buf += sizeof(struct ether_header);
! cp = buf;
! epkt = cp + totlen;
!
! if (off) {
! cp += off + 2 * sizeof(u_short);
! totlen -= 2 * sizeof(u_short);
! }
! 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;
!
! top = 0;
! mp = ⊤
! while (totlen > 0) {
! if (top) {
MGET(m, M_DONTWAIT, MT_DATA);
! if (m == 0) {
! m_freem(top);
return (0);
! }
! m->m_len = MLEN;
! }
! len = min(totlen, epkt - cp);
! if (len >= MINCLSIZE) {
MCLGET(m, M_DONTWAIT);
- if (m->m_flags & M_EXT)
- m->m_len = len = min(len, MCLBYTES);
- else
- len = m->m_len;
- } else {
- /*
- * Place initial small packet/header at end of mbuf.
- */
- 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;
- }
! totlen -= len;
! /* only do up to end of buffer */
! if (cp+len > sc->ec_vmem_end) {
! unsigned toend = sc->ec_vmem_end - cp;
!
! bcopy(cp, mtod(m, caddr_t), toend);
! cp = sc->ec_vmem_ring;
! bcopy(cp, mtod(m, caddr_t)+toend, len - toend);
! cp += len - toend;
! epkt = cp + totlen;
! } else {
! bcopy(cp, mtod(m, caddr_t), (unsigned)len);
! cp += len;
}
! *mp = m;
! mp = &m->m_next;
! if (cp == epkt) {
! cp = buf;
! epkt = cp + tc;
}
}
! return (top);
}
#endif /* NEC > 0 */
--- 904,978 ----
}
/*
! * Copy data from receive buffer to end of mbuf chain
! * allocate additional mbufs as needed. return pointer
! * to last mbuf in chain.
! * sc = ec info
! * src = pointer in ec ring buffer
! * dst = pointer to last mbuf in mbuf chain to copy to
! * amount = amount of data to copy
*/
struct mbuf *
! ec_ring_to_mbuf(sc,src,dst,total_len)
struct ec_softc *sc;
+ char *src;
+ struct mbuf *dst;
+ int total_len;
{
! register struct mbuf *m = dst;
! while (total_len > 0) {
! register int amount = min(total_len, M_TRAILINGSPACE(m));
! if (amount == 0) { /* no more data in this mbuf, alloc another */
! /*
! * if there is enough data for an mbuf cluster, attempt
! * to allocate one of those, otherwise, a regular mbuf
! * will do.
! */
! dst = m;
MGET(m, M_DONTWAIT, MT_DATA);
! if (m == 0)
return (0);
!
! if (total_len >= MINCLSIZE)
MCLGET(m, M_DONTWAIT);
! m->m_len = 0;
! dst->m_next = m;
! amount = min(total_len, M_TRAILINGSPACE(m));
}
!
! src = ec_ring_copy(sc, src, mtod(m, caddr_t) + m->m_len, amount);
!
! m->m_len += amount;
! total_len -= amount;
!
}
+ return (m);
+ }
+
+ static inline char *
+ ec_ring_copy(sc,src,dst,amount)
+ struct ec_softc *sc;
+ char *src;
+ char *dst;
+ int amount;
+ {
+ int tmp_amount;
+
+ /* does copy wrap to lower addr in ring buffer? */
+ if (src + amount > sc->ec_vmem_end) {
+ tmp_amount = sc->ec_vmem_end - src;
+ bcopy(src,dst,tmp_amount); /* copy amount up to end */
+ amount -= tmp_amount;
+ src = sc->ec_vmem_ring;
+ dst += tmp_amount;
}
!
! bcopy(src, dst, amount);
!
! return(src + amount);
}
#endif /* NEC > 0 */
+
============================== cut here ==============================