Make the MI LANCE driver standalone, and use cfattach to resolve
naming conflicts between bus attachments on ports that can have multiple instances of the LANCE. Changed struct ifnet to have a pointer to the softc of the underlying device and a printable "external name" (name + unit number), thus eliminating if_name and if_unit. Updated interface to (*if_watchdog)() and (*if_start)() to take a struct ifnet *, rather than a unit number.
This commit is contained in:
parent
69351e2be6
commit
16e78eb3fb
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: am7990.c,v 1.18 1996/04/22 02:40:50 christos Exp $ */
|
||||
/* $NetBSD: am7990.c,v 1.19 1996/05/07 01:38:35 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995 Charles M. Hannum. All rights reserved.
|
||||
@ -39,10 +39,23 @@
|
||||
* @(#)if_le.c 8.2 (Berkeley) 11/16/93
|
||||
*/
|
||||
|
||||
#include "bpfilter.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#ifdef INET
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/ip.h>
|
||||
@ -66,31 +79,81 @@
|
||||
#include <net/bpfdesc.h>
|
||||
#endif
|
||||
|
||||
#include <dev/ic/am7990reg.h>
|
||||
#include <dev/ic/am7990var.h>
|
||||
|
||||
#ifdef LEDEBUG
|
||||
void recv_print __P((struct le_softc *, int));
|
||||
void xmit_print __P((struct le_softc *, int));
|
||||
void am7990_recv_print __P((struct am7990_softc *, int));
|
||||
void am7990_xmit_print __P((struct am7990_softc *, int));
|
||||
#endif
|
||||
|
||||
integrate void am7990_rint __P((struct am7990_softc *));
|
||||
integrate void am7990_tint __P((struct am7990_softc *));
|
||||
|
||||
integrate int am7990_put __P((struct am7990_softc *, int, struct mbuf *));
|
||||
integrate struct mbuf *am7990_get __P((struct am7990_softc *, int, int));
|
||||
integrate void am7990_read __P((struct am7990_softc *, int, int));
|
||||
|
||||
hide void am7990_shutdown __P((void *));
|
||||
|
||||
#define ifp (&sc->sc_arpcom.ac_if)
|
||||
|
||||
#if 0 /* XXX what do we do about this?! --thorpej */
|
||||
static inline u_int16_t ether_cmp __P((void *, void *));
|
||||
|
||||
/*
|
||||
* Compare two Ether/802 addresses for equality, inlined and
|
||||
* unrolled for speed. I'd love to have an inline assembler
|
||||
* version of this... XXX: Who wanted that? mycroft?
|
||||
* I wrote one, but the following is just as efficient.
|
||||
* This expands to 10 short m68k instructions! -gwr
|
||||
* Note: use this like bcmp()
|
||||
*/
|
||||
static inline u_short
|
||||
ether_cmp(one, two)
|
||||
void *one, *two;
|
||||
{
|
||||
register u_int16_t *a = (u_short *) one;
|
||||
register u_int16_t *b = (u_short *) two;
|
||||
register u_int16_t diff;
|
||||
|
||||
diff = *a++ - *b++;
|
||||
diff |= *a++ - *b++;
|
||||
diff |= *a++ - *b++;
|
||||
|
||||
return (diff);
|
||||
}
|
||||
|
||||
#define ETHER_CMP ether_cmp
|
||||
#endif /* XXX */
|
||||
|
||||
#ifndef ETHER_CMP
|
||||
#define ETHER_CMP(a, b) bcmp((a), (b), ETHER_ADDR_LEN)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* am7990 configuration driver. Attachments are provided by
|
||||
* machine-dependent driver front-ends.
|
||||
*/
|
||||
struct cfdriver le_cd = {
|
||||
NULL, "le", DV_IFNET
|
||||
};
|
||||
|
||||
void
|
||||
leconfig(sc)
|
||||
struct le_softc *sc;
|
||||
am7990_config(sc)
|
||||
struct am7990_softc *sc;
|
||||
{
|
||||
int mem;
|
||||
|
||||
/* Make sure the chip is stopped. */
|
||||
lestop(sc);
|
||||
am7990_stop(sc);
|
||||
|
||||
/* Initialize ifnet structure. */
|
||||
ifp->if_unit = sc->sc_dev.dv_unit;
|
||||
ifp->if_start = lestart;
|
||||
ifp->if_ioctl = leioctl;
|
||||
ifp->if_watchdog = lewatchdog;
|
||||
bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
|
||||
ifp->if_softc = sc;
|
||||
ifp->if_start = am7990_start;
|
||||
ifp->if_ioctl = am7990_ioctl;
|
||||
ifp->if_watchdog = am7990_watchdog;
|
||||
ifp->if_flags =
|
||||
IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
|
||||
#ifdef LANCE_REVC_BUG
|
||||
@ -123,13 +186,17 @@ leconfig(sc)
|
||||
sc->sc_ntbuf = 8;
|
||||
break;
|
||||
default:
|
||||
panic("leconfig: weird memory size");
|
||||
panic("am7990_config: weird memory size");
|
||||
}
|
||||
|
||||
printf(": address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
|
||||
printf("%s: %d receive buffers, %d transmit buffers\n",
|
||||
sc->sc_dev.dv_xname, sc->sc_nrbuf, sc->sc_ntbuf);
|
||||
|
||||
sc->sc_sh = shutdownhook_establish(am7990_shutdown, sc);
|
||||
if (sc->sc_sh == NULL)
|
||||
panic("am7990_config: can't establish shutdownhook");
|
||||
|
||||
mem = 0;
|
||||
sc->sc_initaddr = mem;
|
||||
mem += sizeof(struct leinit);
|
||||
@ -148,34 +215,22 @@ leconfig(sc)
|
||||
}
|
||||
|
||||
void
|
||||
lereset(sc)
|
||||
struct le_softc *sc;
|
||||
am7990_reset(sc)
|
||||
struct am7990_softc *sc;
|
||||
{
|
||||
int s;
|
||||
|
||||
s = splimp();
|
||||
leinit(sc);
|
||||
am7990_init(sc);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
void
|
||||
lewatchdog(unit)
|
||||
int unit;
|
||||
{
|
||||
struct le_softc *sc = LE_SOFTC(unit);
|
||||
|
||||
log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
|
||||
++ifp->if_oerrors;
|
||||
|
||||
lereset(sc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the initialization block and the descriptor rings.
|
||||
*/
|
||||
void
|
||||
lememinit(sc)
|
||||
register struct le_softc *sc;
|
||||
am7990_meminit(sc)
|
||||
register struct am7990_softc *sc;
|
||||
{
|
||||
u_long a;
|
||||
int bix;
|
||||
@ -195,7 +250,7 @@ lememinit(sc)
|
||||
(sc->sc_arpcom.ac_enaddr[3] << 8) | sc->sc_arpcom.ac_enaddr[2];
|
||||
init.init_padr[2] =
|
||||
(sc->sc_arpcom.ac_enaddr[5] << 8) | sc->sc_arpcom.ac_enaddr[4];
|
||||
lesetladrf(&sc->sc_arpcom, init.init_ladrf);
|
||||
am7990_setladrf(&sc->sc_arpcom, init.init_ladrf);
|
||||
|
||||
sc->sc_last_rd = 0;
|
||||
sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
|
||||
@ -240,11 +295,11 @@ lememinit(sc)
|
||||
}
|
||||
|
||||
void
|
||||
lestop(sc)
|
||||
struct le_softc *sc;
|
||||
am7990_stop(sc)
|
||||
struct am7990_softc *sc;
|
||||
{
|
||||
|
||||
lewrcsr(sc, LE_CSR0, LE_C0_STOP);
|
||||
(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -252,45 +307,47 @@ lestop(sc)
|
||||
* and transmit/receive descriptor rings.
|
||||
*/
|
||||
void
|
||||
leinit(sc)
|
||||
register struct le_softc *sc;
|
||||
am7990_init(sc)
|
||||
register struct am7990_softc *sc;
|
||||
{
|
||||
register int timo;
|
||||
u_long a;
|
||||
|
||||
lewrcsr(sc, LE_CSR0, LE_C0_STOP);
|
||||
LE_DELAY(100);
|
||||
(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
|
||||
DELAY(100);
|
||||
|
||||
/* Set the correct byte swapping mode, etc. */
|
||||
lewrcsr(sc, LE_CSR3, sc->sc_conf3);
|
||||
(*sc->sc_wrcsr)(sc, LE_CSR3, sc->sc_conf3);
|
||||
|
||||
/* Set up LANCE init block. */
|
||||
lememinit(sc);
|
||||
am7990_meminit(sc);
|
||||
|
||||
/* Give LANCE the physical address of its init block. */
|
||||
a = sc->sc_addr + LE_INITADDR(sc);
|
||||
lewrcsr(sc, LE_CSR1, a);
|
||||
lewrcsr(sc, LE_CSR2, a >> 16);
|
||||
(*sc->sc_wrcsr)(sc, LE_CSR1, a);
|
||||
(*sc->sc_wrcsr)(sc, LE_CSR2, a >> 16);
|
||||
|
||||
/* Try to initialize the LANCE. */
|
||||
LE_DELAY(100);
|
||||
lewrcsr(sc, LE_CSR0, LE_C0_INIT);
|
||||
DELAY(100);
|
||||
(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INIT);
|
||||
|
||||
/* Wait for initialization to finish. */
|
||||
for (timo = 100000; timo; timo--)
|
||||
if (lerdcsr(sc, LE_CSR0) & LE_C0_IDON)
|
||||
if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON)
|
||||
break;
|
||||
|
||||
if (lerdcsr(sc, LE_CSR0) & LE_C0_IDON) {
|
||||
if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) {
|
||||
/* Start the LANCE. */
|
||||
lewrcsr(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT | LE_C0_IDON);
|
||||
(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT |
|
||||
LE_C0_IDON);
|
||||
ifp->if_flags |= IFF_RUNNING;
|
||||
ifp->if_flags &= ~IFF_OACTIVE;
|
||||
ifp->if_timer = 0;
|
||||
lestart(ifp);
|
||||
am7990_start(ifp);
|
||||
} else
|
||||
printf("%s: card failed to initialize\n", sc->sc_dev.dv_xname);
|
||||
lehwinit(sc);
|
||||
if (sc->sc_hwinit)
|
||||
(*sc->sc_hwinit)(sc);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -298,8 +355,8 @@ leinit(sc)
|
||||
* network buffer memory.
|
||||
*/
|
||||
integrate int
|
||||
leput(sc, boff, m)
|
||||
struct le_softc *sc;
|
||||
am7990_put(sc, boff, m)
|
||||
struct am7990_softc *sc;
|
||||
int boff;
|
||||
register struct mbuf *m;
|
||||
{
|
||||
@ -331,8 +388,8 @@ leput(sc, boff, m)
|
||||
* we copy into clusters.
|
||||
*/
|
||||
integrate struct mbuf *
|
||||
leget(sc, boff, totlen)
|
||||
struct le_softc *sc;
|
||||
am7990_get(sc, boff, totlen)
|
||||
struct am7990_softc *sc;
|
||||
int boff, totlen;
|
||||
{
|
||||
register struct mbuf *m;
|
||||
@ -379,8 +436,8 @@ leget(sc, boff, totlen)
|
||||
* Pass a packet to the higher levels.
|
||||
*/
|
||||
integrate void
|
||||
leread(sc, boff, len)
|
||||
register struct le_softc *sc;
|
||||
am7990_read(sc, boff, len)
|
||||
register struct am7990_softc *sc;
|
||||
int boff, len;
|
||||
{
|
||||
struct mbuf *m;
|
||||
@ -397,7 +454,7 @@ leread(sc, boff, len)
|
||||
}
|
||||
|
||||
/* Pull packet off interface. */
|
||||
m = leget(sc, boff, len);
|
||||
m = am7990_get(sc, boff, len);
|
||||
if (m == 0) {
|
||||
ifp->if_ierrors++;
|
||||
return;
|
||||
@ -453,8 +510,8 @@ leread(sc, boff, len)
|
||||
}
|
||||
|
||||
integrate void
|
||||
lerint(sc)
|
||||
struct le_softc *sc;
|
||||
am7990_rint(sc)
|
||||
struct am7990_softc *sc;
|
||||
{
|
||||
register int bix;
|
||||
int rp;
|
||||
@ -499,9 +556,10 @@ lerint(sc)
|
||||
} else {
|
||||
#ifdef LEDEBUG
|
||||
if (sc->sc_debug)
|
||||
recv_print(sc, sc->sc_last_rd);
|
||||
am7990_recv_print(sc, sc->sc_last_rd);
|
||||
#endif
|
||||
leread(sc, LE_RBUFADDR(sc, bix), (int)rmd.rmd3 - 4);
|
||||
am7990_read(sc, LE_RBUFADDR(sc, bix),
|
||||
(int)rmd.rmd3 - 4);
|
||||
}
|
||||
|
||||
rmd.rmd1_bits = LE_R1_OWN;
|
||||
@ -527,8 +585,8 @@ lerint(sc)
|
||||
}
|
||||
|
||||
integrate void
|
||||
letint(sc)
|
||||
register struct le_softc *sc;
|
||||
am7990_tint(sc)
|
||||
register struct am7990_softc *sc;
|
||||
{
|
||||
register int bix;
|
||||
struct letmd tmd;
|
||||
@ -558,20 +616,23 @@ letint(sc)
|
||||
|
||||
if (tmd.tmd1_bits & LE_T1_ERR) {
|
||||
if (tmd.tmd3 & LE_T3_BUFF)
|
||||
printf("%s: transmit buffer error\n", sc->sc_dev.dv_xname);
|
||||
printf("%s: transmit buffer error\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
else if (tmd.tmd3 & LE_T3_UFLO)
|
||||
printf("%s: underflow\n", sc->sc_dev.dv_xname);
|
||||
if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) {
|
||||
lereset(sc);
|
||||
am7990_reset(sc);
|
||||
return;
|
||||
}
|
||||
if (tmd.tmd3 & LE_T3_LCAR)
|
||||
printf("%s: lost carrier\n", sc->sc_dev.dv_xname);
|
||||
printf("%s: lost carrier\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
if (tmd.tmd3 & LE_T3_LCOL)
|
||||
ifp->if_collisions++;
|
||||
if (tmd.tmd3 & LE_T3_RTRY) {
|
||||
printf("%s: excessive collisions, tdr %d\n",
|
||||
sc->sc_dev.dv_xname, tmd.tmd3 & LE_T3_TDR_MASK);
|
||||
sc->sc_dev.dv_xname,
|
||||
tmd.tmd3 & LE_T3_TDR_MASK);
|
||||
ifp->if_collisions += 16;
|
||||
}
|
||||
ifp->if_oerrors++;
|
||||
@ -592,7 +653,7 @@ letint(sc)
|
||||
|
||||
sc->sc_first_td = bix;
|
||||
|
||||
lestart(ifp);
|
||||
am7990_start(ifp);
|
||||
|
||||
if (sc->sc_no_td == 0)
|
||||
ifp->if_timer = 0;
|
||||
@ -602,22 +663,22 @@ letint(sc)
|
||||
* Controller interrupt.
|
||||
*/
|
||||
int
|
||||
leintr(arg)
|
||||
am7990_intr(arg)
|
||||
register void *arg;
|
||||
{
|
||||
register struct le_softc *sc = arg;
|
||||
register struct am7990_softc *sc = arg;
|
||||
register u_int16_t isr;
|
||||
|
||||
isr = lerdcsr(sc, LE_CSR0);
|
||||
isr = (*sc->sc_rdcsr)(sc, LE_CSR0);
|
||||
#ifdef LEDEBUG
|
||||
if (sc->sc_debug)
|
||||
printf("%s: leintr entering with isr=%04x\n",
|
||||
printf("%s: am7990_intr entering with isr=%04x\n",
|
||||
sc->sc_dev.dv_xname, isr);
|
||||
#endif
|
||||
if ((isr & LE_C0_INTR) == 0)
|
||||
return (0);
|
||||
|
||||
lewrcsr(sc, LE_CSR0,
|
||||
(*sc->sc_wrcsr)(sc, LE_CSR0,
|
||||
isr & (LE_C0_INEA | LE_C0_BABL | LE_C0_MISS | LE_C0_MERR |
|
||||
LE_C0_RINT | LE_C0_TINT | LE_C0_IDON));
|
||||
if (isr & LE_C0_ERR) {
|
||||
@ -641,7 +702,7 @@ leintr(arg)
|
||||
}
|
||||
if (isr & LE_C0_MERR) {
|
||||
printf("%s: memory error\n", sc->sc_dev.dv_xname);
|
||||
lereset(sc);
|
||||
am7990_reset(sc);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
@ -649,26 +710,38 @@ leintr(arg)
|
||||
if ((isr & LE_C0_RXON) == 0) {
|
||||
printf("%s: receiver disabled\n", sc->sc_dev.dv_xname);
|
||||
ifp->if_ierrors++;
|
||||
lereset(sc);
|
||||
am7990_reset(sc);
|
||||
return (1);
|
||||
}
|
||||
if ((isr & LE_C0_TXON) == 0) {
|
||||
printf("%s: transmitter disabled\n", sc->sc_dev.dv_xname);
|
||||
ifp->if_oerrors++;
|
||||
lereset(sc);
|
||||
am7990_reset(sc);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (isr & LE_C0_RINT)
|
||||
lerint(sc);
|
||||
am7990_rint(sc);
|
||||
if (isr & LE_C0_TINT)
|
||||
letint(sc);
|
||||
am7990_tint(sc);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
#undef ifp
|
||||
|
||||
void
|
||||
am7990_watchdog(ifp)
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct am7990_softc *sc = ifp->if_softc;
|
||||
|
||||
log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
|
||||
++ifp->if_oerrors;
|
||||
|
||||
am7990_reset(sc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup output on interface.
|
||||
* Get another datagram to send off of the interface queue, and map it to the
|
||||
@ -676,10 +749,10 @@ leintr(arg)
|
||||
* Called only at splimp or interrupt level.
|
||||
*/
|
||||
void
|
||||
lestart(ifp)
|
||||
am7990_start(ifp)
|
||||
register struct ifnet *ifp;
|
||||
{
|
||||
register struct le_softc *sc = LE_SOFTC(ifp->if_unit);
|
||||
register struct am7990_softc *sc = ifp->if_softc;
|
||||
register int bix;
|
||||
register struct mbuf *m;
|
||||
struct letmd tmd;
|
||||
@ -717,7 +790,7 @@ lestart(ifp)
|
||||
/*
|
||||
* Copy the mbuf chain into the transmit buffer.
|
||||
*/
|
||||
len = leput(sc, LE_TBUFADDR(sc, bix), m);
|
||||
len = am7990_put(sc, LE_TBUFADDR(sc, bix), m);
|
||||
|
||||
#ifdef LEDEBUG
|
||||
if (len > ETHERMTU + sizeof(struct ether_header))
|
||||
@ -737,10 +810,10 @@ lestart(ifp)
|
||||
|
||||
#ifdef LEDEBUG
|
||||
if (sc->sc_debug)
|
||||
xmit_print(sc, sc->sc_last_td);
|
||||
am7990_xmit_print(sc, sc->sc_last_td);
|
||||
#endif
|
||||
|
||||
lewrcsr(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
|
||||
(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
|
||||
|
||||
if (++bix == sc->sc_ntbuf)
|
||||
bix = 0;
|
||||
@ -759,12 +832,12 @@ lestart(ifp)
|
||||
* Process an ioctl request.
|
||||
*/
|
||||
int
|
||||
leioctl(ifp, cmd, data)
|
||||
am7990_ioctl(ifp, cmd, data)
|
||||
register struct ifnet *ifp;
|
||||
u_long cmd;
|
||||
caddr_t data;
|
||||
{
|
||||
struct le_softc *sc = LE_SOFTC(ifp->if_unit);
|
||||
register struct am7990_softc *sc = ifp->if_softc;
|
||||
struct ifaddr *ifa = (struct ifaddr *)data;
|
||||
struct ifreq *ifr = (struct ifreq *)data;
|
||||
int s, error = 0;
|
||||
@ -779,7 +852,7 @@ leioctl(ifp, cmd, data)
|
||||
switch (ifa->ifa_addr->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
leinit(sc);
|
||||
am7990_init(sc);
|
||||
arp_ifinit(&sc->sc_arpcom, ifa);
|
||||
break;
|
||||
#endif
|
||||
@ -796,12 +869,12 @@ leioctl(ifp, cmd, data)
|
||||
sc->sc_arpcom.ac_enaddr,
|
||||
sizeof(sc->sc_arpcom.ac_enaddr));
|
||||
/* Set new address. */
|
||||
leinit(sc);
|
||||
am7990_init(sc);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
leinit(sc);
|
||||
am7990_init(sc);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -812,7 +885,7 @@ leioctl(ifp, cmd, data)
|
||||
ifa->ifa_rtrequest = cons_rtrequest; /* XXX */
|
||||
error = x25_llcglue(PRC_IFUP, ifa->ifa_addr);
|
||||
if (error == 0)
|
||||
leinit(sc);
|
||||
am7990_init(sc);
|
||||
break;
|
||||
#endif /* CCITT && LLC */
|
||||
|
||||
@ -823,7 +896,7 @@ leioctl(ifp, cmd, data)
|
||||
* If interface is marked down and it is running, then
|
||||
* stop it.
|
||||
*/
|
||||
lestop(sc);
|
||||
am7990_stop(sc);
|
||||
ifp->if_flags &= ~IFF_RUNNING;
|
||||
} else if ((ifp->if_flags & IFF_UP) != 0 &&
|
||||
(ifp->if_flags & IFF_RUNNING) == 0) {
|
||||
@ -831,14 +904,14 @@ leioctl(ifp, cmd, data)
|
||||
* If interface is marked up and it is stopped, then
|
||||
* start it.
|
||||
*/
|
||||
leinit(sc);
|
||||
am7990_init(sc);
|
||||
} else {
|
||||
/*
|
||||
* Reset the interface to pick up changes in any other
|
||||
* flags that affect hardware registers.
|
||||
*/
|
||||
/*lestop(sc);*/
|
||||
leinit(sc);
|
||||
/*am7990_stop(sc);*/
|
||||
am7990_init(sc);
|
||||
}
|
||||
#ifdef LEDEBUG
|
||||
if (ifp->if_flags & IFF_DEBUG)
|
||||
@ -859,7 +932,7 @@ leioctl(ifp, cmd, data)
|
||||
* Multicast list has changed; set the hardware filter
|
||||
* accordingly.
|
||||
*/
|
||||
lereset(sc);
|
||||
am7990_reset(sc);
|
||||
error = 0;
|
||||
}
|
||||
break;
|
||||
@ -873,10 +946,18 @@ leioctl(ifp, cmd, data)
|
||||
return (error);
|
||||
}
|
||||
|
||||
hide void
|
||||
am7990_shutdown(arg)
|
||||
void *arg;
|
||||
{
|
||||
|
||||
am7990_stop((struct am7990_softc *)arg);
|
||||
}
|
||||
|
||||
#ifdef LEDEBUG
|
||||
void
|
||||
recv_print(sc, no)
|
||||
struct le_softc *sc;
|
||||
am7990_recv_print(sc, no)
|
||||
struct am7990_softc *sc;
|
||||
int no;
|
||||
{
|
||||
struct lermd rmd;
|
||||
@ -887,7 +968,8 @@ recv_print(sc, no)
|
||||
len = rmd.rmd3;
|
||||
printf("%s: receive buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
|
||||
len);
|
||||
printf("%s: status %04x\n", sc->sc_dev.dv_xname, lerdcsr(sc, LE_CSR0));
|
||||
printf("%s: status %04x\n", sc->sc_dev.dv_xname,
|
||||
(*sc->sc_rdcsr)(sc, LE_CSR0));
|
||||
printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
|
||||
sc->sc_dev.dv_xname,
|
||||
rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3);
|
||||
@ -901,8 +983,8 @@ recv_print(sc, no)
|
||||
}
|
||||
|
||||
void
|
||||
xmit_print(sc, no)
|
||||
struct le_softc *sc;
|
||||
am7990_xmit_print(sc, no)
|
||||
struct am7990_softc *sc;
|
||||
int no;
|
||||
{
|
||||
struct letmd tmd;
|
||||
@ -913,7 +995,8 @@ xmit_print(sc, no)
|
||||
len = -tmd.tmd2;
|
||||
printf("%s: transmit buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
|
||||
len);
|
||||
printf("%s: status %04x\n", sc->sc_dev.dv_xname, lerdcsr(sc, LE_CSR0));
|
||||
printf("%s: status %04x\n", sc->sc_dev.dv_xname,
|
||||
(*sc->sc_rdcsr)(sc, LE_CSR0));
|
||||
printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
|
||||
sc->sc_dev.dv_xname,
|
||||
tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3);
|
||||
@ -931,7 +1014,7 @@ xmit_print(sc, no)
|
||||
* Set up the logical address filter.
|
||||
*/
|
||||
void
|
||||
lesetladrf(ac, af)
|
||||
am7990_setladrf(ac, af)
|
||||
struct arpcom *ac;
|
||||
u_int16_t *af;
|
||||
{
|
||||
@ -1008,7 +1091,6 @@ allmulti:
|
||||
* (3) gap16 (16 bytes of data followed by 16 bytes of padding).
|
||||
*/
|
||||
|
||||
#ifdef LE_NEED_BUF_CONTIG
|
||||
/*
|
||||
* contig: contiguous data with no padding.
|
||||
*
|
||||
@ -1017,7 +1099,7 @@ allmulti:
|
||||
|
||||
void
|
||||
am7990_copytobuf_contig(sc, from, boff, len)
|
||||
struct le_softc *sc;
|
||||
struct am7990_softc *sc;
|
||||
void *from;
|
||||
int boff, len;
|
||||
{
|
||||
@ -1031,7 +1113,7 @@ am7990_copytobuf_contig(sc, from, boff, len)
|
||||
|
||||
void
|
||||
am7990_copyfrombuf_contig(sc, to, boff, len)
|
||||
struct le_softc *sc;
|
||||
struct am7990_softc *sc;
|
||||
void *to;
|
||||
int boff, len;
|
||||
{
|
||||
@ -1045,7 +1127,7 @@ am7990_copyfrombuf_contig(sc, to, boff, len)
|
||||
|
||||
void
|
||||
am7990_zerobuf_contig(sc, boff, len)
|
||||
struct le_softc *sc;
|
||||
struct am7990_softc *sc;
|
||||
int boff, len;
|
||||
{
|
||||
volatile caddr_t buf = sc->sc_mem;
|
||||
@ -1055,9 +1137,13 @@ am7990_zerobuf_contig(sc, boff, len)
|
||||
*/
|
||||
bzero(buf + boff, len);
|
||||
}
|
||||
#endif /* LE_NEED_BUF_CONTIG */
|
||||
|
||||
#ifdef LE_NEED_BUF_GAP2
|
||||
#if 0
|
||||
/*
|
||||
* Examples only; duplicate these and tweak (if necessary) in
|
||||
* machine-specific front-ends.
|
||||
*/
|
||||
|
||||
/*
|
||||
* gap2: two bytes of data followed by two bytes of pad.
|
||||
*
|
||||
@ -1067,7 +1153,7 @@ am7990_zerobuf_contig(sc, boff, len)
|
||||
|
||||
void
|
||||
am7990_copytobuf_gap2(sc, fromv, boff, len)
|
||||
struct le_softc *sc;
|
||||
struct am7990_softc *sc;
|
||||
void *fromv;
|
||||
int boff;
|
||||
register int len;
|
||||
@ -1096,7 +1182,7 @@ am7990_copytobuf_gap2(sc, fromv, boff, len)
|
||||
|
||||
void
|
||||
am7990_copyfrombuf_gap2(sc, tov, boff, len)
|
||||
struct le_softc *sc;
|
||||
struct am7990_softc *sc;
|
||||
void *tov;
|
||||
int boff, len;
|
||||
{
|
||||
@ -1126,7 +1212,7 @@ am7990_copyfrombuf_gap2(sc, tov, boff, len)
|
||||
|
||||
void
|
||||
am7990_zerobuf_gap2(sc, boff, len)
|
||||
struct le_softc *sc;
|
||||
struct am7990_softc *sc;
|
||||
int boff, len;
|
||||
{
|
||||
volatile caddr_t buf = sc->sc_mem;
|
||||
@ -1145,9 +1231,7 @@ am7990_zerobuf_gap2(sc, boff, len)
|
||||
len -= 2;
|
||||
}
|
||||
}
|
||||
#endif /* LE_NEED_BUF_GAP2 */
|
||||
|
||||
#ifdef LE_NEED_BUF_GAP16
|
||||
/*
|
||||
* gap16: 16 bytes of data followed by 16 bytes of pad.
|
||||
*
|
||||
@ -1156,7 +1240,7 @@ am7990_zerobuf_gap2(sc, boff, len)
|
||||
|
||||
void
|
||||
am7990_copytobuf_gap16(sc, fromv, boff, len)
|
||||
struct le_softc *sc;
|
||||
struct am7990_softc *sc;
|
||||
void *fromv;
|
||||
int boff;
|
||||
register int len;
|
||||
@ -1181,7 +1265,7 @@ am7990_copytobuf_gap16(sc, fromv, boff, len)
|
||||
|
||||
void
|
||||
am7990_copyfrombuf_gap16(sc, tov, boff, len)
|
||||
struct le_softc *sc;
|
||||
struct am7990_softc *sc;
|
||||
void *tov;
|
||||
int boff, len;
|
||||
{
|
||||
@ -1205,7 +1289,7 @@ am7990_copyfrombuf_gap16(sc, tov, boff, len)
|
||||
|
||||
void
|
||||
am7990_zerobuf_gap16(sc, boff, len)
|
||||
struct le_softc *sc;
|
||||
struct am7990_softc *sc;
|
||||
int boff, len;
|
||||
{
|
||||
volatile caddr_t buf = sc->sc_mem;
|
||||
@ -1223,4 +1307,4 @@ am7990_zerobuf_gap16(sc, boff, len)
|
||||
xfer = min(len, 16);
|
||||
}
|
||||
}
|
||||
#endif /* LE_NEED_BUF_GAP16 */
|
||||
#endif /* Example only */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: am7990var.h,v 1.6 1996/04/22 02:40:49 christos Exp $ */
|
||||
/* $NetBSD: am7990var.h,v 1.7 1996/05/07 01:38:37 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Charles M. Hannum. All rights reserved.
|
||||
@ -31,30 +31,97 @@
|
||||
|
||||
#ifdef DDB
|
||||
#define integrate
|
||||
#define hide
|
||||
#else
|
||||
#define integrate static __inline
|
||||
#define hide static
|
||||
#endif
|
||||
|
||||
void leconfig __P((struct le_softc *));
|
||||
void leinit __P((struct le_softc *));
|
||||
int leioctl __P((struct ifnet *, u_long, caddr_t));
|
||||
void lememinit __P((struct le_softc *));
|
||||
void lereset __P((struct le_softc *));
|
||||
void lesetladrf __P((struct arpcom *, u_int16_t *));
|
||||
void lestart __P((struct ifnet *));
|
||||
void lestop __P((struct le_softc *));
|
||||
void lewatchdog __P((int));
|
||||
/*
|
||||
* Ethernet software status per device.
|
||||
*
|
||||
* Each interface is referenced by a network interface structure,
|
||||
* arpcom.ac_if, which the routing code uses to locate the interface.
|
||||
* This structure contains the output queue for the interface, its address, ...
|
||||
*
|
||||
* NOTE: this structure MUST be the first element in machine-dependent
|
||||
* le_softc structures! This is designed SPECIFICALLY to make it possible
|
||||
* to simply cast a "void *" to "struct le_softc *" or to
|
||||
* "struct am7990_softc *". Among other things, this saves a lot of hair
|
||||
* in the interrupt handlers.
|
||||
*/
|
||||
struct am7990_softc {
|
||||
struct device sc_dev; /* base device glue */
|
||||
struct arpcom sc_arpcom; /* Ethernet common part */
|
||||
|
||||
integrate void lehwinit __P((struct le_softc *));
|
||||
integrate u_int16_t lerdcsr __P((struct le_softc *, u_int16_t));
|
||||
integrate void lewrcsr __P((struct le_softc *, u_int16_t, u_int16_t));
|
||||
/*
|
||||
* Memory functions:
|
||||
*
|
||||
* copy to/from descriptor
|
||||
* copy to/from buffer
|
||||
* zero bytes in buffer
|
||||
*/
|
||||
void (*sc_copytodesc)
|
||||
__P((struct am7990_softc *, void *, int, int));
|
||||
void (*sc_copyfromdesc)
|
||||
__P((struct am7990_softc *, void *, int, int));
|
||||
void (*sc_copytobuf)
|
||||
__P((struct am7990_softc *, void *, int, int));
|
||||
void (*sc_copyfrombuf)
|
||||
__P((struct am7990_softc *, void *, int, int));
|
||||
void (*sc_zerobuf)
|
||||
__P((struct am7990_softc *, int, int));
|
||||
|
||||
integrate void lerint __P((struct le_softc *));
|
||||
integrate void letint __P((struct le_softc *));
|
||||
/*
|
||||
* Machine-dependent functions:
|
||||
*
|
||||
* read/write CSR
|
||||
* hardware init hook - may be NULL
|
||||
*/
|
||||
u_int16_t (*sc_rdcsr)
|
||||
__P((struct am7990_softc *, u_int16_t));
|
||||
void (*sc_wrcsr)
|
||||
__P((struct am7990_softc *, u_int16_t, u_int16_t));
|
||||
void (*sc_hwinit) __P((struct am7990_softc *));
|
||||
|
||||
integrate int leput __P((struct le_softc *, int, struct mbuf *));
|
||||
integrate struct mbuf *leget __P((struct le_softc *, int, int));
|
||||
integrate void leread __P((struct le_softc *, int, int));
|
||||
void *sc_sh; /* shutdownhook cookie */
|
||||
|
||||
u_int16_t sc_conf3; /* CSR3 value */
|
||||
|
||||
void *sc_mem; /* base address of RAM -- CPU's view */
|
||||
u_long sc_addr; /* base address of RAM -- LANCE's view */
|
||||
|
||||
u_long sc_memsize; /* size of RAM */
|
||||
|
||||
int sc_nrbuf; /* number of receive buffers */
|
||||
int sc_ntbuf; /* number of transmit buffers */
|
||||
int sc_last_rd;
|
||||
int sc_first_td, sc_last_td, sc_no_td;
|
||||
|
||||
int sc_initaddr;
|
||||
int sc_rmdaddr;
|
||||
int sc_tmdaddr;
|
||||
int sc_rbufaddr;
|
||||
int sc_tbufaddr;
|
||||
|
||||
#ifdef LEDEBUG
|
||||
int sc_debug;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Export this to machine-dependent drivers. */
|
||||
extern struct cfdriver le_cd;
|
||||
|
||||
void am7990_config __P((struct am7990_softc *));
|
||||
void am7990_init __P((struct am7990_softc *));
|
||||
int am7990_ioctl __P((struct ifnet *, u_long, caddr_t));
|
||||
void am7990_meminit __P((struct am7990_softc *));
|
||||
void am7990_reset __P((struct am7990_softc *));
|
||||
void am7990_setladrf __P((struct arpcom *, u_int16_t *));
|
||||
void am7990_start __P((struct ifnet *));
|
||||
void am7990_stop __P((struct am7990_softc *));
|
||||
void am7990_watchdog __P((struct ifnet *));
|
||||
int am7990_intr __P((void *));
|
||||
|
||||
/*
|
||||
* The following functions are only useful on certain cpu/bus
|
||||
@ -62,18 +129,16 @@ integrate void leread __P((struct le_softc *, int, int));
|
||||
* maximum efficiency, but machine-independent versions are provided
|
||||
* for drivers that have not yet been optimized.
|
||||
*/
|
||||
#ifdef LE_NEED_BUF_CONTIG
|
||||
void am7990_copytobuf_contig __P((struct le_softc *, void *, int, int));
|
||||
void am7990_copyfrombuf_contig __P((struct le_softc *, void *, int, int));
|
||||
void am7990_zerobuf_contig __P((struct le_softc *, int, int));
|
||||
#endif /* LE_NEED_BUF_CONTIG */
|
||||
#ifdef LE_NEED_BUF_GAP2
|
||||
void am7990_copytobuf_gap2 __P((struct le_softc *, void *, int, int));
|
||||
void am7990_copyfrombuf_gap2 __P((struct le_softc *, void *, int, int));
|
||||
void am7990_zerobuf_gap2 __P((struct le_softc *, int, int));
|
||||
#endif /* LE_NEED_BUF_GAP2 */
|
||||
#ifdef LE_NEED_BUF_GAP16
|
||||
void am7990_copytobuf_gap16 __P((struct le_softc *, void *, int, int));
|
||||
void am7990_copyfrombuf_gap16 __P((struct le_softc *, void *, int, int));
|
||||
void am7990_zerobuf_gap16 __P((struct le_softc *, int, int));
|
||||
#endif /* LE_NEED_BUF_GAP16 */
|
||||
void am7990_copytobuf_contig __P((struct am7990_softc *, void *, int, int));
|
||||
void am7990_copyfrombuf_contig __P((struct am7990_softc *, void *, int, int));
|
||||
void am7990_zerobuf_contig __P((struct am7990_softc *, int, int));
|
||||
|
||||
#if 0 /* Example only - see am7990.c */
|
||||
void am7990_copytobuf_gap2 __P((struct am7990_softc *, void *, int, int));
|
||||
void am7990_copyfrombuf_gap2 __P((struct am7990_softc *, void *, int, int));
|
||||
void am7990_zerobuf_gap2 __P((struct am7990_softc *, int, int));
|
||||
|
||||
void am7990_copytobuf_gap16 __P((struct am7990_softc *, void *, int, int));
|
||||
void am7990_copyfrombuf_gap16 __P((struct am7990_softc *, void *, int, int));
|
||||
void am7990_zerobuf_gap16 __P((struct am7990_softc *, int, int));
|
||||
#endif /* Example only */
|
||||
|
Loading…
Reference in New Issue
Block a user