Fix a transmit bug and get a little more out from the receive logic.
This commit is contained in:
parent
f7d6ee345c
commit
944b6966e9
|
@ -1,4 +1,5 @@
|
|||
/* $NetBSD: if_de.c,v 1.4 2000/06/05 00:09:18 matt Exp $ */
|
||||
/* $NetBSD: if_de.c,v 1.5 2000/06/08 19:58:49 ragge Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989 Regents of the University of California.
|
||||
* Copyright (c) 2000 Ludd, University of Lule}, Sweden.
|
||||
|
@ -49,7 +50,6 @@
|
|||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_iso.h"
|
||||
#include "bpfilter.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
|
@ -127,16 +127,12 @@ struct de_softc {
|
|||
bus_dmamap_t sc_cmap;
|
||||
struct de_cdata *sc_dedata; /* Control structure */
|
||||
struct de_cdata *sc_pdedata; /* Bus-mapped control structure */
|
||||
#ifdef notdef
|
||||
bus_dmamap_t sc_xmtmap[NXMT]; /* unibus xmit maps */
|
||||
struct mbuf *sc_txmbuf[NXMT];
|
||||
#endif
|
||||
bus_dmamap_t sc_rcvmap[NRCV]; /* unibus receive maps */
|
||||
struct mbuf *sc_rxmbuf[NRCV];
|
||||
int sc_nexttx; /* next tx descriptor to put data on */
|
||||
int sc_nextrx; /* next rx descriptor for recv */
|
||||
int sc_inq; /* # if xmit packets in queue */
|
||||
int sc_lastack; /* Last handled rx descriptor */
|
||||
int sc_xindex; /* UNA index into transmit chain */
|
||||
int sc_rindex; /* UNA index into receive chain */
|
||||
int sc_xfree; /* index for next transmit buffer */
|
||||
int sc_nxmit; /* # of transmits in progress */
|
||||
void *sc_sh; /* shutdownhook cookie */
|
||||
};
|
||||
|
||||
|
@ -148,10 +144,8 @@ static int deioctl(struct ifnet *, u_long, caddr_t);
|
|||
static void dereset(struct device *);
|
||||
static void destart(struct ifnet *);
|
||||
static void derecv(struct de_softc *);
|
||||
static void dexmit(struct de_softc *);
|
||||
static void deintr(void *);
|
||||
static int de_add_rxbuf(struct de_softc *, int);
|
||||
static void desetup(struct de_softc *sc);
|
||||
static void deshutdown(void *);
|
||||
|
||||
struct cfattach de_ca = {
|
||||
|
@ -244,23 +238,6 @@ deattach(struct device *parent, struct device *self, void *aux)
|
|||
bzero(sc->sc_dedata, sizeof(struct de_cdata));
|
||||
sc->sc_pdedata = (struct de_cdata *)sc->sc_cmap->dm_segs[0].ds_addr;
|
||||
|
||||
#ifdef notdef
|
||||
/*
|
||||
* Create the transmit descriptor DMA maps.
|
||||
*
|
||||
* XXX - should allocate transmit map pages when needed, not here.
|
||||
*/
|
||||
for (i = 0; i < NXMT; i++) {
|
||||
if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
|
||||
MCLBYTES, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
|
||||
&sc->sc_xmtmap[i]))) {
|
||||
printf(": unable to create tx DMA map %d, error = %d\n",
|
||||
i, error);
|
||||
goto fail_4;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Create receive buffer DMA maps.
|
||||
*/
|
||||
|
@ -301,15 +278,15 @@ deattach(struct device *parent, struct device *self, void *aux)
|
|||
printf("\n%s: %s, hardware address %s\n", sc->sc_dev.dv_xname, c,
|
||||
ether_sprintf(myaddr));
|
||||
|
||||
uba_intr_establish(ua->ua_icookie, ua->ua_cvec, deintr,
|
||||
sc, &sc->sc_intrcnt);
|
||||
uba_intr_establish(ua->ua_icookie, ua->ua_cvec, deintr, sc,
|
||||
&sc->sc_intrcnt);
|
||||
uba_reset_establish(dereset, &sc->sc_dev);
|
||||
evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt,
|
||||
sc->sc_dev.dv_xname, "intr");
|
||||
sc->sc_dev.dv_xname, "intr");
|
||||
|
||||
strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
|
||||
ifp->if_softc = sc;
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX;
|
||||
ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI;
|
||||
ifp->if_ioctl = deioctl;
|
||||
ifp->if_start = destart;
|
||||
if_attach(ifp);
|
||||
|
@ -336,14 +313,7 @@ fail_5:
|
|||
if (sc->sc_rcvmap[i] != NULL)
|
||||
bus_dmamap_destroy(sc->sc_dmat, sc->sc_rcvmap[i]);
|
||||
}
|
||||
#ifdef notdef
|
||||
fail_4:
|
||||
for (i = 0; i < NXMT; i++) {
|
||||
if (sc->sc_xmtmap[i] != NULL)
|
||||
bus_dmamap_destroy(sc->sc_dmat, sc->sc_xmtmap[i]);
|
||||
}
|
||||
bus_dmamap_unload(sc->sc_dmat, sc->sc_cmap);
|
||||
#endif
|
||||
|
||||
fail_3:
|
||||
bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmap);
|
||||
fail_2:
|
||||
|
@ -364,6 +334,7 @@ dereset(struct device *dev)
|
|||
struct de_softc *sc = (void *)dev;
|
||||
|
||||
sc->sc_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
|
||||
sc->sc_pdedata = NULL; /* All mappings lost */
|
||||
DE_WCSR(DE_PCSR0, PCSR0_RSET);
|
||||
dewait(sc, "reset");
|
||||
deinit(sc);
|
||||
|
@ -410,9 +381,12 @@ deinit(struct de_softc *sc)
|
|||
DE_WLOW(CMD_GETCMD);
|
||||
dewait(sc, "wtring");
|
||||
|
||||
desetup(sc);
|
||||
sc->sc_dedata->dc_pcbb.pcbb0 = FC_WTMODE;
|
||||
sc->sc_dedata->dc_pcbb.pcbb2 = MOD_TPAD|MOD_HDX|MOD_DRDC|MOD_ENAL;
|
||||
DE_WLOW(CMD_GETCMD);
|
||||
dewait(sc, "wtmode");
|
||||
|
||||
/* Link the transmit buffers to the descriptors */
|
||||
/* set up the receive and transmit ring entries */
|
||||
for (i = 0; i < NXMT; i++) {
|
||||
dc->dc_xrent[i].r_flags = 0;
|
||||
dc->dc_xrent[i].r_segbl = LOWORD(&pdc->dc_xbuf[i][0]);
|
||||
|
@ -421,17 +395,14 @@ deinit(struct de_softc *sc)
|
|||
|
||||
for (i = 0; i < NRCV; i++)
|
||||
dc->dc_rrent[i].r_flags = RFLG_OWN;
|
||||
sc->sc_nexttx = sc->sc_inq = sc->sc_lastack = sc->sc_nextrx = 0;
|
||||
|
||||
/* start up the board (rah rah) */
|
||||
s = splnet();
|
||||
sc->sc_rindex = sc->sc_xindex = sc->sc_xfree = sc->sc_nxmit = 0;
|
||||
sc->sc_if.if_flags |= IFF_RUNNING;
|
||||
DE_WLOW(PCSR0_INTE); /* Change to interrupts */
|
||||
DELAY(500);
|
||||
DE_WLOW(PCSR0_INTE); /* avoid interlock */
|
||||
destart(&sc->sc_if); /* queue output packets */
|
||||
DE_WLOW(CMD_START|PCSR0_INTE);
|
||||
dewait(sc, "start");
|
||||
DE_WLOW(CMD_PDMD|PCSR0_INTE);
|
||||
dewait(sc, "initpoll");
|
||||
splx(s);
|
||||
}
|
||||
|
||||
|
@ -446,54 +417,45 @@ destart(struct ifnet *ifp)
|
|||
{
|
||||
struct de_softc *sc = ifp->if_softc;
|
||||
struct de_cdata *dc;
|
||||
struct de_ring *rp;
|
||||
struct mbuf *m;
|
||||
int idx, s, running;
|
||||
int nxmit;
|
||||
|
||||
/*
|
||||
* the following test is necessary, since
|
||||
* the code is not reentrant and we have
|
||||
* multiple transmission buffers.
|
||||
*/
|
||||
if (ifp->if_flags & IFF_OACTIVE) /* Too much to do already */
|
||||
if (sc->sc_if.if_flags & IFF_OACTIVE)
|
||||
return;
|
||||
|
||||
if (ifp->if_snd.ifq_head == 0) /* Nothing to do at all */
|
||||
return;
|
||||
|
||||
s = splimp();
|
||||
dc = sc->sc_dedata;
|
||||
running = (sc->sc_inq != 0);
|
||||
while (sc->sc_inq < (NXMT - 1)) {
|
||||
|
||||
idx = sc->sc_nexttx;
|
||||
IF_DEQUEUE(&ifp->if_snd, m);
|
||||
for (nxmit = sc->sc_nxmit; nxmit < NXMT; nxmit++) {
|
||||
IF_DEQUEUE(&sc->sc_if.if_snd, m);
|
||||
if (m == 0)
|
||||
goto out;
|
||||
break;
|
||||
rp = &dc->dc_xrent[sc->sc_xfree];
|
||||
if (rp->r_flags & XFLG_OWN)
|
||||
panic("deuna xmit in progress");
|
||||
m_copydata(m, 0, m->m_pkthdr.len, &dc->dc_xbuf[sc->sc_xfree][0]);
|
||||
rp->r_slen = m->m_pkthdr.len;
|
||||
rp->r_tdrerr = 0;
|
||||
rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN;
|
||||
|
||||
#if NBPFILTER > 0
|
||||
if (ifp->if_bpf)
|
||||
bpf_mtap(ifp->if_bpf, m);
|
||||
#endif
|
||||
m_copydata(m, 0, m->m_pkthdr.len, &dc->dc_xbuf[idx][0]);
|
||||
dc->dc_xrent[idx].r_slen = m->m_pkthdr.len;
|
||||
dc->dc_xrent[idx].r_tdrerr = 0;
|
||||
dc->dc_xrent[idx].r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN;
|
||||
|
||||
m_freem(m);
|
||||
|
||||
sc->sc_inq++;
|
||||
if (++sc->sc_nexttx == NXMT)
|
||||
sc->sc_nexttx = 0;
|
||||
ifp->if_timer = 5; /* If transmit logic dies */
|
||||
sc->sc_xfree++;
|
||||
if (sc->sc_xfree == NXMT)
|
||||
sc->sc_xfree = 0;
|
||||
}
|
||||
if (sc->sc_inq == (NXMT - 1))
|
||||
ifp->if_flags |= IFF_OACTIVE;
|
||||
|
||||
out: if (running == 0) {
|
||||
DE_WLOW(PCSR0_INTE|CMD_PDMD);
|
||||
dewait(sc, "poll");
|
||||
if (sc->sc_nxmit != nxmit) {
|
||||
sc->sc_nxmit = nxmit;
|
||||
if (ifp->if_flags & IFF_RUNNING)
|
||||
DE_WLOW(PCSR0_INTE|CMD_PDMD);
|
||||
}
|
||||
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -502,79 +464,59 @@ out: if (running == 0) {
|
|||
void
|
||||
deintr(void *arg)
|
||||
{
|
||||
struct de_cdata *dc;
|
||||
struct de_softc *sc = arg;
|
||||
short csr0, csr1;
|
||||
struct de_ring *rp;
|
||||
short csr0;
|
||||
|
||||
/* save flags right away - clear out interrupt bits */
|
||||
csr0 = DE_RCSR(DE_PCSR0);
|
||||
csr1 = DE_RCSR(DE_PCSR1);
|
||||
DE_WHIGH(csr0 >> 8);
|
||||
|
||||
if (csr0 & PCSR0_RXI)
|
||||
derecv(sc);
|
||||
|
||||
if (csr0 & PCSR0_TXI)
|
||||
dexmit(sc);
|
||||
|
||||
/* Should never end up here */
|
||||
if (csr0 & PCSR0_PCEI) {
|
||||
printf("%s: Port command error interrupt\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
}
|
||||
|
||||
if (csr0 & PCSR0_SERI) {
|
||||
printf("%s: Status error interrupt\n", sc->sc_dev.dv_xname);
|
||||
}
|
||||
|
||||
if (csr0 & PCSR0_RCBI) {
|
||||
printf("%s: Receive buffer unavail interrupt\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
DE_WLOW(PCSR0_INTE|CMD_PDMD);
|
||||
dewait(sc, "repoll");
|
||||
}
|
||||
destart(&sc->sc_if);
|
||||
}
|
||||
|
||||
void
|
||||
dexmit(struct de_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = &sc->sc_if;
|
||||
struct de_ring *rp;
|
||||
sc->sc_if.if_flags |= IFF_OACTIVE; /* prevent entering destart */
|
||||
/*
|
||||
* if receive, put receive buffer on mbuf
|
||||
* and hang the request again
|
||||
*/
|
||||
derecv(sc);
|
||||
|
||||
/*
|
||||
* Poll transmit ring and check status.
|
||||
* Be careful about loopback requests.
|
||||
* Then free buffer space and check for
|
||||
* more transmit requests.
|
||||
*/
|
||||
rp = &sc->sc_dedata->dc_xrent[sc->sc_lastack];
|
||||
while ((rp->r_flags & XFLG_OWN) == 0) {
|
||||
int idx = sc->sc_lastack;
|
||||
|
||||
if (idx == sc->sc_nexttx)
|
||||
dc = sc->sc_dedata;
|
||||
for ( ; sc->sc_nxmit > 0; sc->sc_nxmit--) {
|
||||
rp = &dc->dc_xrent[sc->sc_xindex];
|
||||
if (rp->r_flags & XFLG_OWN)
|
||||
break;
|
||||
if (rp->r_flags & XFLG_ENP)
|
||||
ifp->if_opackets++;
|
||||
sc->sc_if.if_opackets++;
|
||||
/* check for unusual conditions */
|
||||
if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) {
|
||||
if (rp->r_flags & XFLG_ERRS) {
|
||||
ifp->if_oerrors++;
|
||||
/* output error */
|
||||
sc->sc_if.if_oerrors++;
|
||||
} else if (rp->r_flags & XFLG_ONE) {
|
||||
ifp->if_collisions++;
|
||||
/* one collision */
|
||||
sc->sc_if.if_collisions++;
|
||||
} else if (rp->r_flags & XFLG_MORE) {
|
||||
ifp->if_collisions += 3;
|
||||
/* more than one collision */
|
||||
sc->sc_if.if_collisions += 2; /* guess */
|
||||
}
|
||||
/* else if (rp->r_flags & XFLG_MTCH)
|
||||
* Matches ourself, but why care?
|
||||
* Let upper layer deal with this.
|
||||
*/
|
||||
}
|
||||
if (++sc->sc_lastack == NXMT)
|
||||
sc->sc_lastack = 0;
|
||||
sc->sc_inq--;
|
||||
rp = &sc->sc_dedata->dc_xrent[sc->sc_lastack];
|
||||
/* check if next transmit buffer also finished */
|
||||
sc->sc_xindex++;
|
||||
if (sc->sc_xindex == NXMT)
|
||||
sc->sc_xindex = 0;
|
||||
}
|
||||
sc->sc_if.if_flags &= ~IFF_OACTIVE;
|
||||
destart(&sc->sc_if);
|
||||
|
||||
if (csr0 & PCSR0_RCBI) {
|
||||
DE_WLOW(PCSR0_INTE|CMD_PDMD);
|
||||
}
|
||||
ifp->if_flags &= ~IFF_OACTIVE;
|
||||
if (sc->sc_inq == 0)
|
||||
ifp->if_timer = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -591,25 +533,22 @@ derecv(struct de_softc *sc)
|
|||
{
|
||||
struct ifnet *ifp = &sc->sc_if;
|
||||
struct de_ring *rp;
|
||||
struct de_cdata *dc;
|
||||
struct mbuf *m;
|
||||
int len;
|
||||
|
||||
rp = &sc->sc_dedata->dc_rrent[sc->sc_nextrx];
|
||||
dc = sc->sc_dedata;
|
||||
rp = &dc->dc_rrent[sc->sc_rindex];
|
||||
while ((rp->r_flags & RFLG_OWN) == 0) {
|
||||
ifp->if_ipackets++;
|
||||
sc->sc_if.if_ipackets++;
|
||||
len = (rp->r_lenerr&RERR_MLEN) - ETHER_CRC_LEN;
|
||||
/* check for errors */
|
||||
if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) ||
|
||||
(rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) ||
|
||||
(rp->r_lenerr & (RERR_BUFL|RERR_UBTO))) {
|
||||
ifp->if_ierrors++;
|
||||
sc->sc_if.if_ierrors++;
|
||||
goto next;
|
||||
}
|
||||
m = sc->sc_rxmbuf[sc->sc_nextrx];
|
||||
len = (rp->r_lenerr&RERR_MLEN) - ETHER_CRC_LEN;
|
||||
de_add_rxbuf(sc, sc->sc_nextrx);
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_pkthdr.len = m->m_len = len;
|
||||
|
||||
m = sc->sc_rxmbuf[sc->sc_rindex];
|
||||
#if NBPFILTER > 0
|
||||
if (ifp->if_bpf) {
|
||||
struct ether_header *eh;
|
||||
|
@ -619,22 +558,28 @@ derecv(struct de_softc *sc)
|
|||
if ((ifp->if_flags & IFF_PROMISC) != 0 &&
|
||||
bcmp(LLADDR(ifp->if_sadl), eh->ether_dhost,
|
||||
ETHER_ADDR_LEN) != 0 &&
|
||||
(ETHER_IS_MULTICAST(eh->ether_dhost) == 0)) {
|
||||
m_freem(m);
|
||||
(ETHER_IS_MULTICAST(eh->ether_dhost)==0)) {
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
(*ifp->if_input)(ifp, m);
|
||||
|
||||
if (de_add_rxbuf(sc, sc->sc_rindex) == 0) {
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_pkthdr.len = m->m_len = len;
|
||||
(*ifp->if_input)(ifp, m);
|
||||
} else
|
||||
sc->sc_if.if_ierrors++;
|
||||
|
||||
/* hang the receive buffer again */
|
||||
next: rp->r_lenerr = 0;
|
||||
rp->r_flags = RFLG_OWN;
|
||||
|
||||
/* check next receive buffer */
|
||||
if (++sc->sc_nextrx == NRCV)
|
||||
sc->sc_nextrx = 0;
|
||||
rp = &sc->sc_dedata->dc_rrent[sc->sc_nextrx];
|
||||
sc->sc_rindex++;
|
||||
if (sc->sc_rindex == NRCV)
|
||||
sc->sc_rindex = 0;
|
||||
rp = &dc->dc_rrent[sc->sc_rindex];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -723,9 +668,10 @@ deioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
|||
* If interface is marked down and it is running,
|
||||
* stop it.
|
||||
*/
|
||||
DE_WLOW(0);
|
||||
DELAY(5000);
|
||||
DE_WLOW(PCSR0_RSET);
|
||||
ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
|
||||
DE_WCSR(DE_PCSR0, PCSR0_RSET);
|
||||
dewait(sc, "down");
|
||||
} else if ((ifp->if_flags & IFF_UP) != 0 &&
|
||||
(ifp->if_flags & IFF_RUNNING) == 0) {
|
||||
/*
|
||||
|
@ -738,7 +684,13 @@ deioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
|||
* Send a new setup packet to match any new changes.
|
||||
* (Like IFF_PROMISC etc)
|
||||
*/
|
||||
desetup(sc);
|
||||
sc->sc_dedata->dc_pcbb.pcbb0 = FC_WTMODE;
|
||||
sc->sc_dedata->dc_pcbb.pcbb2 =
|
||||
MOD_TPAD|MOD_HDX|MOD_DRDC|MOD_ENAL;
|
||||
if (ifp->if_flags & IFF_PROMISC)
|
||||
sc->sc_dedata->dc_pcbb.pcbb2 |= MOD_PROM;
|
||||
DE_WLOW(CMD_GETCMD|PCSR0_INTE);
|
||||
dewait(sc, "chgmode");
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -756,7 +708,6 @@ deioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
|||
* Multicast list has changed; set the hardware filter
|
||||
* accordingly.
|
||||
*/
|
||||
desetup(sc);
|
||||
error = 0;
|
||||
}
|
||||
break;
|
||||
|
@ -775,50 +726,19 @@ deioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
|||
void
|
||||
dewait(struct de_softc *sc, char *fn)
|
||||
{
|
||||
int csr0, s;
|
||||
int csr0;
|
||||
|
||||
s = splimp();
|
||||
while ((DE_RCSR(DE_PCSR0) & PCSR0_INTR) == 0)
|
||||
;
|
||||
csr0 = DE_RCSR(DE_PCSR0);
|
||||
DE_WHIGH(csr0 >> 8);
|
||||
if (csr0 & PCSR0_PCEI) {
|
||||
char bits[64];
|
||||
|
||||
printf("%s: %s failed, csr0=%s ", sc->sc_dev.dv_xname, fn,
|
||||
bitmask_snprintf(csr0, PCSR0_BITS, bits, sizeof(bits)));
|
||||
printf("csr1=%s\n", bitmask_snprintf(DE_RCSR(DE_PCSR1),
|
||||
PCSR1_BITS, bits, sizeof(bits)));
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Changes multicast filter list/promiscous modes etc...
|
||||
*/
|
||||
void
|
||||
desetup(struct de_softc *sc)
|
||||
{
|
||||
short mode, intr;
|
||||
|
||||
/*
|
||||
* XXX - so far use ALLMULTI to receive multicast packets.
|
||||
*/
|
||||
sc->sc_if.if_flags &= ~IFF_ALLMULTI;
|
||||
if (sc->sc_ec.ec_multiaddrs.lh_first)
|
||||
sc->sc_if.if_flags |= IFF_ALLMULTI;
|
||||
|
||||
mode = MOD_TPAD|MOD_HDX|MOD_DRDC;
|
||||
if (sc->sc_if.if_flags & IFF_PROMISC)
|
||||
mode |= MOD_PROM;
|
||||
else if (sc->sc_if.if_flags & IFF_ALLMULTI)
|
||||
mode |= MOD_ENAL;
|
||||
|
||||
sc->sc_dedata->dc_pcbb.pcbb0 = FC_WTMODE;
|
||||
sc->sc_dedata->dc_pcbb.pcbb2 = mode;
|
||||
intr = DE_RCSR(DE_PCSR0) & PCSR0_INTE;
|
||||
DE_WLOW(CMD_GETCMD | intr);
|
||||
dewait(sc, "wtmode");
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -866,7 +786,8 @@ deshutdown(void *arg)
|
|||
{
|
||||
struct de_softc *sc = arg;
|
||||
|
||||
DE_WCSR(DE_PCSR0, 0);
|
||||
DELAY(1000);
|
||||
DE_WCSR(DE_PCSR0, PCSR0_RSET);
|
||||
dewait(sc, "shutdown");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue