version 1.20, 2009/05/12 14:43:33 |
version 1.20.22.3, 2017/12/03 11:37:31 |
Line 56 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 56 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/device.h> |
#include <sys/device.h> |
|
|
#include <net/if.h> |
#include <net/if.h> |
#include <net/netisr.h> |
|
|
|
#ifdef INET |
#ifdef INET |
#include <netinet/in.h> |
#include <netinet/in.h> |
Line 134 struct dmcbufs { |
|
Line 133 struct dmcbufs { |
|
* efficiently. |
* efficiently. |
*/ |
*/ |
struct dmc_softc { |
struct dmc_softc { |
struct device sc_dev; /* Configuration common part */ |
device_t sc_dev; /* Configuration common part */ |
struct ifnet sc_if; /* network-visible interface */ |
struct ifnet sc_if; /* network-visible interface */ |
short sc_oused; /* output buffers currently in use */ |
short sc_oused; /* output buffers currently in use */ |
short sc_iused; /* input buffers given to DMC */ |
short sc_iused; /* input buffers given to DMC */ |
Line 183 static int dmcoutput(struct ifnet *, st |
|
Line 182 static int dmcoutput(struct ifnet *, st |
|
struct rtentry *); |
struct rtentry *); |
static void dmcreset(device_t); |
static void dmcreset(device_t); |
|
|
CFATTACH_DECL(dmc, sizeof(struct dmc_softc), |
CFATTACH_DECL_NEW(dmc, sizeof(struct dmc_softc), |
dmcmatch, dmcattach, NULL, NULL); |
dmcmatch, dmcattach, NULL, NULL); |
|
|
/* flags */ |
/* flags */ |
Line 252 dmcattach(device_t parent, device_t self |
|
Line 251 dmcattach(device_t parent, device_t self |
|
struct uba_attach_args *ua = aux; |
struct uba_attach_args *ua = aux; |
struct dmc_softc *sc = device_private(self); |
struct dmc_softc *sc = device_private(self); |
|
|
|
sc->sc_dev = self; |
sc->sc_iot = ua->ua_iot; |
sc->sc_iot = ua->ua_iot; |
sc->sc_ioh = ua->ua_ioh; |
sc->sc_ioh = ua->ua_ioh; |
sc->sc_dmat = ua->ua_dmat; |
sc->sc_dmat = ua->ua_dmat; |
|
|
strlcpy(sc->sc_if.if_xname, device_xname(&sc->sc_dev), IFNAMSIZ); |
strlcpy(sc->sc_if.if_xname, device_xname(sc->sc_dev), IFNAMSIZ); |
sc->sc_if.if_mtu = DMCMTU; |
sc->sc_if.if_mtu = DMCMTU; |
sc->sc_if.if_init = dmcinit; |
sc->sc_if.if_init = dmcinit; |
sc->sc_if.if_output = dmcoutput; |
sc->sc_if.if_output = dmcoutput; |
Line 270 dmcattach(device_t parent, device_t self |
|
Line 270 dmcattach(device_t parent, device_t self |
|
&sc->sc_rintrcnt); |
&sc->sc_rintrcnt); |
uba_intr_establish(ua->ua_icookie, ua->ua_cvec+4, dmcxint, sc, |
uba_intr_establish(ua->ua_icookie, ua->ua_cvec+4, dmcxint, sc, |
&sc->sc_tintrcnt); |
&sc->sc_tintrcnt); |
uba_reset_establish(dmcreset, &sc->sc_dev); |
uba_reset_establish(dmcreset, sc->sc_dev); |
evcnt_attach_dynamic(&sc->sc_rintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt, |
evcnt_attach_dynamic(&sc->sc_rintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt, |
device_xname(&sc->sc_dev), "intr"); |
device_xname(sc->sc_dev), "intr"); |
evcnt_attach_dynamic(&sc->sc_tintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt, |
evcnt_attach_dynamic(&sc->sc_tintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt, |
device_xname(&sc->sc_dev), "intr"); |
device_xname(sc->sc_dev), "intr"); |
|
|
if_attach(&sc->sc_if); |
if_attach(&sc->sc_if); |
} |
} |
Line 286 dmcattach(device_t parent, device_t self |
|
Line 286 dmcattach(device_t parent, device_t self |
|
void |
void |
dmcreset(device_t dev) |
dmcreset(device_t dev) |
{ |
{ |
struct dmc_softc *sc = (struct dmc_softc *)dev; |
struct dmc_softc *sc = device_private(dev); |
|
|
sc->sc_flag = 0; |
sc->sc_flag = 0; |
sc->sc_if.if_flags &= ~IFF_RUNNING; |
sc->sc_if.if_flags &= ~IFF_RUNNING; |
Line 305 dmcinit(struct ifnet *ifp) |
|
Line 305 dmcinit(struct ifnet *ifp) |
|
struct dmcbufs *rp; |
struct dmcbufs *rp; |
struct dmc_command *qp; |
struct dmc_command *qp; |
struct ifaddr *ifa; |
struct ifaddr *ifa; |
cfdata_t ui = device_cfdata(&sc->sc_dev); |
cfdata_t ui = device_cfdata(sc->sc_dev); |
int base; |
int base; |
int s; |
int s; |
|
|
Line 313 dmcinit(struct ifnet *ifp) |
|
Line 313 dmcinit(struct ifnet *ifp) |
|
* Check to see that an address has been set |
* Check to see that an address has been set |
* (both local and destination for an address family). |
* (both local and destination for an address family). |
*/ |
*/ |
IFADDR_FOREACH(ifa, ifp) |
s = pserialize_read_enter(); |
|
IFADDR_READER_FOREACH(ifa, ifp) { |
if (ifa->ifa_addr->sa_family && ifa->ifa_dstaddr->sa_family) |
if (ifa->ifa_addr->sa_family && ifa->ifa_dstaddr->sa_family) |
break; |
break; |
if (ifa == (struct ifaddr *) 0) |
} |
|
pserialize_read_exit(s); |
|
if (ifa == NULL) |
return 0; |
return 0; |
|
|
if ((DMC_RBYTE(DMC_BSEL1) & DMC_RUN) == 0) { |
if ((DMC_RBYTE(DMC_BSEL1) & DMC_RUN) == 0) { |
Line 328 dmcinit(struct ifnet *ifp) |
|
Line 331 dmcinit(struct ifnet *ifp) |
|
if ((sc->sc_flag & DMC_BMAPPED) == 0) { |
if ((sc->sc_flag & DMC_BMAPPED) == 0) { |
sc->sc_ui.ui_size = sizeof(struct dmc_base); |
sc->sc_ui.ui_size = sizeof(struct dmc_base); |
sc->sc_ui.ui_vaddr = (void *)&sc->dmc_base; |
sc->sc_ui.ui_vaddr = (void *)&sc->dmc_base; |
uballoc((void *)device_parent(&sc->sc_dev), &sc->sc_ui, 0); |
uballoc(device_private(device_parent(sc->sc_dev)), &sc->sc_ui, 0); |
sc->sc_flag |= DMC_BMAPPED; |
sc->sc_flag |= DMC_BMAPPED; |
} |
} |
/* initialize UNIBUS resources */ |
/* initialize UNIBUS resources */ |
sc->sc_iused = sc->sc_oused = 0; |
sc->sc_iused = sc->sc_oused = 0; |
if ((ifp->if_flags & IFF_RUNNING) == 0) { |
if ((ifp->if_flags & IFF_RUNNING) == 0) { |
if (if_ubaminit(&sc->sc_ifuba, |
if (if_ubaminit(&sc->sc_ifuba, |
(void *)device_parent(&sc->sc_dev), |
device_private(device_parent(sc->sc_dev)), |
sizeof(struct dmc_header) + DMCMTU, |
sizeof(struct dmc_header) + DMCMTU, |
sc->sc_ifr, NRCV, sc->sc_ifw, NXMT) == 0) { |
sc->sc_ifr, NRCV, sc->sc_ifw, NXMT) == 0) { |
aprint_error_dev(&sc->sc_dev, "can't allocate uba resources\n"); |
aprint_error_dev(sc->sc_dev, "can't allocate uba resources\n"); |
ifp->if_flags &= ~IFF_UP; |
ifp->if_flags &= ~IFF_UP; |
return 0; |
return 0; |
} |
} |
Line 502 dmcrint(void *arg) |
|
Line 505 dmcrint(void *arg) |
|
int n; |
int n; |
|
|
if ((qp = sc->sc_qactive) == (struct dmc_command *) 0) { |
if ((qp = sc->sc_qactive) == (struct dmc_command *) 0) { |
printf("%s: dmcrint no command\n", device_xname(&sc->sc_dev)); |
printf("%s: dmcrint no command\n", device_xname(sc->sc_dev)); |
return; |
return; |
} |
} |
while (DMC_RBYTE(DMC_BSEL0) & DMC_RDYI) { |
while (DMC_RBYTE(DMC_BSEL0) & DMC_RDYI) { |
Line 552 dmcxint(void *a) |
|
Line 555 dmcxint(void *a) |
|
|
|
struct ifnet *ifp; |
struct ifnet *ifp; |
struct mbuf *m; |
struct mbuf *m; |
struct ifqueue *inq; |
|
int arg, pkaddr, cmd, len, s; |
int arg, pkaddr, cmd, len, s; |
struct ifrw *ifrw; |
struct ifrw *ifrw; |
struct dmcbufs *rp; |
struct dmcbufs *rp; |
Line 589 dmcxint(void *a) |
|
Line 591 dmcxint(void *a) |
|
if (rp >= &sc->sc_rbufs[NRCV]) |
if (rp >= &sc->sc_rbufs[NRCV]) |
panic("dmc rcv"); |
panic("dmc rcv"); |
if ((rp->flags & DBUF_DMCS) == 0) |
if ((rp->flags & DBUF_DMCS) == 0) |
aprint_error_dev(&sc->sc_dev, "done unalloc rbuf\n"); |
aprint_error_dev(sc->sc_dev, "done unalloc rbuf\n"); |
|
|
len = (arg & DMC_CCOUNT) - sizeof (struct dmc_header); |
len = (arg & DMC_CCOUNT) - sizeof (struct dmc_header); |
if (len < 0 || len > DMCMTU) { |
if (len < 0 || len > DMCMTU) { |
ifp->if_ierrors++; |
ifp->if_ierrors++; |
#ifdef DMCDEBUG |
#ifdef DMCDEBUG |
printd("%s: bad rcv pkt addr 0x%x len 0x%x\n", |
printd("%s: bad rcv pkt addr 0x%x len 0x%x\n", |
device_xname(&sc->sc_dev), pkaddr, len); |
device_xname(sc->sc_dev), pkaddr, len); |
#endif |
#endif |
goto setup; |
goto setup; |
} |
} |
Line 623 dmcxint(void *a) |
|
Line 625 dmcxint(void *a) |
|
/* Shave off dmc_header */ |
/* Shave off dmc_header */ |
m_adj(m, sizeof(struct dmc_header)); |
m_adj(m, sizeof(struct dmc_header)); |
switch (dh->dmc_type) { |
switch (dh->dmc_type) { |
|
|
#ifdef INET |
#ifdef INET |
case DMC_IPTYPE: |
case DMC_IPTYPE: |
schednetisr(NETISR_IP); |
|
inq = &ipintrq; |
|
break; |
break; |
#endif |
#endif |
default: |
default: |
Line 636 dmcxint(void *a) |
|
Line 635 dmcxint(void *a) |
|
} |
} |
|
|
s = splnet(); |
s = splnet(); |
if (IF_QFULL(inq)) { |
if (__predict_false(!pktq_enqueue(ip_pktq, m, 0))) { |
IF_DROP(inq); |
|
m_freem(m); |
m_freem(m); |
} else |
} |
IF_ENQUEUE(inq, m); |
|
splx(s); |
splx(s); |
|
|
setup: |
setup: |
Line 665 dmcxint(void *a) |
|
Line 662 dmcxint(void *a) |
|
ifxp++; |
ifxp++; |
} |
} |
if (rp >= &sc->sc_xbufs[NXMT]) { |
if (rp >= &sc->sc_xbufs[NXMT]) { |
aprint_error_dev(&sc->sc_dev, "bad packet address 0x%x\n", |
aprint_error_dev(sc->sc_dev, "bad packet address 0x%x\n", |
pkaddr); |
pkaddr); |
break; |
break; |
} |
} |
if ((rp->flags & DBUF_DMCS) == 0) |
if ((rp->flags & DBUF_DMCS) == 0) |
aprint_error_dev(&sc->sc_dev, "unallocated packet 0x%x\n", |
aprint_error_dev(sc->sc_dev, "unallocated packet 0x%x\n", |
pkaddr); |
pkaddr); |
/* mark buffer free */ |
/* mark buffer free */ |
if_ubaend(&sc->sc_ifuba, ifxp); |
if_ubaend(&sc->sc_ifuba, ifxp); |
Line 699 dmcxint(void *a) |
|
Line 696 dmcxint(void *a) |
|
arg); |
arg); |
log(LOG_ERR, |
log(LOG_ERR, |
"%s: fatal error, flags=%s\n", |
"%s: fatal error, flags=%s\n", |
device_xname(&sc->sc_dev), buf); |
device_xname(sc->sc_dev), buf); |
} |
} |
dmcrestart(sc); |
dmcrestart(sc); |
break; |
break; |
Line 732 dmcxint(void *a) |
|
Line 729 dmcxint(void *a) |
|
#ifdef DMCDEBUG |
#ifdef DMCDEBUG |
snprintb(buf, sizeof(buf), CNTLO_BITS, arg); |
snprintb(buf, sizeof(buf), CNTLO_BITS, arg); |
printd("%s: soft error, flags=%s\n", |
printd("%s: soft error, flags=%s\n", |
device_xname(&sc->sc_dev), buf); |
device_xname(sc->sc_dev), buf); |
#endif |
#endif |
if ((sc->sc_flag & DMC_RESTART) == 0) { |
if ((sc->sc_flag & DMC_RESTART) == 0) { |
/* |
/* |
Line 748 dmcxint(void *a) |
|
Line 745 dmcxint(void *a) |
|
|
|
default: |
default: |
printf("%s: bad control %o\n", |
printf("%s: bad control %o\n", |
device_xname(&sc->sc_dev), cmd); |
device_xname(sc->sc_dev), cmd); |
break; |
break; |
} |
} |
} |
} |
Line 768 dmcoutput(struct ifnet *ifp, struct mbuf |
|
Line 765 dmcoutput(struct ifnet *ifp, struct mbuf |
|
int type, error, s; |
int type, error, s; |
struct mbuf *m = m0; |
struct mbuf *m = m0; |
struct dmc_header *dh; |
struct dmc_header *dh; |
ALTQ_DECL(struct altq_pktattr pktattr;) |
|
|
|
if ((ifp->if_flags & IFF_UP) == 0) { |
if ((ifp->if_flags & IFF_UP) == 0) { |
error = ENETDOWN; |
error = ENETDOWN; |
goto bad; |
goto bad; |
} |
} |
|
|
IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr); |
IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family); |
|
|
switch (dst->sa_family) { |
switch (dst->sa_family) { |
#ifdef INET |
#ifdef INET |
Line 813 dmcoutput(struct ifnet *ifp, struct mbuf |
|
Line 809 dmcoutput(struct ifnet *ifp, struct mbuf |
|
* not yet active. |
* not yet active. |
*/ |
*/ |
s = splnet(); |
s = splnet(); |
IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error); |
IFQ_ENQUEUE(&ifp->if_snd, m, error); |
if (error) { |
if (error) { |
/* mbuf is already freed */ |
/* mbuf is already freed */ |
splx(s); |
splx(s); |
Line 881 dmcrestart(struct dmc_softc *sc) |
|
Line 877 dmcrestart(struct dmc_softc *sc) |
|
|
|
#ifdef DMCDEBUG |
#ifdef DMCDEBUG |
/* dump base table */ |
/* dump base table */ |
printf("%s base table:\n", device_xname(&sc->sc_dev)); |
printf("%s base table:\n", device_xname(sc->sc_dev)); |
for (i = 0; i < sizeof (struct dmc_base); i++) |
for (i = 0; i < sizeof (struct dmc_base); i++) |
printf("%o\n" ,dmc_base[unit].d_base[i]); |
printf("%o\n" ,dmc_base[unit].d_base[i]); |
#endif |
#endif |
Line 896 dmcrestart(struct dmc_softc *sc) |
|
Line 892 dmcrestart(struct dmc_softc *sc) |
|
; |
; |
/* Did the timer expire or did the DMR finish? */ |
/* Did the timer expire or did the DMR finish? */ |
if ((DMC_RBYTE(DMC_BSEL1) & DMC_RUN) == 0) { |
if ((DMC_RBYTE(DMC_BSEL1) & DMC_RUN) == 0) { |
log(LOG_ERR, "%s: M820 Test Failed\n", device_xname(&sc->sc_dev)); |
log(LOG_ERR, "%s: M820 Test Failed\n", device_xname(sc->sc_dev)); |
return; |
return; |
} |
} |
|
|
Line 949 dmctimeout(struct ifnet *ifp) |
|
Line 945 dmctimeout(struct ifnet *ifp) |
|
snprintb(buf2, sizeof(buf2), DMC2BITS, |
snprintb(buf2, sizeof(buf2), DMC2BITS, |
DMC_RBYTE(DMC_BSEL2) & 0xff); |
DMC_RBYTE(DMC_BSEL2) & 0xff); |
log(LOG_ERR, "%s: output timeout, bsel0=%s bsel2=%s\n", |
log(LOG_ERR, "%s: output timeout, bsel0=%s bsel2=%s\n", |
device_xname(&sc->sc_dev), buf1, buf2); |
device_xname(sc->sc_dev), buf1, buf2); |
dmcrestart(sc); |
dmcrestart(sc); |
} |
} |
} |
} |