Push the copying of the output buffer further down, with the intent of

eliminating it and outputting the mbufs directly.  Make sure the queue drains
even if packets are not failing to transmit.
This commit is contained in:
mycroft 1995-07-23 20:27:48 +00:00
parent 4525afdaeb
commit 6bc1cc31f8
1 changed files with 41 additions and 44 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_eg.c,v 1.14 1995/07/23 19:45:42 mycroft Exp $ */
/* $NetBSD: if_eg.c,v 1.15 1995/07/23 20:27:48 mycroft Exp $ */
/*
* Copyright (c) 1993 Dean Huxley <dean@fsa.ca>
@ -108,7 +108,7 @@ struct eg_softc {
u_char eg_pcb[64]; /* Primary Command Block buffer */
u_char eg_incount; /* Number of buffers currently used */
u_char *eg_inbuf; /* Incoming packet buffer */
u_char *eg_outbuf; /* Outgoing packet buffer */
u_char *eg_outbuf; /* Outgoing packet buffer */
};
int egprobe __P((struct device *, void *, void *));
@ -443,7 +443,7 @@ eginit(sc)
if (sc->eg_outbuf == NULL)
sc->eg_outbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT);
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
@ -465,8 +465,8 @@ egrecv(sc)
sc->eg_pcb[3] = 0;
sc->eg_pcb[4] = 0;
sc->eg_pcb[5] = 0;
sc->eg_pcb[6] = EG_BUFLEN & 0xff; /* our buffer size */
sc->eg_pcb[7] = (EG_BUFLEN >> 8) & 0xff;
sc->eg_pcb[6] = EG_BUFLEN; /* our buffer size */
sc->eg_pcb[7] = EG_BUFLEN >> 8;
sc->eg_pcb[8] = 0; /* timeout, 0 == none */
sc->eg_pcb[9] = 0;
if (egwritePCB(sc) == 0)
@ -482,43 +482,31 @@ egstart(ifp)
{
register struct eg_softc *sc = egcd.cd_devs[ifp->if_unit];
struct mbuf *m0, *m;
caddr_t buffer;
int len;
short *ptr;
u_short *ptr;
/* Don't transmit if interface is busy or not running */
if ((sc->sc_arpcom.ac_if.if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
return;
loop:
/* Dequeue the next datagram. */
IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m0);
if (m0 == NULL)
IF_DEQUEUE(&ifp->if_snd, m0);
if (m0 == 0)
return;
sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE;
ifp->if_flags |= IFF_OACTIVE;
/* We need to use m->m_pkthdr.len, so require the header */
if ((m0->m_flags & M_PKTHDR) == 0)
panic("ed_start: no header mbuf");
len = max(m0->m_pkthdr.len, ETHER_MIN_LEN);
/* Copy the datagram to the buffer. */
len = 0;
for (m = m0; m; m = m->m_next) {
if (m->m_len == 0)
continue;
if (len + m->m_len > EG_BUFLEN) {
dprintf(("Packet too large to send\n"));
m_freem(m0);
sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
sc->sc_arpcom.ac_if.if_oerrors++;
return;
}
bcopy(mtod(m, caddr_t), sc->eg_outbuf + len, m->m_len);
len += m->m_len;
}
#if NBPFILTER > 0
if (sc->sc_arpcom.ac_if.if_bpf)
bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m0);
if (ifp->if_bpf)
bpf_mtap(ifp->if_bpf, m0);
#endif
m_freem(m0);
/* length must be a minimum of ETHER_MIN_LEN bytes */
len = max(len, ETHER_MIN_LEN);
/* set direction bit: host -> adapter */
outb(sc->eg_ctl, inb(sc->eg_ctl) & ~EG_CTL_DIR);
@ -529,19 +517,28 @@ egstart(ifp)
sc->eg_pcb[3] = 0;
sc->eg_pcb[4] = 0;
sc->eg_pcb[5] = 0;
sc->eg_pcb[6] = len & 0xff; /* length of packet */
sc->eg_pcb[7] = (len >> 8) & 0xff;
if (egwritePCB(sc) == 0) {
for (ptr = (short *) sc->eg_outbuf; len > 0; len -= 2) {
outw(sc->eg_data, *ptr++);
while (!(inb(sc->eg_stat) & EG_STAT_HRDY))
; /* XXX need timeout here */
}
} else {
sc->eg_pcb[6] = len; /* length of packet */
sc->eg_pcb[7] = len >> 8;
if (egwritePCB(sc) != 0) {
dprintf(("egwritePCB in egstart failed\n"));
sc->sc_arpcom.ac_if.if_oerrors++;
sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
ifp->if_oerrors++;
ifp->if_flags &= ~IFF_OACTIVE;
goto loop;
}
buffer = sc->eg_outbuf;
for (m = m0; m != 0; m = m->m_next) {
bcopy(mtod(m, caddr_t), buffer, m->m_len);
buffer += m->m_len;
}
for (ptr = (u_short *) sc->eg_outbuf; len > 0; len -= 2) {
outw(sc->eg_data, *ptr++);
while (!(inb(sc->eg_stat) & EG_STAT_HRDY))
; /* XXX need timeout here */
}
m_freem(m0);
/* Set direction bit : Adapter -> host */
outb(sc->eg_ctl, inb(sc->eg_ctl) | EG_CTL_DIR);
@ -553,14 +550,14 @@ egintr(arg)
{
register struct eg_softc *sc = arg;
int i, len;
short *ptr;
u_short *ptr;
while (inb(sc->eg_stat) & EG_STAT_ACRF) {
egreadPCB(sc);
switch (sc->eg_pcb[0]) {
case EG_RSP_RECVPACKET:
len = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8);
for (ptr = (short *) sc->eg_inbuf; len > 0; len -= 2) {
for (ptr = (u_short *) sc->eg_inbuf; len > 0; len -= 2) {
while (!(inb(sc->eg_stat) & EG_STAT_HRDY))
;
*ptr++ = inw(sc->eg_data);