diff --git a/sys/dev/ic/am7990.c b/sys/dev/ic/am7990.c index 1e377fde93cc..221de6765750 100644 --- a/sys/dev/ic/am7990.c +++ b/sys/dev/ic/am7990.c @@ -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 +#include +#include +#include +#include +#include +#include #include #include +#include + #ifdef INET +#include +#include #include #include #include @@ -66,31 +79,81 @@ #include #endif +#include +#include + #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 */ diff --git a/sys/dev/ic/am7990var.h b/sys/dev/ic/am7990var.h index 4745d5540fb9..301a21589825 100644 --- a/sys/dev/ic/am7990var.h +++ b/sys/dev/ic/am7990var.h @@ -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 */