From: deraadt Date: Fri, 10 May 1996 12:41:10 +0000 (+0000) Subject: if_name/if_unit -> if_xname/if_softc X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=17fbbb3b790e8ed624256a5df53cfb81be81bdd4;p=openbsd if_name/if_unit -> if_xname/if_softc --- diff --git a/sys/dev/ic/am7990.c b/sys/dev/ic/am7990.c index 2b243bd2095..5f89ebb8e63 100644 --- a/sys/dev/ic/am7990.c +++ b/sys/dev/ic/am7990.c @@ -1,5 +1,5 @@ -/* $OpenBSD: am7990.c,v 1.7 1996/05/05 13:39:31 mickey Exp $ */ -/* $NetBSD: am7990.c,v 1.18 1996/04/22 02:40:50 christos Exp $ */ +/* $OpenBSD: am7990.c,v 1.8 1996/05/10 12:41:10 deraadt Exp $ */ +/* $NetBSD: am7990.c,v 1.19 1996/05/07 01:38:35 thorpej Exp $ */ /*- * Copyright (c) 1995 Charles M. Hannum. All rights reserved. @@ -40,10 +40,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 @@ -54,31 +67,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 @@ -111,13 +174,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); @@ -136,34 +203,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; @@ -183,7 +238,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; @@ -228,11 +283,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); } /* @@ -240,45 +295,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); } /* @@ -286,8 +343,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; { @@ -319,8 +376,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; @@ -367,8 +424,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; @@ -385,7 +442,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; @@ -441,8 +498,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; @@ -487,9 +544,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; @@ -515,8 +573,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; @@ -546,20 +604,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++; @@ -580,7 +641,7 @@ letint(sc) sc->sc_first_td = bix; - lestart(ifp); + am7990_start(ifp); if (sc->sc_no_td == 0) ifp->if_timer = 0; @@ -590,22 +651,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) { @@ -629,7 +690,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); } } @@ -637,26 +698,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 @@ -664,10 +737,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; @@ -705,7 +778,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)) @@ -725,10 +798,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; @@ -747,12 +820,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; @@ -772,12 +845,12 @@ 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 default: - leinit(sc); + am7990_init(sc); break; } break; @@ -789,7 +862,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) { @@ -797,14 +870,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) @@ -825,7 +898,7 @@ leioctl(ifp, cmd, data) * Multicast list has changed; set the hardware filter * accordingly. */ - lereset(sc); + am7990_reset(sc); error = 0; } break; @@ -839,10 +912,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; @@ -853,7 +934,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); @@ -867,8 +949,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; @@ -879,7 +961,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); @@ -897,7 +980,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; { @@ -974,7 +1057,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. * @@ -983,7 +1065,7 @@ allmulti: void am7990_copytobuf_contig(sc, from, boff, len) - struct le_softc *sc; + struct am7990_softc *sc; void *from; int boff, len; { @@ -997,7 +1079,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; { @@ -1011,7 +1093,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; @@ -1021,9 +1103,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. * @@ -1033,7 +1119,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; @@ -1062,7 +1148,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; { @@ -1092,7 +1178,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; @@ -1111,9 +1197,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. * @@ -1122,7 +1206,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; @@ -1147,7 +1231,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; { @@ -1171,7 +1255,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; @@ -1189,4 +1273,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 337bc871fb5..1aa1afd7442 100644 --- a/sys/dev/ic/am7990var.h +++ b/sys/dev/ic/am7990var.h @@ -1,5 +1,5 @@ -/* $OpenBSD: am7990var.h,v 1.4 1996/05/02 13:51:46 deraadt Exp $ */ -/* $NetBSD: am7990var.h,v 1.6 1996/04/22 02:40:49 christos Exp $ */ +/* $OpenBSD: am7990var.h,v 1.5 1996/05/10 12:41:11 deraadt Exp $ */ +/* $NetBSD: am7990var.h,v 1.7 1996/05/07 01:38:37 thorpej Exp $ */ /* * Copyright (c) 1995 Charles M. Hannum. All rights reserved. @@ -32,30 +32,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 */ + + /* + * 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)); + + /* + * 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 *)); + + void *sc_sh; /* shutdownhook cookie */ + + u_int16_t sc_conf3; /* CSR3 value */ -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)); + void *sc_mem; /* base address of RAM -- CPU's view */ + u_long sc_addr; /* base address of RAM -- LANCE's view */ -integrate void lerint __P((struct le_softc *)); -integrate void letint __P((struct le_softc *)); + u_long sc_memsize; /* size of RAM */ -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)); + 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 @@ -63,18 +130,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 */ diff --git a/sys/dev/ic/elink3.c b/sys/dev/ic/elink3.c index fa99384c50a..8eeba382af5 100644 --- a/sys/dev/ic/elink3.c +++ b/sys/dev/ic/elink3.c @@ -1,4 +1,4 @@ -/* $NetBSD: elink3.c,v 1.4 1996/05/03 19:08:47 christos Exp $ */ +/* $NetBSD: elink3.c,v 1.5 1996/05/07 01:43:13 thorpej Exp $ */ /* * Copyright (c) 1994 Herb Peyerl @@ -80,7 +80,7 @@ static int epstatus __P((struct ep_softc *)); void epinit __P((struct ep_softc *)); int epioctl __P((struct ifnet *, u_long, caddr_t)); void epstart __P((struct ifnet *)); -void epwatchdog __P((int)); +void epwatchdog __P((struct ifnet *)); void epreset __P((struct ep_softc *)); void epread __P((struct ep_softc *)); struct mbuf *epget __P((struct ep_softc *, int)); @@ -96,12 +96,11 @@ epconfig(sc, conn) struct ep_softc *sc; u_int conn; { + struct ifnet *ifp = &sc->sc_arpcom.ac_if; bus_chipset_tag_t bc = sc->sc_bc; bus_io_handle_t ioh = sc->sc_ioh; u_short i; - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - sc->ep_connectors = 0; if (conn & IS_AUI) { printf("aui"); @@ -139,8 +138,8 @@ epconfig(sc, conn) printf(" address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr)); - ifp->if_unit = sc->sc_dev.dv_unit; - ifp->if_name = ep_cd.cd_name; + bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); + ifp->if_softc = sc; ifp->if_start = epstart; ifp->if_ioctl = epioctl; ifp->if_watchdog = epwatchdog; @@ -294,7 +293,7 @@ void epstart(ifp) struct ifnet *ifp; { - register struct ep_softc *sc = ep_cd.cd_devs[ifp->if_unit]; + register struct ep_softc *sc = ifp->if_softc; bus_chipset_tag_t bc = sc->sc_bc; bus_io_handle_t ioh = sc->sc_ioh; struct mbuf *m, *m0; @@ -798,7 +797,7 @@ epioctl(ifp, cmd, data) u_long cmd; caddr_t data; { - struct ep_softc *sc = ep_cd.cd_devs[ifp->if_unit]; + struct ep_softc *sc = ifp->if_softc; struct ifaddr *ifa = (struct ifaddr *)data; struct ifreq *ifr = (struct ifreq *)data; int s, error = 0; @@ -893,10 +892,10 @@ epreset(sc) } void -epwatchdog(unit) - int unit; +epwatchdog(ifp) + struct ifnet *ifp; { - struct ep_softc *sc = ep_cd.cd_devs[unit]; + struct ep_softc *sc = ifp->if_softc; log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); ++sc->sc_arpcom.ac_if.if_oerrors; diff --git a/sys/dev/ic/i82595reg.h b/sys/dev/ic/i82595reg.h new file mode 100644 index 00000000000..9d6a9812f46 --- /dev/null +++ b/sys/dev/ic/i82595reg.h @@ -0,0 +1,219 @@ +/* $NetBSD: i82595reg.h,v 1.1 1996/05/06 21:36:51 is Exp $ */ + +/* + * Copyright (c) 1996, Ignatios Souvatzis. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Ignatios Souvatzis + * for the NetBSD project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Intel 82595 Ethernet chip register, bit, and structure definitions. + * + * Written by is with reference to Intel's i82595FX data sheet, with some + * clarification coming from looking at the Clarkson Packet Driver code for this + * chip written by Russ Nelson and others; + * + * and + * + * configuration EEPROM layout. Written with reference to Intels + * public "LAN595 Hardware and Software Specifications" document. + */ + +/* registers */ + +/* bank0 */ + +#define COMMAND_REG 0 /* available in any bank */ + +#define MC_SETUP_CMD 0x03 +#define XMT_CMD 0x04 +#define TDR_CMD 0x05 +#define DUMP_CMD 0x06 +#define DIAG_CMD 0x07 +#define RCV_ENABLE_CMD 0x08 +#define RCV_DISABLE_CMD 0x0a +#define RCV_STOP_CMD 0x0b +#define RESET_CMD 0x0e +#define TRISTATE_CMD 0x16 +#define NO_TRISTATE_CMD 0x17 +#define POWER_DOWN_CMD 0x18 +#define SLEEP_MODE_CMD 0x19 +#define NEGOTIATE_CMD 0x1a +#define RESUME_XMT_CMD 0x1c +#define SEL_RESET_CMD 0x1e +#define BANK_SEL(n) (n<<6) /* 0, 1, 2 */ + +#define STATUS_REG 1 + +#define RX_STP_INT 0x01 +#define RX_INT 0x02 +#define TX_INT 0x04 +#define EXEC_INT 0x08 +#define EXEC_STATUS 0x30 + +#define ID_REG 2 + +#define ID_REG_MASK 0x2c +#define ID_REG_SIG 0x24 +#define R_ROBIN_BITS 0xc0 +#define R_ROBIN_SHIFT 6 +#define AUTO_ENABLE 0x10 + +#define INT_MASK_REG 3 + +#define RX_STOP_BIT 0x01 +#define RX_BIT 0x02 +#define TX_BIT 0x04 +#define EXEC_BIT 0x08 +#define ALL_INTS 0x0f + +#define RCV_START_LOW 4 +#define RCV_START_HIGH 5 + +#define RCV_STOP_LOW 6 +#define RCV_STOP_HIGH 7 + +#define XMT_ADDR_REG 0x0a +#define HOST_ADDR_REG 0x0c +#define MEM_PORT_REG 0x0e + +/* -------------------- bank1 -------------------- */ + +#define REG1 1 + +#define WORD_WIDTH 0x02 +#define INT_ENABLE 0x80 + +#define INT_NO_REG 2 + +#define RCV_LOWER_LIMIT_REG 8 +#define RCV_UPPER_LIMIT_REG 9 + +#define XMT_LOWER_LIMIT_REG 10 +#define XMT_UPPER_LIMIT_REG 11 + +/* bank2 */ + +/* reg1, apparently */ + +#define XMT_CHAIN_INT 0x20 /* interupt at end of xmt chain */ +#define XMT_CHAIN_ERRSTOP 0x40 /* int at end of chain even if err */ +#define RCV_DISCARD_BAD 0x80 /* Throw bad frames away and continue */ + +#define RECV_MODES_REG 2 + +#define PROMISC_MODE 0x01 +#define NO_RX_CRC 0x04 +#define NO_ADD_INS 0x10 +#define MULTI_IA 0x20 + +#define MATCH_ID (NO_ADD_INS | NO_RX_CRC | 0x02) +#define MATCH_ALL (NO_ADD_INS | NO_RX_CRC | 0x01) +#define MATCH_BRDCST (NO_ADD_INS | NO_RX_CRC) + +#define MEDIA_SELECT 3 + +#define TPE_BIT 0x04 +#define BNC_BIT 0x20 +#define TEST_MODE_MASK 0x3f + +#define I_ADD(n) (n+4) /* 0..5 -> 4..9 */ + +#define EEPROM_REG 10 + +#define EEDO 8 +#define EEDI 4 +#define EECS 2 +#define EESK 1 + +/* + * EEPROM layout. Written with reference to Intels public "LAN595 Hardware and + * Software Specifications" document. + */ + +#define EEPPW0 0 +#define EEPP_BusWidth 0x0004 +#define EEPP_FlashAdrs 0x0038 +#define EEPP_FLASHTRANSFORM {-1, -1, 0xC8000, 0xCC000, 0xD0000, \ + 0xD4000, 0xD8000, 0xDC000} +#define EEPP_AutoIO 0x0040 +#define EEPP_IOMapping 0xfc00 + +#define EEPPW1 1 +#define EEPP_Int 0x0007 +#define EEPP_INTMAP {3, 5, 9, 10, 11, -1, -1, -1} +#define EEPP_RINTMAP {0xff, 0xff, 0x02, 0x00, 0xff, 0x01, 0xff, \ + 0xff, 0xff, 0x02, 0x03, 0x04 } + +#define EEPP_LinkInteg 0x0008 +#define EEPP_PolarCorr 0x0010 +#define EEPP_AuiTpe 0x0020 +#define EEPP_Jabber 0x0040 +#define EEPP_AutoPort 0x0080 +#define EEPP_SmOut 0x0100 +#define EEPP_BootFls 0x0200 +#define EEPP_DramSize 0x1000 +#define EEPP_AltReady 0x2000 + +#define EEPPEther2 2 +#define EEPPEther1 3 +#define EEPPEther0 4 + +#define EEPPEther2a 0x3c +#define EEPPEther1a 0x3d +#define EEPPEther0a 0x3e + +#define EEPPW5 5 +#define EEPP_BncTpe 0x0001 +#define EEPP_RomSlct 0x0006 /* none, NetWare, NDIS, rsrvd. */ +#define EEPP_NumConn 0x0008 /* 0=2, 1=3 */ + +#define EEPW6 6 +#define EEPP_BoardRev 0x00FF + +#define EEPP_LENGTH 0x40 +#define EEPP_CHKSUM 0xBABA /* Intel claim 0x0, but this seems to be wrong */ + +#define I595_XMT_HDRLEN 8 + +#define CMD_MASK 0x001f +#define TX_DONE 0x0080 +#define CHAIN 0x8000 + +#define XMT_STATUS 0x02 +#define XMT_CHAIN 0x04 +#define XMT_COUNT 0x06 + +#define I595_RCV_HDRLEN 8 + +#define RCV_DONE 0x0008 +#define RX_OK 0x2000 +#define RX_ERR 0x0d81 + + diff --git a/sys/dev/ic/pdq_ifsubr.c b/sys/dev/ic/pdq_ifsubr.c index 13fe3f58900..4526538ab41 100644 --- a/sys/dev/ic/pdq_ifsubr.c +++ b/sys/dev/ic/pdq_ifsubr.c @@ -1,5 +1,5 @@ -/* $OpenBSD: pdq_ifsubr.c,v 1.1 1996/04/18 23:47:23 niklas Exp $ */ -/* $NetBSD: pdq_ifsubr.c,v 1.2 1996/03/11 21:41:32 thorpej Exp $ */ +/* $OpenBSD: pdq_ifsubr.c,v 1.2 1996/05/10 12:41:12 deraadt Exp $ */ +/* $NetBSD: pdq_ifsubr.c,v 1.3 1996/05/07 01:43:15 thorpej Exp $ */ /*- * Copyright (c) 1995 Matt Thomas (thomas@lkg.dec.com) @@ -407,8 +407,8 @@ pdq_ifioctl( void pdq_ifattach( pdq_softc_t *sc, - ifnet_ret_t (*ifinit)(int unit), - ifnet_ret_t (*ifwatchdog)(int unit)) + pdq_ifinit_t ifinit, + pdq_ifwatchdog_t ifwatchdog) { struct ifnet *ifp = &sc->sc_if; diff --git a/sys/dev/ic/pdqvar.h b/sys/dev/ic/pdqvar.h index d4ebce5e453..3b40d483578 100644 --- a/sys/dev/ic/pdqvar.h +++ b/sys/dev/ic/pdqvar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: pdqvar.h,v 1.2 1996/04/18 23:47:25 niklas Exp $ */ -/* $NetBSD: pdqvar.h,v 1.4 1996/03/11 21:41:35 thorpej Exp $ */ +/* $OpenBSD: pdqvar.h,v 1.3 1996/05/10 12:41:13 deraadt Exp $ */ +/* $NetBSD: pdqvar.h,v 1.5 1996/05/07 01:43:17 thorpej Exp $ */ /*- * Copyright (c) 1995 Matt Thomas (thomas@lkg.dec.com) @@ -142,13 +142,21 @@ typedef struct { #define sc_if sc_ac.ac_if #define sc_bpf sc_if.if_bpf +#if defined(__NetBSD__) +typedef ifnet_ret_t (*pdq_ifwatchdog_t)(struct ifnet *ifp); +typedef ifnet_ret_t (*pdq_ifinit_t)(struct ifnet *ifp); +#else +typedef ifnet_ret_t (*pdq_ifwatchdog_t)(int unit); +typedef ifnet_ret_t (*pdq_ifinit_t)(int unit); +#endif + extern void pdq_ifreset(pdq_softc_t *sc); extern void pdq_ifinit(pdq_softc_t *sc); extern void pdq_ifwatchdog(pdq_softc_t *sc); extern ifnet_ret_t pdq_ifstart(struct ifnet *ifp); extern int pdq_ifioctl(struct ifnet *ifp, ioctl_cmd_t cmd, caddr_t data); -extern void pdq_ifattach(pdq_softc_t *sc, ifnet_ret_t (*ifinit)(int unit), - ifnet_ret_t (*ifwatchdog)(int unit)); +extern void pdq_ifattach(pdq_softc_t *sc, pdq_ifinit_t ifinit, + pdq_ifwatchdog_t ifwatchdog); #endif /* PDQ_HWSUPPORT */ #elif defined(DLPI_PDQ) #include diff --git a/sys/dev/ic/smc90cx6.c b/sys/dev/ic/smc90cx6.c index afa12df2b80..7b45e10a9d4 100644 --- a/sys/dev/ic/smc90cx6.c +++ b/sys/dev/ic/smc90cx6.c @@ -1,4 +1,4 @@ -/* $NetBSD: smc90cx6.c,v 1.16 1996/03/20 13:28:50 is Exp $ */ +/* $NetBSD: smc90cx6.c,v 1.17 1996/05/07 01:43:18 thorpej Exp $ */ /* * Copyright (c) 1994, 1995 Ignatios Souvatzis @@ -183,7 +183,7 @@ void bah_stop __P((struct bah_softc *)); void bah_start __P((struct ifnet *)); int bahintr __P((struct bah_softc *sc)); int bah_ioctl __P((struct ifnet *, unsigned long, caddr_t)); -void bah_watchdog __P((int)); +void bah_watchdog __P((struct ifnet *)); void movepout __P((u_char *from, u_char __volatile *to, int len)); void movepin __P((u_char __volatile *from, u_char *to, int len)); void bah_srint __P((void *vsc, void *dummy)); @@ -272,8 +272,8 @@ bah_zbus_attach(parent, self, aux) */ bah_stop(sc); - ifp->if_unit = sc->sc_dev.dv_unit; - ifp->if_name = bah_cd.cd_name; + bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); + ifp->if_softc = sc; ifp->if_output = arc_output; ifp->if_start = bah_start; ifp->if_ioctl = bah_ioctl; @@ -360,8 +360,8 @@ bah_reset(sc) linkaddress = sc->sc_base->dipswitches; #if defined(BAH_DEBUG) && (BAH_DEBUG > 2) - printf("bah%ld: reset: card reset, link addr = 0x%02x (%ld)\n", - ifp->if_unit, linkaddress, linkaddress); + printf("%s: reset: card reset, link addr = 0x%02x (%ld)\n", + sc->sc_dev.dv_xname, linkaddress, linkaddress); #endif sc->sc_arccom.ac_anaddr = linkaddress; @@ -540,7 +540,7 @@ bah_start(ifp) u_long copystart, lencopy, perbyte; #endif - sc = bah_cd.cd_devs[ifp->if_unit]; + sc = ifp->if_softc; #if defined(BAH_DEBUG) && (BAH_DEBUG > 3) printf("%s: start(0x%x)\n", sc->sc_dev.dv_xname, ifp); @@ -1150,7 +1150,7 @@ bah_ioctl(ifp, command, data) int s, error; error = 0; - sc = bah_cd.cd_devs[ifp->if_unit]; + sc = ifp->if_softc; ifa = (struct ifaddr *)data; s = splnet(); @@ -1217,14 +1217,10 @@ bah_ioctl(ifp, command, data) */ void -bah_watchdog(unit) -int unit; -{ - struct bah_softc *sc; +bah_watchdog(ifp) struct ifnet *ifp; - - sc = bah_cd.cd_devs[unit]; - ifp = &(sc->sc_arccom.ac_if); +{ + struct bah_softc *sc = ifp->if_softc; sc->sc_base->command = ARC_TXDIS; return; diff --git a/sys/dev/isa/if_ed.c b/sys/dev/isa/if_ed.c index 5435c1fcdc2..d520b509d41 100644 --- a/sys/dev/isa/if_ed.c +++ b/sys/dev/isa/if_ed.c @@ -1,5 +1,5 @@ -/* $OpenBSD: if_ed.c,v 1.14 1996/05/07 07:36:47 deraadt Exp $ */ -/* $NetBSD: if_ed.c,v 1.96 1996/05/03 19:05:30 christos Exp $ */ +/* $OpenBSD: if_ed.c,v 1.15 1996/05/10 12:41:16 deraadt Exp $ */ +/* $NetBSD: if_ed.c,v 1.98 1996/05/07 01:55:13 thorpej Exp $ */ /* * Device driver for National Semiconductor DS8390/WD83C690 based ethernet @@ -77,6 +77,7 @@ struct ed_softc { bus_chipset_tag_t sc_bc; /* bus identifier */ bus_io_handle_t sc_ioh; /* io handle */ + bus_io_handle_t sc_delayioh; /* io handle for `delay port' */ bus_mem_handle_t sc_memh; /* bus memory handle */ bus_io_size_t asic_base; /* offset of ASIC I/O port */ @@ -128,7 +129,7 @@ int ed_find_Novell __P((struct ed_softc *, struct cfdata *, int edintr __P((void *)); int edioctl __P((struct ifnet *, u_long, caddr_t)); void edstart __P((struct ifnet *)); -void edwatchdog __P((int)); +void edwatchdog __P((struct ifnet *)); void edreset __P((struct ed_softc *)); void edinit __P((struct ed_softc *)); void edstop __P((struct ed_softc *)); @@ -451,6 +452,7 @@ ed_find_WD80x3(sc, cf, ia) { bus_chipset_tag_t bc; bus_io_handle_t ioh; + bus_io_handle_t delayioh = ia->ia_delayioh; bus_mem_handle_t memh; u_int memsize; u_char iptr, isa16bit, sum; @@ -537,7 +539,8 @@ ed_find_WD80x3(sc, cf, ia) isa16bit = 1; break; case ED_TYPE_WD8013EP: /* also WD8003EP */ - if (inb(asicbase + ED_WD_ICR) & ED_WD_ICR_16BIT) { + if (bus_io_read_1(bc, ioh, asicbase + ED_WD_ICR) + & ED_WD_ICR_16BIT) { isa16bit = 1; memsize = 16384; sc->type_str = "WD8013EP"; @@ -788,8 +791,8 @@ ed_find_WD80x3(sc, cf, ia) bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR, sc->wd_msr_proto | ED_WD_MSR_MENB); - (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */ - (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */ + (void) bus_io_read_1(bc, delayioh, 0); + (void) bus_io_read_1(bc, delayioh, 0); /* Now zero memory and verify that it is clear. */ for (i = 0; i < memsize; ++i) @@ -807,8 +810,8 @@ ed_find_WD80x3(sc, cf, ia) if (isa16bit) bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR, sc->wd_laar_proto); - (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */ - (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */ + (void) bus_io_read_1(bc, delayioh, 0); + (void) bus_io_read_1(bc, delayioh, 0); goto out; } @@ -824,8 +827,8 @@ ed_find_WD80x3(sc, cf, ia) if (isa16bit) bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR, sc->wd_laar_proto); - (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */ - (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */ + (void) bus_io_read_1(bc, delayioh, 0); + (void) bus_io_read_1(bc, delayioh, 0); ia->ia_iosize = ED_WD_IO_PORTS; rv = 1; @@ -1399,13 +1402,14 @@ edattach(parent, self, aux) ioh = sc->sc_ioh; /* XXX */ asicbase = sc->asic_base; + sc->sc_delayioh = ia->ia_delayioh; /* Set interface to stopped condition (reset). */ edstop(sc); /* Initialize ifnet structure. */ - ifp->if_unit = sc->sc_dev.dv_unit; - ifp->if_name = ed_cd.cd_name; + bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); + ifp->if_softc = sc; ifp->if_start = edstart; ifp->if_ioctl = edioctl; ifp->if_watchdog = edwatchdog; @@ -1518,10 +1522,10 @@ edstop(sc) * an interrupt after a transmit has been started on it. */ void -edwatchdog(unit) - int unit; +edwatchdog(ifp) + struct ifnet *ifp; { - struct ed_softc *sc = ed_cd.cd_devs[unit]; + struct ed_softc *sc = ifp->if_softc; log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); ++sc->sc_arpcom.ac_if.if_oerrors; @@ -1735,7 +1739,7 @@ void edstart(ifp) struct ifnet *ifp; { - struct ed_softc *sc = ed_cd.cd_devs[ifp->if_unit]; + struct ed_softc *sc = ifp->if_softc; bus_chipset_tag_t bc = sc->sc_bc; bus_io_handle_t ioh = sc->sc_ioh; struct mbuf *m0, *m; @@ -1796,8 +1800,8 @@ outloop: sc->wd_laar_proto | ED_WD_LAAR_M16EN); bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR, sc->wd_msr_proto | ED_WD_MSR_MENB); - (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */ - (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */ + (void) bus_io_read_1(bc, sc->sc_delayioh, 0); + (void) bus_io_read_1(bc, sc->sc_delayioh, 0); break; } @@ -1822,8 +1826,8 @@ outloop: if (sc->isa16bit) bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR, sc->wd_laar_proto); - (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */ - (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */ + (void) bus_io_read_1(bc, sc->sc_delayioh, 0); + (void) bus_io_read_1(bc, sc->sc_delayioh, 0); break; } } else @@ -2118,9 +2122,10 @@ edintr(arg) bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR, sc->wd_msr_proto | ED_WD_MSR_MENB); - /* XXX */ - (void) bus_io_read_1(bc, ioh, 0x84); - (void) bus_io_read_1(bc, ioh, 0x84); + (void) bus_io_read_1(bc, + sc->sc_delayioh, 0); + (void) bus_io_read_1(bc, + sc->sc_delayioh, 0); } ed_rint(sc); @@ -2134,9 +2139,10 @@ edintr(arg) bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR, sc->wd_laar_proto); - /* XXX */ - (void) bus_io_read_1(bc, ioh, 0x84); - (void) bus_io_read_1(bc, ioh, 0x84); + (void) bus_io_read_1(bc, + sc->sc_delayioh, 0); + (void) bus_io_read_1(bc, + sc->sc_delayioh, 0); } } } @@ -2183,7 +2189,7 @@ edioctl(ifp, cmd, data) u_long cmd; caddr_t data; { - struct ed_softc *sc = ed_cd.cd_devs[ifp->if_unit]; + struct ed_softc *sc = ifp->if_softc; register struct ifaddr *ifa = (struct ifaddr *)data; struct ifreq *ifr = (struct ifreq *)data; int s, error = 0; diff --git a/sys/dev/isa/if_eg.c b/sys/dev/isa/if_eg.c index c51baf8aaae..463bbb05457 100644 --- a/sys/dev/isa/if_eg.c +++ b/sys/dev/isa/if_eg.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_eg.c,v 1.24 1996/04/11 22:29:03 cgd Exp $ */ +/* $NetBSD: if_eg.c,v 1.25 1996/05/07 01:55:17 thorpej Exp $ */ /* * Copyright (c) 1993 Dean Huxley @@ -125,7 +125,7 @@ void eginit __P((struct eg_softc *)); int egioctl __P((struct ifnet *, u_long, caddr_t)); void egrecv __P((struct eg_softc *)); void egstart __P((struct ifnet *)); -void egwatchdog __P((int)); +void egwatchdog __P((struct ifnet *)); void egreset __P((struct eg_softc *)); void egread __P((struct eg_softc *, caddr_t, int)); struct mbuf *egget __P((struct eg_softc *, caddr_t, int)); @@ -396,8 +396,8 @@ egattach(parent, self, aux) } /* Initialize ifnet structure. */ - ifp->if_unit = sc->sc_dev.dv_unit; - ifp->if_name = eg_cd.cd_name; + bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); + ifp->if_softc = sc; ifp->if_start = egstart; ifp->if_ioctl = egioctl; ifp->if_watchdog = egwatchdog; @@ -475,8 +475,8 @@ egrecv(sc) sc->eg_pcb[3] = 0; sc->eg_pcb[4] = 0; sc->eg_pcb[5] = 0; - sc->eg_pcb[6] = EG_BUFLEN; /* our buffer size */ - sc->eg_pcb[7] = EG_BUFLEN >> 8; + sc->eg_pcb[6] = EG_BUFLEN & 0xff; /* our buffer size */ + sc->eg_pcb[7] = (EG_BUFLEN >> 8) & 0xff; sc->eg_pcb[8] = 0; /* timeout, 0 == none */ sc->eg_pcb[9] = 0; if (egwritePCB(sc) != 0) @@ -489,7 +489,7 @@ void egstart(ifp) struct ifnet *ifp; { - register struct eg_softc *sc = eg_cd.cd_devs[ifp->if_unit]; + register struct eg_softc *sc = ifp->if_softc; struct mbuf *m0, *m; caddr_t buffer; int len; @@ -728,7 +728,7 @@ egioctl(ifp, cmd, data) u_long cmd; caddr_t data; { - struct eg_softc *sc = eg_cd.cd_devs[ifp->if_unit]; + struct eg_softc *sc = ifp->if_softc; struct ifaddr *ifa = (struct ifaddr *)data; struct ifreq *ifr = (struct ifreq *)data; int s, error = 0; @@ -810,10 +810,10 @@ egreset(sc) } void -egwatchdog(unit) - int unit; +egwatchdog(ifp) + struct ifnet *ifp; { - struct eg_softc *sc = eg_cd.cd_devs[unit]; + struct eg_softc *sc = ifp->if_softc; log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); sc->sc_arpcom.ac_if.if_oerrors++; diff --git a/sys/dev/isa/if_el.c b/sys/dev/isa/if_el.c index 42213f55926..692b84108ff 100644 --- a/sys/dev/isa/if_el.c +++ b/sys/dev/isa/if_el.c @@ -1,5 +1,5 @@ -/* $OpenBSD: if_el.c,v 1.9 1996/05/07 07:36:53 deraadt Exp $ */ -/* $NetBSD: if_el.c,v 1.37 1996/04/29 20:03:17 christos Exp $ */ +/* $OpenBSD: if_el.c,v 1.10 1996/05/10 12:41:18 deraadt Exp $ */ +/* $NetBSD: if_el.c,v 1.38 1996/05/07 01:55:20 thorpej Exp $ */ /* * Copyright (c) 1994, Matthew E. Kimmel. Permission is hereby granted @@ -82,7 +82,7 @@ int elintr __P((void *)); void elinit __P((struct el_softc *)); int elioctl __P((struct ifnet *, u_long, caddr_t)); void elstart __P((struct ifnet *)); -void elwatchdog __P((int)); +void elwatchdog __P((struct ifnet *)); void elreset __P((struct el_softc *)); void elstop __P((struct el_softc *)); static int el_xmit __P((struct el_softc *)); @@ -184,8 +184,8 @@ elattach(parent, self, aux) elstop(sc); /* Initialize ifnet structure. */ - ifp->if_unit = sc->sc_dev.dv_unit; - ifp->if_name = el_cd.cd_name; + bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); + ifp->if_softc = sc; ifp->if_start = elstart; ifp->if_ioctl = elioctl; ifp->if_watchdog = elwatchdog; @@ -303,7 +303,7 @@ void elstart(ifp) struct ifnet *ifp; { - struct el_softc *sc = el_cd.cd_devs[ifp->if_unit]; + struct el_softc *sc = ifp->if_softc; int iobase = sc->sc_iobase; struct mbuf *m, *m0; int s, i, off, retries; @@ -615,7 +615,7 @@ elioctl(ifp, cmd, data) u_long cmd; caddr_t data; { - struct el_softc *sc = el_cd.cd_devs[ifp->if_unit]; + struct el_softc *sc = ifp->if_softc; struct ifaddr *ifa = (struct ifaddr *)data; int s, error = 0; @@ -682,10 +682,10 @@ elioctl(ifp, cmd, data) * Device timeout routine. */ void -elwatchdog(unit) - int unit; +elwatchdog(ifp) + struct ifnet *ifp; { - struct el_softc *sc = el_cd.cd_devs[unit]; + struct el_softc *sc = ifp->if_softc; log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); sc->sc_arpcom.ac_if.if_oerrors++; diff --git a/sys/dev/isa/if_fe.c b/sys/dev/isa/if_fe.c index baa3f87796c..7f1a21191fe 100644 --- a/sys/dev/isa/if_fe.c +++ b/sys/dev/isa/if_fe.c @@ -201,7 +201,7 @@ void fe_init __P((struct fe_softc *)); int fe_ioctl __P((struct ifnet *, u_long, caddr_t)); void fe_start __P((struct ifnet *)); void fe_reset __P((struct fe_softc *)); -void fe_watchdog __P((int)); +void fe_watchdog __P((struct ifnet *)); /* Local functions. Order of declaration is confused. FIXME. */ int fe_probe_fmv __P((struct fe_softc *, struct isa_attach_args *)); @@ -991,8 +991,8 @@ feattach(parent, self, aux) fe_stop(sc); /* Initialize ifnet structure. */ - ifp->if_unit = sc->sc_dev.dv_unit; - ifp->if_name = fe_cd.cd_name; + bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); + ifp->if_softc = sc; ifp->if_start = fe_start; ifp->if_ioctl = fe_ioctl; ifp->if_watchdog = fe_watchdog; @@ -1194,10 +1194,10 @@ fe_stop(sc) * generate an interrupt after a transmit has been started on it. */ void -fe_watchdog(unit) - int unit; +fe_watchdog(ifp) + struct ifnet *ifp; { - struct fe_softc *sc = fe_cd.cd_devs[unit]; + struct fe_softc *sc = ifp->if_softc; log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); #if FE_DEBUG >= 3 @@ -1419,7 +1419,7 @@ void fe_start(ifp) struct ifnet *ifp; { - struct fe_softc *sc = fe_cd.cd_devs[ifp->if_unit]; + struct fe_softc *sc = ifp->if_softc; struct mbuf *m; #if FE_DEBUG >= 1 @@ -1920,7 +1920,7 @@ fe_ioctl(ifp, command, data) u_long command; caddr_t data; { - struct fe_softc *sc = fe_cd.cd_devs[ifp->if_unit]; + struct fe_softc *sc = ifp->if_softc; register struct ifaddr *ifa = (struct ifaddr *)data; struct ifreq *ifr = (struct ifreq *)data; int s, error = 0; diff --git a/sys/dev/isa/if_ie.c b/sys/dev/isa/if_ie.c index 8c2926131c8..77c99075c63 100644 --- a/sys/dev/isa/if_ie.c +++ b/sys/dev/isa/if_ie.c @@ -1,5 +1,5 @@ -/* $OpenBSD: if_ie.c,v 1.9 1996/05/07 07:36:59 deraadt Exp $ */ -/* $NetBSD: if_ie.c,v 1.49 1996/04/30 22:21:54 thorpej Exp $ */ +/* $OpenBSD: if_ie.c,v 1.10 1996/05/10 12:41:20 deraadt Exp $ */ +/* $NetBSD: if_ie.c,v 1.50 1996/05/07 01:55:25 thorpej Exp $ */ /*- * Copyright (c) 1993, 1994, 1995 Charles Hannum. @@ -261,7 +261,7 @@ struct ie_softc { #endif }; -void iewatchdog __P((int)); +void iewatchdog __P((struct ifnet *)); int ieintr __P((void *)); void iestop __P((struct ie_softc *)); int ieinit __P((struct ie_softc *)); @@ -788,8 +788,8 @@ ieattach(parent, self, aux) struct isa_attach_args *ia = aux; struct ifnet *ifp = &sc->sc_arpcom.ac_if; - ifp->if_unit = sc->sc_dev.dv_unit; - ifp->if_name = ie_cd.cd_name; + bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); + ifp->if_softc = sc; ifp->if_start = iestart; ifp->if_ioctl = ieioctl; ifp->if_watchdog = iewatchdog; @@ -818,10 +818,10 @@ ieattach(parent, self, aux) * an interrupt after a transmit has been started on it. */ void -iewatchdog(unit) - int unit; +iewatchdog(ifp) + struct ifnet *ifp; { - struct ie_softc *sc = ie_cd.cd_devs[unit]; + struct ie_softc *sc = ifp->if_softc; log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); ++sc->sc_arpcom.ac_if.if_oerrors; @@ -1473,7 +1473,7 @@ void iestart(ifp) struct ifnet *ifp; { - struct ie_softc *sc = ie_cd.cd_devs[ifp->if_unit]; + struct ie_softc *sc = ifp->if_softc; struct mbuf *m0, *m; u_char *buffer; u_short len; @@ -2142,7 +2142,7 @@ ieioctl(ifp, cmd, data) u_long cmd; caddr_t data; { - struct ie_softc *sc = ie_cd.cd_devs[ifp->if_unit]; + struct ie_softc *sc = ifp->if_softc; struct ifaddr *ifa = (struct ifaddr *)data; struct ifreq *ifr = (struct ifreq *)data; int s, error = 0; diff --git a/sys/dev/isa/if_iy.c b/sys/dev/isa/if_iy.c new file mode 100644 index 00000000000..2e8ee044b67 --- /dev/null +++ b/sys/dev/isa/if_iy.c @@ -0,0 +1,1353 @@ +/* $NetBSD: if_iy.c,v 1.2 1996/05/07 01:55:28 thorpej Exp $ */ +/* #define IYDEBUG */ +/* #define IYMEMDEBUG */ +/*- + * Copyright (c) 1996 Ignatios Souvatzis. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product contains software developed by Ignatios Souvatzis for + * the NetBSD project. + * 4. The names of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "bpfilter.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#if NBPFILTER > 0 +#include +#include +#endif + +#ifdef INET +#include +#include +#include +#include +#include +#endif + +#ifdef NS +#include +#include +#endif + +#include + +#include +#include + +#include +#include +#include + +#define ETHER_MIN_LEN 64 +#define ETHER_MAX_LEN 1518 + +/* + * Ethernet status, per interface. + */ +struct iy_softc { + struct device sc_dev; + void *sc_ih; + + int sc_iobase; + struct arpcom sc_arpcom; + +#define MAX_MBS 8 + struct mbuf *mb[MAX_MBS]; + int next_mb, last_mb; + + int mappedirq; + + int hard_vers; + + int promisc; + + int sram, tx_size, rx_size; + + int tx_start, tx_end, tx_last; + int rx_start; + +#ifdef IYDEBUG + int sc_debug; +#endif +}; + +void iywatchdog __P((struct ifnet *)); +int iyioctl __P((struct ifnet *, u_long, caddr_t)); +int iyintr __P((void *)); +void iyinit __P((struct iy_softc *)); +void iystop __P((struct iy_softc *)); +void iystart __P((struct ifnet *)); + +void iy_intr_rx __P((struct iy_softc *)); +void iy_intr_tx __P((struct iy_softc *)); +void eepro_reset_595 __P((struct iy_softc *)); +int eepro_probe __P((struct iy_softc *, struct isa_attach_args *)); +void eepro_eeprom_outbits __P((struct iy_softc *, int, int)); +void eepro_eeprom_clock __P((struct iy_softc *, int)); +u_short eepro_read_eeprom __P((struct iy_softc *, int)); +int eepro_eeprom_inbits __P((struct iy_softc *)); + +void iyreset __P((struct iy_softc *)); +void iy_readframe __P((struct iy_softc *, int)); +void iy_drop_packet_buffer __P((struct iy_softc *)); +void iy_find_mem_size __P((struct iy_softc *)); +void iyrint __P((struct iy_softc *)); +void iytint __P((struct iy_softc *)); +void iyxmit __P((struct iy_softc *)); +void iyget __P((struct iy_softc *, int, int)); +void iymbuffill __P((void *)); +void iymbufempty __P((void *)); +void iyprobemem __P((struct iy_softc *)); + +/* + * void iymeminit __P((void *, struct iy_softc *)); + * static int iy_mc_setup __P((struct iy_softc *, void *)); + * static void iy_mc_reset __P((struct iy_softc *)); + */ +#ifdef IYDEBUGX +void print_rbd __P((volatile struct iy_recv_buf_desc *)); + +int in_ifrint = 0; +int in_iftint = 0; +#endif + +int iyprobe __P((struct device *, void *, void *)); +void iyattach __P((struct device *, struct device *, void *)); + +static u_int16_t eepromread __P((int, int)); + +struct cfattach iy_ca = { + sizeof(struct iy_softc), iyprobe, iyattach +}; + +struct cfdriver iy_cd = { + NULL, "iy", DV_IFNET +}; + +static u_int8_t eepro_irqmap[] = EEPP_INTMAP; +static u_int8_t eepro_revirqmap[] = EEPP_RINTMAP; + +int +iyprobe(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct iy_softc *sc = match; + struct isa_attach_args *ia = aux; + + u_int16_t eaddr[8]; + int iobase; + int i; + + u_int16_t checksum = 0; + u_int16_t eepromtmp; + u_int8_t c, d; + + + iobase = ia->ia_iobase; + + if (iobase == -1) + return 0; + + /* try to find the round robin sig: */ + + /* check here for addresses already given to other devices */ + + c = inb(iobase + ID_REG); + if (c & ID_REG_MASK != ID_REG_SIG) + return 0; + + d = inb(iobase + ID_REG); + if (d & ID_REG_MASK != ID_REG_SIG) + return 0; + + if (((d-c) & R_ROBIN_BITS) != 0x40) + return 0; + + d = inb(iobase + ID_REG); + if (d & ID_REG_MASK != ID_REG_SIG) + return 0; + + if (((d-c) & R_ROBIN_BITS) != 0x80) + return 0; + + d = inb(iobase + ID_REG); + if (d & ID_REG_MASK != ID_REG_SIG) + return 0; + + if (((d-c) & R_ROBIN_BITS) != 0xC0) + return 0; + + d = inb(iobase + ID_REG); + if (d & ID_REG_MASK != ID_REG_SIG) + return 0; + + if (((d-c) & R_ROBIN_BITS) != 0x00) + return 0; + +#ifdef IYDEBUG + printf("eepro_probe verified working ID reg.\n"); +#endif + + for (i=0; i<64; ++i) { + eepromtmp = eepromread(iobase, i); + checksum += eepromtmp; + if (i<(sizeof(eaddr)/sizeof(*eaddr))) + eaddr[i] = eepromtmp; + } + if (checksum != EEPP_CHKSUM) + printf("wrong EEPROM checksum 0x%x should be 0x%x\n", + checksum, EEPP_CHKSUM); + + + if ((eaddr[EEPPEther0] != eepromread(iobase, EEPPEther0a)) && + (eaddr[EEPPEther1] != eepromread(iobase, EEPPEther1a)) && + (eaddr[EEPPEther2] != eepromread(iobase, EEPPEther2a))) + printf("EEPROM Ethernet address differs from copy\n"); + + sc->sc_arpcom.ac_enaddr[1] = eaddr[EEPPEther0] & 0xFF; + sc->sc_arpcom.ac_enaddr[0] = eaddr[EEPPEther0] >> 8; + sc->sc_arpcom.ac_enaddr[3] = eaddr[EEPPEther1] & 0xFF; + sc->sc_arpcom.ac_enaddr[2] = eaddr[EEPPEther1] >> 8; + sc->sc_arpcom.ac_enaddr[5] = eaddr[EEPPEther2] & 0xFF; + sc->sc_arpcom.ac_enaddr[4] = eaddr[EEPPEther2] >> 8; + + if (ia->ia_irq == IRQUNK) + ia->ia_irq = eepro_irqmap[eaddr[EEPPW1] & EEPP_Int]; + + if (ia->ia_irq >= sizeof(eepro_revirqmap)) + return 0; + + if ((sc->mappedirq = eepro_revirqmap[ia->ia_irq]) == -1) + return 0; + + sc->hard_vers = eaddr[EEPW6] & EEPP_BoardRev; + + /* now lets reset the chip */ + + outb(iobase + COMMAND_REG, RESET_CMD); + delay(200); + + ia->ia_iobase = iobase; + ia->ia_iosize = 16; + return 1; /* found */ +} + +void +iyattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct iy_softc *sc = (void *)self; + struct isa_attach_args *ia = aux; + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + + bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); + ifp->if_softc = sc; + ifp->if_start = iystart; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; + /* XXX todo: | IFF_MULTICAST */ + sc->sc_iobase = ia->ia_iobase; + + iyprobemem(sc); + + ifp->if_ioctl = iyioctl; + ifp->if_watchdog = iywatchdog; + + /* Attach the interface. */ + if_attach(ifp); + ether_ifattach(ifp); + printf(": address %s, chip rev. %d, %d kB SRAM\n", + ether_sprintf(sc->sc_arpcom.ac_enaddr), + sc->hard_vers, sc->sram/1024); +#if NBPFILTER > 0 + bpfattach(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB, + sizeof(struct ether_header)); +#endif + + sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, + IPL_NET, iyintr, sc); +} + +void +iystop(sc) +struct iy_softc *sc; +{ + int iobase; +#ifdef IYDEBUG + u_int p, v; +#endif + + iobase = sc->sc_iobase; + + outb(iobase + COMMAND_REG, RCV_DISABLE_CMD); + + outb(iobase + INT_MASK_REG, ALL_INTS); + outb(iobase + STATUS_REG, ALL_INTS); + + outb(iobase + COMMAND_REG, RESET_CMD); + delay(200); +#ifdef IYDEBUG + printf("%s: dumping tx chain (st 0x%x end 0x%x last 0x%x)\n", + sc->sc_dev.dv_xname, sc->tx_start, sc->tx_end, sc->tx_last); + p = sc->tx_last; + if (!p) + p = sc->tx_start; + do { + outw(iobase + HOST_ADDR_REG, p); + v = inw(iobase + MEM_PORT_REG); + printf("0x%04x: %b ", p, v, "\020\006Ab\010Dn"); + v = inw(iobase + MEM_PORT_REG); + printf("0x%b", v, "\020\6MAX_COL\7HRT_BEAT\010TX_DEF\011UND_RUN\012JERR\013LST_CRS\014LTCOL\016TX_OK\020COLL"); + p = inw(iobase + MEM_PORT_REG); + printf(" 0x%04x", p); + v = inw(iobase + MEM_PORT_REG); + printf(" 0x%b\n", v, "\020\020Ch"); + + } while (v & 0x8000); +#endif + sc->tx_start = sc->tx_end = sc->rx_size; + sc->tx_last = 0; + sc->sc_arpcom.ac_if.if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); + + iymbufempty((void *)sc); +} + +void +iyreset(sc) +struct iy_softc *sc; +{ + int s; + s = splimp(); + iystop(sc); + iyinit(sc); + splx(s); +} + +void +iyinit(sc) +struct iy_softc *sc; +{ + int i; + unsigned temp; + struct ifnet *ifp; + int iobase; + + ifp = &sc->sc_arpcom.ac_if; +#ifdef IYDEBUG + printf("ifp is %p\n", ifp); +#endif + iobase = sc->sc_iobase; + + outb(iobase, BANK_SEL(2)); + + temp = inb(iobase + EEPROM_REG); + if (temp & 0x10) + outb(iobase + EEPROM_REG, temp & ~0x10); + + for (i=0; i<6; ++i) { + outb(iobase + I_ADD(i), sc->sc_arpcom.ac_enaddr[i]); + } + + temp = inb(iobase + REG1); + outb(iobase + REG1, temp | XMT_CHAIN_INT | XMT_CHAIN_ERRSTOP | + RCV_DISCARD_BAD); + + temp = inb(iobase + RECV_MODES_REG); + outb(iobase + RECV_MODES_REG, temp | MATCH_BRDCST); +#ifdef IYDEBUG + printf("%s: RECV_MODES were %b set to %b\n", + sc->sc_dev.dv_xname, + temp, "\020\1PRMSC\2NOBRDST\3SEECRC\4LENGTH\5NOSaIns\6MultiIA", + temp|MATCH_BRDCST, + "\020\1PRMSC\2NOBRDST\3SEECRC\4LENGTH\5NOSaIns\6MultiIA"); +#endif + + + DELAY(500000); /* for the hardware to test for the connector */ + + temp = inb(iobase + MEDIA_SELECT); +#ifdef IYDEBUG + printf("%s: media select was 0x%b", sc->sc_dev.dv_xname, + temp, "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC"); +#endif + temp = (temp & TEST_MODE_MASK) /* | BNC_BIT XXX*/; + outb(iobase + MEDIA_SELECT, temp); +#ifdef IYDEBUG + printf("changed to 0x%b\n", + temp, "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC"); +#endif + + outb(iobase, BANK_SEL(1)); + + temp = inb(iobase + INT_NO_REG); + outb(iobase + INT_NO_REG, (temp & 0xf8) | sc->mappedirq); + +#ifdef IYDEBUG + printf("%s: int no was %b\n", sc->sc_dev.dv_xname, + temp, "\020\4bad_irq\010flash/boot present"); + temp = inb(iobase + INT_NO_REG); + printf("%s: int no now 0x%02x\n", sc->sc_dev.dv_xname, + temp, "\020\4BAD IRQ\010flash/boot present"); +#endif + + + outb(iobase + RCV_LOWER_LIMIT_REG, 0); + outb(iobase + RCV_UPPER_LIMIT_REG, (sc->rx_size - 2) >> 8); + outb(iobase + XMT_LOWER_LIMIT_REG, sc->rx_size >> 8); + outb(iobase + XMT_UPPER_LIMIT_REG, sc->sram >> 8); + + temp = inb(iobase + REG1); +#ifdef IYDEBUG + printf("%s: HW access is %b\n", sc->sc_dev.dv_xname, + temp, "\020\2WORD_WIDTH\010INT_ENABLE"); +#endif + outb(iobase + REG1, temp | INT_ENABLE); /* XXX what about WORD_WIDTH? */ + +#ifdef IYDEBUG + temp = inb(iobase + REG1); + printf("%s: HW access is %b\n", sc->sc_dev.dv_xname, + temp, "\020\2WORD_WIDTH\010INT_ENABLE"); +#endif + + outb(iobase, BANK_SEL(0)); + + outb(iobase + INT_MASK_REG, ALL_INTS & ~(RX_BIT|TX_BIT)); + outb(iobase + STATUS_REG, ALL_INTS); /* clear ints */ + + outw(iobase + RCV_START_LOW, 0); + outw(iobase + RCV_STOP_LOW, sc->rx_size - 2); + sc->rx_start = 0; + + outb(iobase, SEL_RESET_CMD); + DELAY(200); + + outw(iobase + XMT_ADDR_REG, sc->rx_size); + + sc->tx_start = sc->tx_end = sc->rx_size; + sc->tx_last = 0; + + outb(iobase, RCV_ENABLE_CMD); + + ifp->if_flags |= IFF_RUNNING; + ifp->if_flags &= ~IFF_OACTIVE; +} + +void +iystart(ifp) +struct ifnet *ifp; +{ + struct iy_softc *sc; + int iobase; + + struct mbuf *m0, *m; + u_int len, pad, last, end; + u_int llen, residual; + int avail; + caddr_t data; + u_int16_t resval, stat; + +#ifdef IYDEBUG + printf("iystart called\n"); +#endif + if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) + return; + + sc = ifp->if_softc; + iobase = sc->sc_iobase; + + while ((m0 = ifp->if_snd.ifq_head) != NULL) { +#ifdef IYDEBUG + printf("%s: trying to write another packet to the hardware\n", + sc->sc_dev.dv_xname); +#endif + + /* We need to use m->m_pkthdr.len, so require the header */ + if ((m0->m_flags & M_PKTHDR) == 0) + panic("iystart: no header mbuf"); + + len = m0->m_pkthdr.len; + pad = len & 1; + +#ifdef IYDEBUG + printf("%s: length is %d.\n", sc->sc_dev.dv_xname, len); +#endif + if (len < ETHER_MIN_LEN) { + pad = ETHER_MIN_LEN - len; + } + + if (len + pad > ETHER_MAX_LEN) { + /* packet is obviously too large: toss it */ + ++ifp->if_oerrors; + IF_DEQUEUE(&ifp->if_snd, m0); + m_freem(m0); + continue; + } + +#if NBPFILTER > 0 + if (ifp->if_bpf) + bpf_mtap(ifp->if_bpf, m0); +#endif + + avail = sc->tx_start - sc->tx_end; + if (avail <= 0) + avail += sc->tx_size; + +#ifdef IYDEBUG + printf("%s: avail is %d.\n", sc->sc_dev.dv_xname, avail); +#endif + /* + * we MUST RUN at splnet here --- + * XXX todo: or even turn off the boards ints ??? hm... + */ + + /* See if there is room to put another packet in the buffer. */ + + if ((len+pad+2*I595_XMT_HDRLEN) > avail) { + printf("%s: len = %d, avail = %d, setting OACTIVE\n", + sc->sc_dev.dv_xname, len, avail); + ifp->if_flags |= IFF_OACTIVE; + return; + } + + /* we know it fits in the hardware now, so dequeue it */ + IF_DEQUEUE(&ifp->if_snd, m0); + + last = sc->tx_end; + end = last + pad + len + I595_XMT_HDRLEN; + + if (end >= sc->sram) { + if ((sc->sram - last) <= I595_XMT_HDRLEN) { + /* keep header in one piece */ + last = sc->rx_size; + end = last + pad + len + I595_XMT_HDRLEN; + } else + end -= sc->tx_size; + } + + outw(iobase + HOST_ADDR_REG, last); + outw(iobase + MEM_PORT_REG, XMT_CMD); + outw(iobase + MEM_PORT_REG, 0); + outw(iobase + MEM_PORT_REG, 0); + outw(iobase + MEM_PORT_REG, len + pad); + + residual = resval = 0; + + while ((m = m0)!=0) { + data = mtod(m, caddr_t); + llen = m->m_len; + if (residual) { +#ifdef IYDEBUG + printf("%s: merging residual with next mbuf.\n", + sc->sc_dev.dv_xname); +#endif + resval |= *data << 8; + outw(iobase + MEM_PORT_REG, resval); + --llen; + ++data; + } + if (llen > 1) + outsw(iobase + MEM_PORT_REG, data, llen>>1); + residual = llen & 1; + if (residual) { + resval = *(data + llen - 1); +#ifdef IYDEBUG + printf("%s: got odd mbuf to send.\n", + sc->sc_dev.dv_xname); +#endif + } + + MFREE(m, m0); + } + + if (residual) + outw(iobase + MEM_PORT_REG, resval); + + pad >>= 1; + while (pad-- > 0) + outw(iobase + MEM_PORT_REG, 0); + +#ifdef IYDEBUG + printf("%s: new last = 0x%x, end = 0x%x.\n", + sc->sc_dev.dv_xname, last, end); + printf("%s: old start = 0x%x, end = 0x%x, last = 0x%x\n", + sc->sc_dev.dv_xname, sc->tx_start, sc->tx_end, sc->tx_last); +#endif + + if (sc->tx_start != sc->tx_end) { + outw(iobase + HOST_ADDR_REG, sc->tx_last + XMT_COUNT); + stat = inw(iobase + MEM_PORT_REG); + + outw(iobase + HOST_ADDR_REG, sc->tx_last + XMT_CHAIN); + outw(iobase + MEM_PORT_REG, last); + outw(iobase + MEM_PORT_REG, stat | CHAIN); +#ifdef IYDEBUG + printf("%s: setting 0x%x to 0x%x\n", + sc->sc_dev.dv_xname, sc->tx_last + XMT_COUNT, + stat | CHAIN); +#endif + } + stat = inw(iobase + MEM_PORT_REG); /* dummy read */ + + /* XXX todo: enable ints here if disabled */ + + ++ifp->if_opackets; + + if (sc->tx_start == sc->tx_end) { + outw(iobase + XMT_ADDR_REG, last); + outb(iobase, XMT_CMD); + sc->tx_start = last; +#ifdef IYDEBUG + printf("%s: writing 0x%x to XAR and giving XCMD\n", + sc->sc_dev.dv_xname, last); +#endif + } else { + outb(iobase, RESUME_XMT_CMD); +#ifdef IYDEBUG + printf("%s: giving RESUME_XCMD\n", + sc->sc_dev.dv_xname); +#endif + } + sc->tx_last = last; + sc->tx_end = end; + } +} + + +static __inline void +eepromwritebit(eio, what) + int eio, what; +{ + outb(eio, what); + delay(1); + outb(eio, what|EESK); + delay(1); + outb(eio, what); + delay(1); +} + +static __inline int +eepromreadbit(eio) + int eio; +{ + int b; + + outb(eio, EECS|EESK); + delay(1); + b = inb(eio); + outb(eio, EECS); + delay(1); + + return ((b & EEDO) != 0); +} + +static u_int16_t +eepromread(io, offset) + int io, offset; +{ + volatile int i; + volatile int j; + volatile u_int16_t readval; + int eio = io+EEPROM_REG; + + outb(io, BANK_SEL(2)); + delay(1); + outb(io, EECS); + delay(1); + + eepromwritebit(eio, EECS|EEDI); + eepromwritebit(eio, EECS|EEDI); + eepromwritebit(eio, EECS); + + for (j=5; j>=0; --j) { + if ((offset>>j) & 1) + eepromwritebit(eio, EECS|EEDI); + else + eepromwritebit(eio, EECS); + } + + for (readval=0, i=0; i<16; ++i) { + readval<<=1; + readval |= eepromreadbit(eio); + } + + outb(eio, 0|EESK); + delay(1); + outb(eio, 0); + + outb(eio, BANK_SEL(0)); + + return readval; +} + +/* + * Device timeout/watchdog routine. Entered if the device neglects to generate + * an interrupt after a transmit has been started on it. + */ +void +iywatchdog(ifp) + struct ifnet *ifp +{ + struct iy_softc *sc = ifp->if_softc; + + log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); + ++sc->sc_arpcom.ac_if.if_oerrors; + iyreset(sc); +} + +/* + * What to do upon receipt of an interrupt. + */ +int +iyintr(arg) + void *arg; +{ + struct iy_softc *sc = arg; + int iobase; + register u_short status; + + iobase = sc->sc_iobase; + status = inb(iobase + STATUS_REG); +#ifdef IYDEBUG + if (status & ALL_INTS) { + printf("%s: got interupt %b", sc->sc_dev.dv_xname, status, + "\020\1RX_STP\2RX\3TX\4EXEC"); + if (status & EXEC_INT) + printf(" event %b\n", inb(iobase), + "\020\6ABORT"); + else + printf("\n"); + } +#endif + if ((status & (RX_INT | TX_INT) == 0)) + return 0; + + if (status & RX_INT) { + iy_intr_rx(sc); + outb(iobase + STATUS_REG, RX_INT); + } else if (status & TX_INT) { + iy_intr_tx(sc); + outb(iobase + STATUS_REG, TX_INT); + } + return 1; +} + +void +iyget(sc, iobase, rxlen) +struct iy_softc *sc; +int iobase, rxlen; +{ + struct mbuf *m, *top, **mp; + struct ether_header *eh; + struct ifnet *ifp; + int len; + + ifp = &sc->sc_arpcom.ac_if; + + m = sc->mb[sc->next_mb]; + sc->mb[sc->next_mb] = 0; + if (m == 0) { + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == 0) + goto dropped; + } else { + if (sc->last_mb == sc->next_mb) + timeout(iymbuffill, sc, 1); + sc->next_mb = (sc->next_mb + 1) % MAX_MBS; + m->m_data = m->m_pktdat; + m->m_flags = M_PKTHDR; + } + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = rxlen; + len = MHLEN; + top = 0; + mp = ⊤ + + while (rxlen > 0) { + if (top) { + m = sc->mb[sc->next_mb]; + sc->mb[sc->next_mb] = 0; + if (m == 0) { + MGET(m, M_DONTWAIT, MT_DATA); + if (m == 0) { + m_freem(top); + goto dropped; + } + } else { + sc->next_mb = (sc->next_mb + 1) % MAX_MBS; + } + len = MLEN; + } + if (rxlen >= MINCLSIZE) { + MCLGET(m, M_DONTWAIT); + if (m->m_flags & M_EXT) + len = MCLBYTES; + } + len = min(rxlen, len); + if (len > 1) { + len &= ~1; + insw(iobase + MEM_PORT_REG, mtod(m, caddr_t), len/2); + } else { +#ifdef IYDEBUG + printf("%s: received odd mbuf\n", sc->sc_dev.dv_xname); +#endif + *(mtod(m, caddr_t)) = inw(iobase + MEM_PORT_REG); + } + m->m_len = len; + rxlen -= len; + *mp = m; + mp = &m->m_next; + } + /* XXX receive the top here */ + ++ifp->if_ipackets; + + eh = mtod(top, struct ether_header *); + +#if NBPFILTER > 0 + if (ifp->if_bpf) { + bpf_mtap(ifp->if_bpf, top); + if ((ifp->if_flags & IFF_PROMISC) && + (eh->ether_dhost[0] & 1) == 0 && + bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr, + sizeof(eh->ether_dhost)) != 0) { + m_freem(top); + return; + } + } +#endif + m_adj(top, sizeof(struct ether_header)); + ether_input(ifp, eh, top); + return; + +dropped: + ++ifp->if_ierrors; + return; +} +void +iy_intr_rx(sc) +struct iy_softc *sc; +{ + struct ifnet *ifp; + int iobase; + u_int rxadrs, rxevnt, rxstatus, rxnext, rxlen; + + iobase = sc->sc_iobase; + ifp = &sc->sc_arpcom.ac_if; + + rxadrs = sc->rx_start; + outw(iobase + HOST_ADDR_REG, rxadrs); + rxevnt = inw(iobase + MEM_PORT_REG); + rxnext = 0; + + while (rxevnt == RCV_DONE) { + rxstatus = inw(iobase + MEM_PORT_REG); + rxnext = inw(iobase + MEM_PORT_REG); + rxlen = inw(iobase + MEM_PORT_REG); +#ifdef IYDEBUG + printf("%s: pck at 0x%04x stat %b next 0x%x len 0x%x\n", + sc->sc_dev.dv_xname, rxadrs, rxstatus, + "\020\1RCLD\2IA_MCH\010SHORT\011OVRN\013ALGERR" + "\014CRCERR\015LENERR\016RCVOK\020TYP", + rxnext, rxlen); +#endif + iyget(sc, iobase, rxlen); + + /* move stop address */ + outw(iobase + RCV_STOP_LOW, + rxnext == 0 ? sc->rx_size - 2 : rxnext - 2); + + outw(iobase + HOST_ADDR_REG, rxnext); + rxadrs = rxnext; + rxevnt = inw(iobase + MEM_PORT_REG); + } + sc->rx_start = rxnext; +} + +void +iy_intr_tx(sc) +struct iy_softc *sc; +{ + int iobase; + struct ifnet *ifp; + u_int txstatus, txstat2, txlen, txnext; + + ifp = &sc->sc_arpcom.ac_if; + iobase = sc->sc_iobase; + + while (sc->tx_start != sc->tx_end) { + outw(iobase + HOST_ADDR_REG, sc->tx_start); + txstatus = inw(iobase + MEM_PORT_REG); + if ((txstatus & (TX_DONE|CMD_MASK)) != (TX_DONE|XMT_CMD)) + break; + + txstat2 = inw(iobase + MEM_PORT_REG); + txnext = inw(iobase + MEM_PORT_REG); + txlen = inw(iobase + MEM_PORT_REG); +#ifdef IYDEBUG + printf("txstat 0x%x stat2 0x%b next 0x%x len 0x%x\n", + txstatus, txstat2, "\020\6MAX_COL\7HRT_BEAT\010TX_DEF" + "\011UND_RUN\012JERR\013LST_CRS\014LTCOL\016TX_OK\020COLL", + txnext, txlen); +#endif + if (txlen & CHAIN) + sc->tx_start = txnext; + else + sc->tx_start = sc->tx_end; + ifp->if_flags &= ~IFF_OACTIVE; + + if ((txstat2 & 0x2000) == 0) + ++ifp->if_oerrors; + if (txstat2 & 0x000f) + ifp->if_oerrors += txstat2 & 0x000f; + } + ifp->if_flags &= ~IFF_OACTIVE; +} + +#if 0 +/* + * Compare two Ether/802 addresses for equality, inlined and unrolled for + * speed. I'd love to have an inline assembler version of this... + */ +static inline int +ether_equal(one, two) + u_char *one, *two; +{ + + if (one[0] != two[0] || one[1] != two[1] || one[2] != two[2] || + one[3] != two[3] || one[4] != two[4] || one[5] != two[5]) + return 0; + return 1; +} + +/* + * Check for a valid address. to_bpf is filled in with one of the following: + * 0 -> BPF doesn't get this packet + * 1 -> BPF does get this packet + * 2 -> BPF does get this packet, but we don't + * Return value is true if the packet is for us, and false otherwise. + * + * This routine is a mess, but it's also critical that it be as fast + * as possible. It could be made cleaner if we can assume that the + * only client which will fiddle with IFF_PROMISC is BPF. This is + * probably a good assumption, but we do not make it here. (Yet.) + */ +static inline int +check_eh(sc, eh, to_bpf) + struct iy_softc *sc; + struct ether_header *eh; + int *to_bpf; +{ + int i; + + switch (sc->promisc) { + case IFF_ALLMULTI: + /* + * Receiving all multicasts, but no unicasts except those + * destined for us. + */ +#if NBPFILTER > 0 + *to_bpf = (sc->sc_arpcom.ac_if.iy_bpf != 0); /* BPF gets this packet if anybody cares */ +#endif + if (eh->ether_dhost[0] & 1) + return 1; + if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr)) + return 1; + return 0; + + case IFF_PROMISC: + /* + * Receiving all packets. These need to be passed on to BPF. + */ +#if NBPFILTER > 0 + *to_bpf = (sc->sc_arpcom.ac_if.iy_bpf != 0); +#endif + /* If for us, accept and hand up to BPF */ + if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr)) + return 1; + +#if NBPFILTER > 0 + if (*to_bpf) + *to_bpf = 2; /* we don't need to see it */ +#endif + + /* + * Not a multicast, so BPF wants to see it but we don't. + */ + if (!(eh->ether_dhost[0] & 1)) + return 1; + + /* + * If it's one of our multicast groups, accept it and pass it + * up. + */ + for (i = 0; i < sc->mcast_count; i++) { + if (ether_equal(eh->ether_dhost, (u_char *)&sc->mcast_addrs[i])) { +#if NBPFILTER > 0 + if (*to_bpf) + *to_bpf = 1; +#endif + return 1; + } + } + return 1; + + case IFF_ALLMULTI | IFF_PROMISC: + /* + * Acting as a multicast router, and BPF running at the same + * time. Whew! (Hope this is a fast machine...) + */ +#if NBPFILTER > 0 + *to_bpf = (sc->sc_arpcom.ac_if.iy_bpf != 0); +#endif + /* We want to see multicasts. */ + if (eh->ether_dhost[0] & 1) + return 1; + + /* We want to see our own packets */ + if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr)) + return 1; + + /* Anything else goes to BPF but nothing else. */ +#if NBPFILTER > 0 + if (*to_bpf) + *to_bpf = 2; +#endif + return 1; + + case 0: + /* + * Only accept unicast packets destined for us, or multicasts + * for groups that we belong to. For now, we assume that the + * '586 will only return packets that we asked it for. This + * isn't strictly true (it uses hashing for the multicast + * filter), but it will do in this case, and we want to get out + * of here as quickly as possible. + */ +#if NBPFILTER > 0 + *to_bpf = (sc->sc_arpcom.ac_if.iy_bpf != 0); +#endif + return 1; + } + +#ifdef DIAGNOSTIC + panic("check_eh: impossible"); +#endif +} +#endif + +int +iyioctl(ifp, cmd, data) + register struct ifnet *ifp; + u_long cmd; + caddr_t data; +{ + struct iy_softc *sc; + struct ifaddr *ifa; + struct ifreq *ifr; + int s, error = 0; + + sc = ifp->if_softc; + ifa = (struct ifaddr *)data; + ifr = (struct ifreq *)data; + +#ifdef IYDEBUG + printf("iyioctl called with ifp 0x%p (%s) cmd 0x%x data 0x%p\n", + ifp, ifp->if_xname, cmd, data); +#endif + + s = splimp(); + + switch (cmd) { + + case SIOCSIFADDR: + ifp->if_flags |= IFF_UP; + + switch (ifa->ifa_addr->sa_family) { +#ifdef INET + case AF_INET: + iyinit(sc); + arp_ifinit(&sc->sc_arpcom, ifa); + break; +#endif +#ifdef NS + /* XXX - This code is probably wrong. */ + case AF_NS: + { + struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; + + if (ns_nullhost(*ina)) + ina->x_host = + *(union ns_host *)(sc->sc_arpcom.ac_enaddr); + else + bcopy(ina->x_host.c_host, + sc->sc_arpcom.ac_enaddr, + sizeof(sc->sc_arpcom.ac_enaddr)); + /* Set new address. */ + iyinit(sc); + break; + } +#endif /* NS */ + default: + iyinit(sc); + break; + } + break; + + case SIOCSIFFLAGS: + sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI); + if ((ifp->if_flags & IFF_UP) == 0 && + (ifp->if_flags & IFF_RUNNING) != 0) { + /* + * If interface is marked down and it is running, then + * stop it. + */ + iystop(sc); + ifp->if_flags &= ~IFF_RUNNING; + } else if ((ifp->if_flags & IFF_UP) != 0 && + (ifp->if_flags & IFF_RUNNING) == 0) { + /* + * If interface is marked up and it is stopped, then + * start it. + */ + iyinit(sc); + } else { + /* + * Reset the interface to pick up changes in any other + * flags that affect hardware registers. + */ + iystop(sc); + iyinit(sc); + } +#ifdef IYDEBUGX + if (ifp->if_flags & IFF_DEBUG) + sc->sc_debug = IFY_ALL; + else + sc->sc_debug = 0; +#endif + break; + +#if 0 /* XXX */ + case SIOCADDMULTI: + case SIOCDELMULTI: + error = (cmd == SIOCADDMULTI) ? + ether_addmulti(ifr, &sc->sc_arpcom): + ether_delmulti(ifr, &sc->sc_arpcom); + + if (error == ENETRESET) { + /* + * Multicast list has changed; set the hardware filter + * accordingly. + */ + iy_mc_reset(sc); /* XXX */ + error = 0; + } + break; +#endif + default: + error = EINVAL; + } + splx(s); + return error; +} + +#if 0 +static void +iy_mc_reset(sc) + struct iy_softc *sc; +{ + struct ether_multi *enm; + struct ether_multistep step; + + /* + * Step through the list of addresses. + */ + sc->mcast_count = 0; + ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm); + while (enm) { + if (sc->mcast_count >= MAXMCAST || + bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) { + sc->sc_arpcom.ac_if.if_flags |= IFF_ALLMULTI; + iyioctl(&sc->sc_arpcom.ac_if, SIOCSIFFLAGS, (void *)0); + goto setflag; + } + + bcopy(enm->enm_addrlo, &sc->mcast_addrs[sc->mcast_count], 6); + sc->mcast_count++; + ETHER_NEXT_MULTI(step, enm); + } + setflag: + sc->want_mcsetup = 1; +} + +#ifdef IYDEBUG +void +print_rbd(rbd) + volatile struct ie_recv_buf_desc *rbd; +{ + + printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n" + "length %04x, mbz %04x\n", (u_long)rbd, rbd->ie_rbd_actual, + rbd->ie_rbd_next, rbd->ie_rbd_buffer, rbd->ie_rbd_length, + rbd->mbz); +} +#endif +#endif + +void +iymbuffill(arg) + void *arg; +{ + struct iy_softc *sc = (struct iy_softc *)arg; + int s, i; + + s = splimp(); + i = sc->last_mb; + do { + if (sc->mb[i] == NULL) + MGET(sc->mb[i], M_DONTWAIT, MT_DATA); + if (sc->mb[i] == NULL) + break; + i = (i + 1) % MAX_MBS; + } while (i != sc->next_mb); + sc->last_mb = i; + /* If the queue was not filled, try again. */ + if (sc->last_mb != sc->next_mb) + timeout(iymbuffill, sc, 1); + splx(s); +} + + +void +iymbufempty(arg) + void *arg; +{ + struct iy_softc *sc = (struct iy_softc *)arg; + int s, i; + + s = splimp(); + for (i = 0; imb[i]) { + m_freem(sc->mb[i]); + sc->mb[i] = NULL; + } + } + sc->last_mb = sc->next_mb = 0; + untimeout(iymbuffill, sc); + splx(s); +} + +void +iyprobemem(sc) + struct iy_softc *sc; +{ + int iobase; + int testing; + + iobase = sc->sc_iobase; + + outw(iobase + HOST_ADDR_REG, 4096-2); + outw(iobase + MEM_PORT_REG, 0); + + for (testing=65536; testing >= 4096; testing >>= 1) { + outw(iobase + HOST_ADDR_REG, testing-2); + outw(iobase + MEM_PORT_REG, 0xdead); + outw(iobase + HOST_ADDR_REG, testing-2); + if (inw(iobase + MEM_PORT_REG) != 0xdead) { +#ifdef IYMEMDEBUG + printf("%s: Didn't keep 0xdead at 0x%x\n", + sc->sc_dev.dv_xname, testing-2); +#endif + continue; + } + + outw(iobase + HOST_ADDR_REG, testing-2); + outw(iobase + MEM_PORT_REG, 0xbeef); + outw(iobase + HOST_ADDR_REG, testing-2); + if (inw(iobase + MEM_PORT_REG) != 0xbeef) { +#ifdef IYMEMDEBUG + printf("%s: Didn't keep 0xbeef at 0x%x\n", + sc->sc_dev.dv_xname, testing-2); +#endif + continue; + } + + outw(iobase + HOST_ADDR_REG, 0); + outw(iobase + MEM_PORT_REG, 0); + outw(iobase + HOST_ADDR_REG, testing >> 1); + outw(iobase + MEM_PORT_REG, testing >> 1); + outw(iobase + HOST_ADDR_REG, 0); + if (inw(iobase + MEM_PORT_REG) == (testing >> 1)) { +#ifdef IYMEMDEBUG + printf("%s: 0x%x alias of 0x0\n", + sc->sc_dev.dv_xname, testing >> 1); +#endif + continue; + } + + break; + } + + sc->sram = testing; + + switch(testing) { + case 65536: + /* 4 NFS packets + overhead RX, 2 NFS + overhead TX */ + sc->rx_size = 44*1024; + break; + + case 32768: + /* 2 NFS packets + overhead RX, 1 NFS + overhead TX */ + sc->rx_size = 22*1024; + break; + + case 16384: + /* 1 NFS packet + overhead RX, 4 big packets TX */ + sc->rx_size = 10*1024; + break; + default: + sc->rx_size = testing/2; + break; + } + sc->tx_size = testing - sc->rx_size; +} diff --git a/sys/dev/isa/if_le.c b/sys/dev/isa/if_le.c index bc7a2e6070e..e69de29bb2d 100644 --- a/sys/dev/isa/if_le.c +++ b/sys/dev/isa/if_le.c @@ -1,463 +0,0 @@ -/* $OpenBSD: if_le.c,v 1.9 1996/05/02 13:51:53 deraadt Exp $ */ -/* $NetBSD: if_le.c,v 1.43 1996/04/22 02:53:28 christos Exp $ */ - -/*- - * Copyright (c) 1995 Charles M. Hannum. All rights reserved. - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell and Rick Macklem. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)if_le.c 8.2 (Berkeley) 11/16/93 - */ - -#include "bpfilter.h" - -#include -#include -#include -#include -#include -#include - -#include - -#ifdef INET -#include -#include -#endif - -#include - -#include -#include - -#include "isa.h" -#include "pci.h" - -#if NISA > 0 -#include -#include -#include -#include -#endif - -#if NPCI > 0 -#include -#include -#endif - -#include -#include -#define LE_NEED_BUF_CONTIG -#include - -char *card_type[] = {"unknown", "BICC Isolan", "NE2100", "DEPCA", "PCnet-ISA", "PCnet-PCI"}; - -#define LE_SOFTC(unit) le_cd.cd_devs[unit] -#define LE_DELAY(x) delay(x) - -int leprobe __P((struct device *, void *, void *)); -int depca_probe __P((struct le_softc *, struct isa_attach_args *)); -int ne2100_probe __P((struct le_softc *, struct isa_attach_args *)); -int bicc_probe __P((struct le_softc *, struct isa_attach_args *)); -int lance_probe __P((struct le_softc *)); -void leattach __P((struct device *, struct device *, void *)); -int leintr __P((void *)); -int leintredge __P((void *)); -void leshutdown __P((void *)); - -/* XXX the following two structs should be different. */ -struct cfattach le_isa_ca = { - sizeof(struct le_softc), leprobe, leattach -}; - -struct cfattach le_pci_ca = { - sizeof(struct le_softc), leprobe, leattach -}; - -struct cfdriver le_cd = { - NULL, "le", DV_IFNET -}; - -integrate void -lehwinit(sc) - struct le_softc *sc; -{ -} - -integrate void -lewrcsr(sc, port, val) - struct le_softc *sc; - u_int16_t port, val; -{ - - outw(sc->sc_rap, port); - outw(sc->sc_rdp, val); -} - -integrate u_int16_t -lerdcsr(sc, port) - struct le_softc *sc; - u_int16_t port; -{ - u_int16_t val; - - outw(sc->sc_rap, port); - val = inw(sc->sc_rdp); - return (val); -} - -int -leprobe(parent, match, aux) - struct device *parent; - void *match, *aux; -{ - struct le_softc *sc = match; - extern struct cfdriver isa_cd, pci_cd; - -#if NISA > 0 - if (parent->dv_cfdata->cf_driver == &isa_cd) { - struct isa_attach_args *ia = aux; - - if (bicc_probe(sc, ia)) - return (1); - if (ne2100_probe(sc, ia)) - return (1); - if (depca_probe(sc, ia)) - return (1); - } -#endif - -#if NPCI > 0 - if (parent->dv_cfdata->cf_driver == &pci_cd) { - struct pci_attach_args *pa = aux; - - if (pa->pa_id == 0x20001022) - return (1); - } -#endif - - return (0); -} - -#if NISA > 0 -int -depca_probe(sc, ia) - struct le_softc *sc; - struct isa_attach_args *ia; -{ - int iobase = ia->ia_iobase, port; - u_long sum, rom_sum; - u_char x; - int i; - - sc->sc_rap = iobase + DEPCA_RAP; - sc->sc_rdp = iobase + DEPCA_RDP; - sc->sc_card = DEPCA; - - if (lance_probe(sc) == 0) - return 0; - - outb(iobase + DEPCA_CSR, DEPCA_CSR_DUM); - - /* - * Extract the physical MAC address from the ROM. - * - * The address PROM is 32 bytes wide, and we access it through - * a single I/O port. On each read, it rotates to the next - * position. We find the ethernet address by looking for a - * particular sequence of bytes (0xff, 0x00, 0x55, 0xaa, 0xff, - * 0x00, 0x55, 0xaa), and then reading the next 8 bytes (the - * ethernet address and a checksum). - * - * It appears that the PROM can be at one of two locations, so - * we just try both. - */ - port = iobase + DEPCA_ADP; - for (i = 0; i < 32; i++) - if (inb(port) == 0xff && inb(port) == 0x00 && - inb(port) == 0x55 && inb(port) == 0xaa && - inb(port) == 0xff && inb(port) == 0x00 && - inb(port) == 0x55 && inb(port) == 0xaa) - goto found; - port = iobase + DEPCA_ADP + 1; - for (i = 0; i < 32; i++) - if (inb(port) == 0xff && inb(port) == 0x00 && - inb(port) == 0x55 && inb(port) == 0xaa && - inb(port) == 0xff && inb(port) == 0x00 && - inb(port) == 0x55 && inb(port) == 0xaa) - goto found; - printf("%s: address not found\n", sc->sc_dev.dv_xname); - return 0; - -found: - for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++) - sc->sc_arpcom.ac_enaddr[i] = inb(port); - -#if 0 - sum = - (sc->sc_arpcom.ac_enaddr[0] << 2) + - (sc->sc_arpcom.ac_enaddr[1] << 10) + - (sc->sc_arpcom.ac_enaddr[2] << 1) + - (sc->sc_arpcom.ac_enaddr[3] << 9) + - (sc->sc_arpcom.ac_enaddr[4] << 0) + - (sc->sc_arpcom.ac_enaddr[5] << 8); - sum = (sum & 0xffff) + (sum >> 16); - sum = (sum & 0xffff) + (sum >> 16); - - rom_sum = inb(port); - rom_sum |= inb(port) << 8; - - if (sum != rom_sum) { - printf("%s: checksum mismatch; calculated %04x != read %04x", - sc->sc_dev.dv_xname, sum, rom_sum); - return 0; - } -#endif - - outb(iobase + DEPCA_CSR, DEPCA_CSR_NORMAL); - - ia->ia_iosize = 16; - ia->ia_drq = DRQUNK; - return 1; -} - -int -ne2100_probe(sc, ia) - struct le_softc *sc; - struct isa_attach_args *ia; -{ - int iobase = ia->ia_iobase; - int i; - - sc->sc_rap = iobase + NE2100_RAP; - sc->sc_rdp = iobase + NE2100_RDP; - sc->sc_card = NE2100; - - if (lance_probe(sc) == 0) - return 0; - - /* - * Extract the physical MAC address from the ROM. - */ - for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++) - sc->sc_arpcom.ac_enaddr[i] = inb(iobase + i); - - ia->ia_iosize = 24; - return 1; -} - -int -bicc_probe(sc, ia) - struct le_softc *sc; - struct isa_attach_args *ia; -{ - int iobase = ia->ia_iobase; - int i; - - sc->sc_rap = iobase + BICC_RAP; - sc->sc_rdp = iobase + BICC_RDP; - sc->sc_card = BICC; - - if (lance_probe(sc) == 0) - return 0; - - /* - * Extract the physical MAC address from the ROM. - */ - for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++) - sc->sc_arpcom.ac_enaddr[i] = inb(iobase + i * 2); - - ia->ia_iosize = 16; - return 1; -} - -/* - * Determine which chip is present on the card. - */ -int -lance_probe(sc) - struct le_softc *sc; -{ - - /* Stop the LANCE chip and put it in a known state. */ - lewrcsr(sc, LE_CSR0, LE_C0_STOP); - LE_DELAY(100); - - if (lerdcsr(sc, LE_CSR0) != LE_C0_STOP) - return 0; - - lewrcsr(sc, LE_CSR3, sc->sc_conf3); - return 1; -} -#endif - -void -leattach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - struct le_softc *sc = (void *)self; - extern struct cfdriver isa_cd, pci_cd; - -#if NPCI > 0 - if (parent->dv_cfdata->cf_driver == &pci_cd) { - struct pci_attach_args *pa = aux; - int iobase; - - if (pa->pa_id == 0x20001022) { - int i; - - if (pci_map_io(pa->pa_tag, 0x10, &iobase)) - return; - - sc->sc_rap = iobase + NE2100_RAP; - sc->sc_rdp = iobase + NE2100_RDP; - sc->sc_card = PCnet_PCI; - - /* - * Extract the physical MAC address from the ROM. - */ - for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++) - sc->sc_arpcom.ac_enaddr[i] = inb(iobase + i); - } - } -#endif - -#if NISA > 0 - if (sc->sc_card == DEPCA) { - struct isa_attach_args *ia = aux; - u_char *mem, val; - int i; - - mem = sc->sc_mem = ISA_HOLE_VADDR(ia->ia_maddr); - - val = 0xff; - for (;;) { - for (i = 0; i < ia->ia_msize; i++) - mem[i] = val; - for (i = 0; i < ia->ia_msize; i++) - if (mem[i] != val) { - printf("%s: failed to clear memory\n", - sc->sc_dev.dv_xname); - return; - } - if (val == 0x00) - break; - val -= 0x55; - } - - sc->sc_conf3 = LE_C3_ACON; - sc->sc_addr = 0; - sc->sc_memsize = ia->ia_msize; - } else -#endif - { - sc->sc_mem = malloc(16384, M_DEVBUF, M_NOWAIT); - if (sc->sc_mem == 0) { - printf("%s: couldn't allocate memory for card\n", - sc->sc_dev.dv_xname); - return; - } - - sc->sc_conf3 = 0; - sc->sc_addr = kvtop(sc->sc_mem); - sc->sc_memsize = 16384; - } - - sc->sc_copytodesc = am7990_copytobuf_contig; - sc->sc_copyfromdesc = am7990_copyfrombuf_contig; - sc->sc_copytobuf = am7990_copytobuf_contig; - sc->sc_copyfrombuf = am7990_copyfrombuf_contig; - sc->sc_zerobuf = am7990_zerobuf_contig; - - sc->sc_arpcom.ac_if.if_name = le_cd.cd_name; - leconfig(sc); - - printf("%s: type %s\n", sc->sc_dev.dv_xname, card_type[sc->sc_card]); - -#if NISA > 0 - if (parent->dv_cfdata->cf_driver == &isa_cd) { - struct isa_attach_args *ia = aux; - - if (ia->ia_drq != DRQUNK) - isa_dmacascade(ia->ia_drq); - - sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, - IPL_NET, leintredge, sc, sc->sc_dev.dv_xname); - } -#endif - -#if NPCI > 0 - if (parent->dv_cfdata->cf_driver == &pci_cd) { - struct pci_attach_args *pa = aux; - pcireg_t csr; - - csr = pci_conf_read(pa->pa_bc, pa->pa_tag, - PCI_COMMAND_STATUS_REG); - pci_conf_write(pa->pa_bc, pa->pa_tag, PCI_COMMAND_STATUS_REG, - csr | PCI_COMMAND_MASTER_ENABLE); - - sc->sc_ih = pci_map_int(pa->pa_tag, IPL_NET, leintr, sc); - } -#endif - - sc->sc_sh = shutdownhook_establish(leshutdown, sc); -} - -void -leshutdown(arg) - void *arg; -{ - struct le_softc *sc = arg; - - lestop(sc); -} - -#if NISA > 0 -/* - * Controller interrupt. - */ -leintredge(arg) - void *arg; -{ - - if (leintr(arg) == 0) - return (0); - for (;;) - if (leintr(arg) == 0) - return (1); -} -#endif - -#include diff --git a/sys/dev/isa/if_le_isa.c b/sys/dev/isa/if_le_isa.c new file mode 100644 index 00000000000..44aaf16676a --- /dev/null +++ b/sys/dev/isa/if_le_isa.c @@ -0,0 +1,367 @@ +/* $NetBSD: if_le_isa.c,v 1.1 1996/05/07 01:50:05 thorpej Exp $ */ + +/*- + * Copyright (c) 1995 Charles M. Hannum. All rights reserved. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_le.c 8.2 (Berkeley) 11/16/93 + */ + +#include "bpfilter.h" + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef INET +#include +#include +#endif + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +static char *card_type[] = + { "unknown", "BICC Isolan", "NE2100", "DEPCA", "PCnet-ISA" }; + +int le_isa_probe __P((struct device *, void *, void *)); +void le_isa_attach __P((struct device *, struct device *, void *)); + +struct cfattach le_isa_ca = { + sizeof(struct le_softc), le_isa_probe, le_isa_attach +}; + +int depca_isa_probe __P((struct le_softc *, struct isa_attach_args *)); +int ne2100_isa_probe __P((struct le_softc *, struct isa_attach_args *)); +int bicc_isa_probe __P((struct le_softc *, struct isa_attach_args *)); +int lance_isa_probe __P((struct am7990_softc *)); + +int le_isa_intredge __P((void *)); + +hide void le_isa_wrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t)); +hide u_int16_t le_isa_rdcsr __P((struct am7990_softc *, u_int16_t)); + +hide void +le_isa_wrcsr(sc, port, val) + struct am7990_softc *sc; + u_int16_t port, val; +{ + + outw(((struct le_softc *)sc)->sc_rap, port); + outw(((struct le_softc *)sc)->sc_rdp, val); +} + +hide u_int16_t +le_isa_rdcsr(sc, port) + struct am7990_softc *sc; + u_int16_t port; +{ + u_int16_t val; + + outw(((struct le_softc *)sc)->sc_rap, port); + val = inw(((struct le_softc *)sc)->sc_rdp); + return (val); +} + +int +le_isa_probe(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct le_softc *lesc = match; + struct isa_attach_args *ia = aux; + + if (bicc_isa_probe(lesc, ia)) + return (1); + if (ne2100_isa_probe(lesc, ia)) + return (1); + if (depca_isa_probe(lesc, ia)) + return (1); + + return (0); +} + +int +depca_isa_probe(lesc, ia) + struct le_softc *lesc; + struct isa_attach_args *ia; +{ + struct am7990_softc *sc = &lesc->sc_am7990; + int iobase = ia->ia_iobase, port; + u_long sum, rom_sum; + u_char x; + int i; + + lesc->sc_rap = iobase + DEPCA_RAP; + lesc->sc_rdp = iobase + DEPCA_RDP; + lesc->sc_card = DEPCA; + + if (lance_isa_probe(sc) == 0) + return 0; + + outb(iobase + DEPCA_CSR, DEPCA_CSR_DUM); + + /* + * Extract the physical MAC address from the ROM. + * + * The address PROM is 32 bytes wide, and we access it through + * a single I/O port. On each read, it rotates to the next + * position. We find the ethernet address by looking for a + * particular sequence of bytes (0xff, 0x00, 0x55, 0xaa, 0xff, + * 0x00, 0x55, 0xaa), and then reading the next 8 bytes (the + * ethernet address and a checksum). + * + * It appears that the PROM can be at one of two locations, so + * we just try both. + */ + port = iobase + DEPCA_ADP; + for (i = 0; i < 32; i++) + if (inb(port) == 0xff && inb(port) == 0x00 && + inb(port) == 0x55 && inb(port) == 0xaa && + inb(port) == 0xff && inb(port) == 0x00 && + inb(port) == 0x55 && inb(port) == 0xaa) + goto found; + port = iobase + DEPCA_ADP + 1; + for (i = 0; i < 32; i++) + if (inb(port) == 0xff && inb(port) == 0x00 && + inb(port) == 0x55 && inb(port) == 0xaa && + inb(port) == 0xff && inb(port) == 0x00 && + inb(port) == 0x55 && inb(port) == 0xaa) + goto found; + printf("%s: address not found\n", sc->sc_dev.dv_xname); + return 0; + +found: + for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++) + sc->sc_arpcom.ac_enaddr[i] = inb(port); + +#if 0 + sum = + (sc->sc_arpcom.ac_enaddr[0] << 2) + + (sc->sc_arpcom.ac_enaddr[1] << 10) + + (sc->sc_arpcom.ac_enaddr[2] << 1) + + (sc->sc_arpcom.ac_enaddr[3] << 9) + + (sc->sc_arpcom.ac_enaddr[4] << 0) + + (sc->sc_arpcom.ac_enaddr[5] << 8); + sum = (sum & 0xffff) + (sum >> 16); + sum = (sum & 0xffff) + (sum >> 16); + + rom_sum = inb(port); + rom_sum |= inb(port) << 8; + + if (sum != rom_sum) { + printf("%s: checksum mismatch; calculated %04x != read %04x", + sc->sc_dev.dv_xname, sum, rom_sum); + return 0; + } +#endif + + outb(iobase + DEPCA_CSR, DEPCA_CSR_NORMAL); + + ia->ia_iosize = 16; + ia->ia_drq = DRQUNK; + return 1; +} + +int +ne2100_isa_probe(lesc, ia) + struct le_softc *lesc; + struct isa_attach_args *ia; +{ + struct am7990_softc *sc = &lesc->sc_am7990; + int iobase = ia->ia_iobase; + int i; + + lesc->sc_rap = iobase + NE2100_RAP; + lesc->sc_rdp = iobase + NE2100_RDP; + lesc->sc_card = NE2100; + + if (lance_isa_probe(sc) == 0) + return 0; + + /* + * Extract the physical MAC address from the ROM. + */ + for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++) + sc->sc_arpcom.ac_enaddr[i] = inb(iobase + i); + + ia->ia_iosize = 24; + return 1; +} + +int +bicc_isa_probe(lesc, ia) + struct le_softc *lesc; + struct isa_attach_args *ia; +{ + struct am7990_softc *sc = &lesc->sc_am7990; + int iobase = ia->ia_iobase; + int i; + + lesc->sc_rap = iobase + BICC_RAP; + lesc->sc_rdp = iobase + BICC_RDP; + lesc->sc_card = BICC; + + if (lance_isa_probe(sc) == 0) + return 0; + + /* + * Extract the physical MAC address from the ROM. + */ + for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++) + sc->sc_arpcom.ac_enaddr[i] = inb(iobase + i * 2); + + ia->ia_iosize = 16; + return 1; +} + +/* + * Determine which chip is present on the card. + */ +int +lance_isa_probe(sc) + struct am7990_softc *sc; +{ + + /* Stop the LANCE chip and put it in a known state. */ + le_isa_wrcsr(sc, LE_CSR0, LE_C0_STOP); + delay(100); + + if (le_isa_rdcsr(sc, LE_CSR0) != LE_C0_STOP) + return 0; + + le_isa_wrcsr(sc, LE_CSR3, sc->sc_conf3); + return 1; +} + +void +le_isa_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct le_softc *lesc = (void *)self; + struct am7990_softc *sc = &lesc->sc_am7990; + struct isa_attach_args *ia = aux; + + printf(": %s Ethernet\n", sc->sc_dev.dv_xname, + card_type[lesc->sc_card]); + + if (lesc->sc_card == DEPCA) { + u_char *mem, val; + int i; + + mem = sc->sc_mem = ISA_HOLE_VADDR(ia->ia_maddr); + + val = 0xff; + for (;;) { + for (i = 0; i < ia->ia_msize; i++) + mem[i] = val; + for (i = 0; i < ia->ia_msize; i++) + if (mem[i] != val) { + printf("%s: failed to clear memory\n", + sc->sc_dev.dv_xname); + return; + } + if (val == 0x00) + break; + val -= 0x55; + } + + sc->sc_conf3 = LE_C3_ACON; + sc->sc_addr = 0; + sc->sc_memsize = ia->ia_msize; + } else { + sc->sc_mem = malloc(16384, M_DEVBUF, M_NOWAIT); + if (sc->sc_mem == 0) { + printf("%s: couldn't allocate memory for card\n", + sc->sc_dev.dv_xname); + return; + } + + sc->sc_conf3 = 0; + sc->sc_addr = kvtop(sc->sc_mem); + sc->sc_memsize = 16384; + } + + sc->sc_copytodesc = am7990_copytobuf_contig; + sc->sc_copyfromdesc = am7990_copyfrombuf_contig; + sc->sc_copytobuf = am7990_copytobuf_contig; + sc->sc_copyfrombuf = am7990_copyfrombuf_contig; + sc->sc_zerobuf = am7990_zerobuf_contig; + + sc->sc_rdcsr = le_isa_rdcsr; + sc->sc_wrcsr = le_isa_wrcsr; + sc->sc_hwinit = NULL; + + printf("%s", sc->sc_dev.dv_xname); + am7990_config(sc); + + if (ia->ia_drq != DRQUNK) + isa_dmacascade(ia->ia_drq); + + lesc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, + IPL_NET, le_isa_intredge, sc); +} + +/* + * Controller interrupt. + */ +le_isa_intredge(arg) + void *arg; +{ + + if (am7990_intr(arg) == 0) + return (0); + for (;;) + if (am7990_intr(arg) == 0) + return (1); +} diff --git a/sys/dev/isa/if_levar.h b/sys/dev/isa/if_levar.h index e28b35a0966..57c8c3f4ffa 100644 --- a/sys/dev/isa/if_levar.h +++ b/sys/dev/isa/if_levar.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_levar.h,v 1.4 1996/04/29 20:03:23 christos Exp $ */ +/* $NetBSD: if_levar.h,v 1.5 1996/05/07 01:50:07 thorpej Exp $ */ /* * LANCE Ethernet driver header file @@ -20,7 +20,6 @@ #define NE2100 2 #define PCnet_ISA 4 -#define PCnet_PCI 5 #define NE2100_RDP 0x10 #define NE2100_RAP 0x12 @@ -45,44 +44,10 @@ * This structure contains the output queue for the interface, its address, ... */ struct le_softc { - struct device sc_dev; /* base structure */ - struct arpcom sc_arpcom; /* Ethernet common part */ - - void (*sc_copytodesc) /* Copy to descriptor */ - __P((struct le_softc *, void *, int, int)); - void (*sc_copyfromdesc) /* Copy from descriptor */ - __P((struct le_softc *, void *, int, int)); - void (*sc_copytobuf) /* Copy to buffer */ - __P((struct le_softc *, void *, int, int)); - void (*sc_copyfrombuf) /* Copy from buffer */ - __P((struct le_softc *, void *, int, int)); - void (*sc_zerobuf) /* and Zero bytes in buffer */ - __P((struct le_softc *, int, int)); - - 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 + struct am7990_softc sc_am7990; /* glue to MI code */ void *sc_ih; bus_io_handle_t sc_ioh; - void *sc_sh; int sc_card; - int sc_rap, sc_rdp; /* LANCE registers */ + int sc_rap, sc_rdp; /* offsets to LANCE registers */ }; diff --git a/sys/dev/pci/if_de.c b/sys/dev/pci/if_de.c index aefcf00fc41..6c85de4952b 100644 --- a/sys/dev/pci/if_de.c +++ b/sys/dev/pci/if_de.c @@ -1,5 +1,5 @@ -/* $OpenBSD: if_de.c,v 1.8 1996/05/07 07:38:29 deraadt Exp $ */ -/* $NetBSD: if_de.c,v 1.18 1996/05/03 17:32:20 christos Exp $ */ +/* $OpenBSD: if_de.c,v 1.9 1996/05/10 12:41:24 deraadt Exp $ */ +/* $NetBSD: if_de.c,v 1.19 1996/05/07 02:17:18 thorpej Exp $ */ /*- * Copyright (c) 1994, 1995 Matt Thomas (matt@lkg.dec.com) @@ -317,6 +317,7 @@ struct _tulip_softc_t { bus_io_handle_t tulip_memh; /* memory region handle */ #endif #endif + char tulip_xname[IFNAMSIZ]; /* name + unit number */ struct arpcom tulip_ac; tulip_regfile_t tulip_csrs; unsigned tulip_flags; @@ -366,6 +367,7 @@ typedef void ifnet_ret_t; typedef int ioctl_cmd_t; tulip_softc_t *tulips[NDE]; #define TULIP_UNIT_TO_SOFTC(unit) (tulips[unit]) +#define TULIP_IFP_TO_SOFTC(ifp) (TULIP_UNIT_TO_SOFTC((ifp)->if_unit)) #define TULIP_BURSTSIZE(unit) pci_max_burst_len #endif #if defined(__bsdi__) @@ -373,6 +375,7 @@ typedef int ifnet_ret_t; typedef int ioctl_cmd_t; extern struct cfdriver decd; #define TULIP_UNIT_TO_SOFTC(unit) ((tulip_softc_t *) decd.cd_devs[unit]) +#define TULIP_IFP_TO_SOFTC(ifp) (TULIP_UNIT_TO_SOFTC((ifp)->if_unit)) #define TULIP_BURSTSIZE(unit) log2_burst_size #endif #if defined(__NetBSD__) @@ -381,6 +384,7 @@ typedef u_long ioctl_cmd_t; extern struct cfattach de_ca; extern struct cfdriver de_cd; #define TULIP_UNIT_TO_SOFTC(unit) ((tulip_softc_t *) de_cd.cd_devs[unit]) +#define TULIP_IFP_TO_SOFTC(ifp) ((tulip_softc_t *)((ifp)->if_softc)) #endif #ifndef TULIP_BURSTSIZE @@ -388,8 +392,13 @@ extern struct cfdriver de_cd; #endif #define tulip_if tulip_ac.ac_if +#ifdef __NetBSD__ +#define tulip_unit tulip_dev.dv_unit +#define tulip_name tulip_dev.dv_cfdata->cf_driver->cd_name +#else #define tulip_unit tulip_ac.ac_if.if_unit #define tulip_name tulip_ac.ac_if.if_name +#endif #define tulip_bpf tulip_ac.ac_if.if_bpf #define tulip_hwaddr tulip_ac.ac_enaddr @@ -440,14 +449,12 @@ tulip_dc21040_media_select( TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_RESET); if (sc->tulip_if.if_flags & IFF_ALTPHYS) { if ((sc->tulip_flags & TULIP_ALTPHYS) == 0) - printf("%s%d: enabling Thinwire/AUI port\n", - sc->tulip_if.if_name, sc->tulip_if.if_unit); + printf("%s: enabling Thinwire/AUI port\n", sc->tulip_xname); TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_AUI); sc->tulip_flags |= TULIP_ALTPHYS; } else { if (sc->tulip_flags & TULIP_ALTPHYS) - printf("%s%d: enabling 10baseT/UTP port\n", - sc->tulip_if.if_name, sc->tulip_if.if_unit); + printf("%s: enabling 10baseT/UTP port\n", sc->tulip_xname); TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_10BASET); sc->tulip_flags &= ~TULIP_ALTPHYS; sc->tulip_media = TULIP_MEDIA_10BASET; @@ -478,8 +485,7 @@ tulip_zx314_media_select( |TULIP_CMD_BACKOFFCTR; TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_RESET); if (sc->tulip_flags & TULIP_ALTPHYS) - printf("%s%d: enabling 10baseT/UTP port\n", - sc->tulip_if.if_name, sc->tulip_if.if_unit); + printf("%s: enabling 10baseT/UTP port\n", sc->tulip_xname); TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_10BASET); sc->tulip_flags &= ~TULIP_ALTPHYS; sc->tulip_media = TULIP_MEDIA_10BASET; @@ -525,8 +531,7 @@ tulip_dc21140_evalboard_media_select( TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EB_INIT); if (sc->tulip_if.if_flags & IFF_ALTPHYS) { if ((sc->tulip_flags & TULIP_ALTPHYS) == 0) - printf("%s%d: enabling 100baseTX UTP port\n", - sc->tulip_if.if_name, sc->tulip_if.if_unit); + printf("%s: enabling 100baseTX UTP port\n", sc->tulip_xname); sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER; sc->tulip_cmdmode &= ~TULIP_CMD_TXTHRSHLDCTL; @@ -534,8 +539,7 @@ tulip_dc21140_evalboard_media_select( sc->tulip_media = TULIP_MEDIA_100BASET; } else { if (sc->tulip_flags & TULIP_ALTPHYS) - printf("%s%d: enabling 10baseT UTP port\n", - sc->tulip_if.if_name, sc->tulip_if.if_unit); + printf("%s: enabling 10baseT UTP port\n", sc->tulip_xname); sc->tulip_cmdmode &= ~(TULIP_CMD_PORTSELECT |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER); sc->tulip_cmdmode |= TULIP_CMD_TXTHRSHLDCTL; @@ -579,8 +583,7 @@ tulip_dc21140_cogent_em100_media_select( TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EM100_PINS); TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EM100_INIT); if ((sc->tulip_flags & TULIP_ALTPHYS) == 0) - printf("%s%d: enabling 100baseTX UTP port\n", - sc->tulip_if.if_name, sc->tulip_if.if_unit); + printf("%s: enabling 100baseTX UTP port\n", sc->tulip_xname); sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER; sc->tulip_cmdmode &= ~TULIP_CMD_TXTHRSHLDCTL; @@ -627,8 +630,7 @@ tulip_dc21140_znyx_zx34x_media_select( TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_ZX34X_INIT); if (sc->tulip_if.if_flags & IFF_ALTPHYS) { if ((sc->tulip_flags & TULIP_ALTPHYS) == 0) - printf("%s%d: enabling 100baseTX UTP port\n", - sc->tulip_if.if_name, sc->tulip_if.if_unit); + printf("%s: enabling 100baseTX UTP port\n", sc->tulip_xname); sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER; sc->tulip_cmdmode &= ~TULIP_CMD_TXTHRSHLDCTL; @@ -636,8 +638,7 @@ tulip_dc21140_znyx_zx34x_media_select( sc->tulip_media = TULIP_MEDIA_100BASET; } else { if (sc->tulip_flags & TULIP_ALTPHYS) - printf("%s%d: enabling 10baseT UTP port\n", - sc->tulip_if.if_name, sc->tulip_if.if_unit); + printf("%s: enabling 10baseT UTP port\n", sc->tulip_xname); sc->tulip_cmdmode &= ~(TULIP_CMD_PORTSELECT |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER); sc->tulip_cmdmode |= TULIP_CMD_TXTHRSHLDCTL; @@ -689,8 +690,7 @@ tulip_dc21140_de500_media_select( TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_DE500_PINS); if (sc->tulip_if.if_flags & IFF_ALTPHYS) { if ((sc->tulip_flags & TULIP_ALTPHYS) == 0) - printf("%s%d: enabling 100baseTX UTP port\n", - sc->tulip_if.if_name, sc->tulip_if.if_unit); + printf("%s: enabling 100baseTX UTP port\n", sc->tulip_xname); sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER; sc->tulip_cmdmode &= ~TULIP_CMD_TXTHRSHLDCTL; @@ -700,8 +700,7 @@ tulip_dc21140_de500_media_select( TULIP_GP_DE500_HALFDUPLEX|TULIP_GP_DE500_FORCE_100); } else { if (sc->tulip_flags & TULIP_ALTPHYS) - printf("%s%d: enabling 10baseT UTP port\n", - sc->tulip_if.if_name, sc->tulip_if.if_unit); + printf("%s: enabling 10baseT UTP port\n", sc->tulip_xname); sc->tulip_cmdmode &= ~(TULIP_CMD_PORTSELECT |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER); sc->tulip_cmdmode |= TULIP_CMD_TXTHRSHLDCTL; @@ -827,8 +826,7 @@ tulip_dc21041_media_select( && sc->tulip_media != TULIP_MEDIA_AUI) || (sc->tulip_probe_state == TULIP_PROBE_BNC && sc->tulip_media != TULIP_MEDIA_AUI)) { - printf("%s%d: enabling %s port\n", - sc->tulip_if.if_name, sc->tulip_if.if_unit, + printf("%s: enabling %s port\n", sc->tulip_xname, sc->tulip_probe_state == TULIP_PROBE_BNC ? "Thinwire/BNC" : "AUI"); if (sc->tulip_probe_state == TULIP_PROBE_AUI) @@ -888,8 +886,8 @@ tulip_dc21041_media_select( sc->tulip_flags &= ~TULIP_WANTRXACT; sc->tulip_gpticks = 4; } else { - printf("%s%d: autosense failed: cable problem?\n", - sc->tulip_name, sc->tulip_unit); + printf("%s: autosense failed: cable problem?\n", + sc->tulip_xname); } } /* @@ -920,8 +918,7 @@ tulip_dc21041_media_select( * proper media to use. */ if (sc->tulip_media != TULIP_MEDIA_10BASET) - printf("%s%d: enabling 10baseT/UTP port\n", - sc->tulip_if.if_name, sc->tulip_if.if_unit); + printf("%s: enabling 10baseT/UTP port\n", sc->tulip_xname); if (sc->tulip_media != TULIP_MEDIA_10BASET || (sc->tulip_flags & TULIP_INRESET)) { sc->tulip_media = TULIP_MEDIA_10BASET; @@ -1282,7 +1279,7 @@ static ifnet_ret_t tulip_start( struct ifnet * const ifp) { - tulip_softc_t * const sc = TULIP_UNIT_TO_SOFTC(ifp->if_unit); + tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp); struct ifqueue * const ifq = &ifp->if_snd; tulip_ringinfo_t * const ri = &sc->tulip_txinfo; struct mbuf *m, *m0, *next_m0; @@ -1514,8 +1511,8 @@ tulip_intr( } } if (csr & TULIP_STS_ABNRMLINTR) { - printf("%s%d: abnormal interrupt: 0x%05x [0x%05x]\n", - sc->tulip_name, sc->tulip_unit, csr, csr & sc->tulip_intrmask); + printf("%s: abnormal interrupt: 0x%05x [0x%05x]\n", + sc->tulip_xname, csr, csr & sc->tulip_intrmask); TULIP_WRITE_CSR(sc, csr_command, sc->tulip_cmdmode); } if (csr & TULIP_STS_RXINTR) @@ -1930,7 +1927,7 @@ tulip_ioctl( ioctl_cmd_t cmd, caddr_t data) { - tulip_softc_t * const sc = TULIP_UNIT_TO_SOFTC(ifp->if_unit); + tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp); struct ifaddr *ifa = (struct ifaddr *)data; struct ifreq *ifr = (struct ifreq *) data; int s, error = 0; @@ -2048,15 +2045,22 @@ tulip_attach( ifp->if_start = tulip_start; #if defined(__FreeBSD__) - printf("%s%d", sc->tulip_name, sc->tulip_unit); + printf("%s", sc->tulip_xname); #elif defined(__bsdi__) - printf("\n%s%d", sc->tulip_name, sc->tulip_unit); + printf("\n%s", sc->tulip_xname); #endif +#if defined(__NetBSD__) + printf(": %s%s pass %d.%d\n%s: Ethernet address %s\n", +#else printf(": %s%s pass %d.%d Ethernet address %s\n", +#endif sc->tulip_boardsw->bd_description, tulip_chipdescs[sc->tulip_chipid], (sc->tulip_revinfo & 0xF0) >> 4, sc->tulip_revinfo & 0x0F, +#if defined(__NetBSD__) + sc->tulip_dev.dv_xname, +#endif ether_sprintf(sc->tulip_hwaddr)); if ((*sc->tulip_boardsw->bd_media_probe)(sc)) { @@ -2515,9 +2519,19 @@ tulip_pci_attach( } sc->tulip_chipid = chipid; +#if defined(__NetBSD__) + bcopy(self->dv_xname, sc->tulip_if.if_xname, IFNAMSIZ); + sc->tulip_if.if_softc = sc; +#else sc->tulip_unit = unit; sc->tulip_name = "de"; +#endif sc->tulip_revinfo = revinfo; + + /* Set up human-readable name. */ + bzero(sc->tulip_xname, sizeof(sc->tulip_xname)); + sprintf(sc->tulip_xname, "%s%d", sc->tulip_name, sc->tulip_unit); + #if defined(__FreeBSD__) #if defined(TULIP_IOMAPPED) retval = pci_map_port(config_id, PCI_CBIO, &csr_base); @@ -2567,14 +2581,14 @@ tulip_pci_attach( tulip_initring(sc, &sc->tulip_txinfo, txdescs, TULIP_TXDESCS); if ((retval = tulip_read_macaddr(sc)) < 0) { #ifdef __FreeBSD__ - printf("%s%d", sc->tulip_name, sc->tulip_unit); + printf("%s", sc->tulip_xname); #endif printf(": can't read ENET ROM (why=%d) (", retval); for (idx = 0; idx < 32; idx++) printf("%02x", sc->tulip_rombuf[idx]); printf("\n"); - printf("%s%d: %s%s pass %d.%d Ethernet address %s\n", - sc->tulip_name, sc->tulip_unit, + printf("%s: %s%s pass %d.%d Ethernet address %s\n", + sc->tulip_xname, (sc->tulip_boardsw != NULL ? sc->tulip_boardsw->bd_description : ""), tulip_chipdescs[sc->tulip_chipid], (sc->tulip_revinfo & 0xF0) >> 4, sc->tulip_revinfo & 0x0F, @@ -2609,14 +2623,13 @@ tulip_pci_attach( } sc->tulip_ats = shutdownhook_establish(tulip_pci_shutdown, sc); if (sc->tulip_ats == NULL) - printf("\n%s%d: warning: couldn't establish shutdown hook", - sc->tulip_name, sc->tulip_unit); + printf("\n%s: warning: couldn't establish shutdown hook", + sc->tulip_xname); #endif #if defined(__FreeBSD__) if (sc->tulip_boardsw->bd_type != TULIP_DC21040_ZX314_SLAVE) { if (!pci_map_int (config_id, tulip_intr, (void*) sc, &net_imask)) { - printf("%s%d: couldn't map interrupt\n", - sc->tulip_name, sc->tulip_unit); + printf("%s: couldn't map interrupt\n", sc->tulip_xname); return; } } diff --git a/sys/dev/pci/if_fpa.c b/sys/dev/pci/if_fpa.c index eb6be356f02..7a53b6df129 100644 --- a/sys/dev/pci/if_fpa.c +++ b/sys/dev/pci/if_fpa.c @@ -1,5 +1,5 @@ -/* $OpenBSD: if_fpa.c,v 1.5 1996/04/21 22:25:19 deraadt Exp $ */ -/* $NetBSD: if_fpa.c,v 1.7 1996/03/17 00:55:30 thorpej Exp $ */ +/* $OpenBSD: if_fpa.c,v 1.6 1996/05/10 12:41:26 deraadt Exp $ */ +/* $NetBSD: if_fpa.c,v 1.8 1996/05/07 02:17:23 thorpej Exp $ */ /*- * Copyright (c) 1995 Matt Thomas (thomas@lkg.dec.com) @@ -191,9 +191,24 @@ extern struct cfdriver fpa_cd; #define PDQ_PCI_UNIT_TO_SOFTC(unit) ((pdq_softc_t *)fpa_cd.cd_devs[unit]) #endif +#if defined(__NetBSD__) static ifnet_ret_t pdq_pci_ifinit( - int unit) + struct ifnet *ifp) +{ + pdq_ifinit((pdq_softc_t *)(ifp->if_softc)); +} + +static ifnet_ret_t +pdq_pci_ifwatchdog( + struct ifnet *ifp) +{ + pdq_ifwatchdog((pdq_softc_t *)(ifp->if_softc)); +} +#else +static ifnet_ret_t +pdq_pci_ifinit( + int unit) { pdq_ifinit(PDQ_PCI_UNIT_TO_SOFTC(unit)); } @@ -204,6 +219,7 @@ pdq_pci_ifwatchdog( { pdq_ifwatchdog(PDQ_PCI_UNIT_TO_SOFTC(unit)); } +#endif static int pdq_pci_ifintr( @@ -428,39 +444,40 @@ pdq_pci_attach( pdq_uint32_t data; pdq_softc_t * const sc = (pdq_softc_t *) self; struct pci_attach_args * const pa = (struct pci_attach_args *) aux; + pci_chipset_tag_t pc = pa->pa_pc; - data = pci_conf_read(pa->pa_tag, PCI_CFLT); + data = pci_conf_read(pc, pa->pa_tag, PCI_CFLT); if ((data & 0xFF00) == 0) { data &= ~0xFF00; data |= DEFPA_LATENCY << 8; - pci_conf_write(pa->pa_tag, PCI_CFLT, data); + pci_conf_write(pc, pa->pa_tag, PCI_CFLT, data); } if (pci_map_mem(pa->pa_tag, PCI_CBMA, &va_csrs, &pa_csrs)) return; - sc->sc_if.if_name = "fpa"; - sc->sc_if.if_unit = sc->sc_dev.dv_unit; + bcopy(sc->sc_dev.dv_xname, sc->sc_if.if_xname, IFNAMSIZ); + sc->sc_if.if_softc = sc; sc->sc_if.if_flags = 0; - sc->sc_pdq = pdq_initialize((void *) va_csrs, sc->sc_if.if_name, - sc->sc_if.if_unit, (void *) sc, PDQ_DEFPA); + sc->sc_pdq = pdq_initialize((void *) va_csrs, + sc->sc_dev.dv_cfdata->cf_driver->cd_name, sc->sc_dev.dv_unit, + (void *) sc, PDQ_DEFPA); if (sc->sc_pdq == NULL) return; bcopy((caddr_t) sc->sc_pdq->pdq_hwaddr.lanaddr_bytes, sc->sc_ac.ac_enaddr, 6); pdq_ifattach(sc, pdq_pci_ifinit, pdq_pci_ifwatchdog); - sc->sc_ih = pci_map_int(pa->pa_tag, IPL_NET, pdq_pci_ifintr, sc - sc->sc_dev.dv_xname); + sc->sc_ih = pci_map_int(pa->pa_tag, IPL_NET, pdq_pci_ifintr, sc); if (sc->sc_ih == NULL) { - printf("fpa%d: error: couldn't map interrupt\n", sc->sc_if.if_unit); + printf("%s: error: couldn't map interrupt\n", sc->sc_dev.dv_xname); return; } #if 0 sc->sc_ats = shutdownhook_establish(pdq_hwreset, sc); if (sc->sc_ats == NULL) - printf("fpa%d: warning: couldn't establish shutdown hook\n", - sc->sc_if.if_unit); + printf("%s: warning: couldn't establish shutdown hook\n", + sc->sc_dev.dv_xname); #endif } diff --git a/sys/dev/pci/if_le_pci.c b/sys/dev/pci/if_le_pci.c new file mode 100644 index 00000000000..e08d8906a76 --- /dev/null +++ b/sys/dev/pci/if_le_pci.c @@ -0,0 +1,206 @@ +/* $NetBSD: if_le_pci.c,v 1.1 1996/05/07 02:03:02 thorpej Exp $ */ + +/*- + * Copyright (c) 1995 Charles M. Hannum. All rights reserved. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_le.c 8.2 (Berkeley) 11/16/93 + */ + +#include "bpfilter.h" + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef INET +#include +#include +#endif + +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include + +int le_pci_match __P((struct device *, void *, void *)); +void le_pci_attach __P((struct device *, struct device *, void *)); + +struct cfattach le_pci_ca = { + sizeof(struct le_softc), le_pci_match, le_pci_attach +}; + +hide void le_pci_wrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t)); +hide u_int16_t le_pci_rdcsr __P((struct am7990_softc *, u_int16_t)); + +hide void +le_pci_wrcsr(sc, port, val) + struct am7990_softc *sc; + u_int16_t port, val; +{ + + outw(((struct le_softc *)sc)->sc_rap, port); + outw(((struct le_softc *)sc)->sc_rdp, val); +} + +hide u_int16_t +le_pci_rdcsr(sc, port) + struct am7990_softc *sc; + u_int16_t port; +{ + u_int16_t val; + + outw(((struct le_softc *)sc)->sc_rap, port); + val = inw(((struct le_softc *)sc)->sc_rdp); + return (val); +} + +int +le_pci_match(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct pci_attach_args *pa = aux; + + if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_AMD) + return (0); + + switch (PCI_PRODUCT(pa->pa_id)) { + case PCI_PRODUCT_AMD_PCNET_PCI: + return (1); + } + + return (0); +} + +void +le_pci_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct le_softc *lesc = (void *)self; + struct am7990_softc *sc = &lesc->sc_am7990; + struct pci_attach_args *pa = aux; + pci_chipset_tag_t pc = pa->pa_pc; + pci_intr_handle_t ih; + pcireg_t csr; + int iobase, i; + const char *model, *intrstr; + + switch (PCI_PRODUCT(pa->pa_id)) { + case PCI_PRODUCT_AMD_PCNET_PCI: + model = "PCnet-PCI Ethernet"; + lesc->sc_rap = iobase + PCNET_PCI_RAP; + lesc->sc_rdp = iobase + PCNET_PCI_RDP; + break; + + default: + model = "unknown model!"; + } + + printf(": %s\n", sc->sc_dev.dv_xname, model); + + if (pci_map_io(pa->pa_tag, 0x10, &iobase)) + return; + + /* + * Extract the physical MAC address from the ROM. + */ + for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++) + sc->sc_arpcom.ac_enaddr[i] = inb(iobase + i); + + sc->sc_mem = malloc(16384, M_DEVBUF, M_NOWAIT); + if (sc->sc_mem == 0) { + printf("%s: couldn't allocate memory for card\n", + sc->sc_dev.dv_xname); + return; + } + + sc->sc_conf3 = 0; + sc->sc_addr = kvtop(sc->sc_mem); /* XXX XXX XXX */ + sc->sc_memsize = 16384; + + sc->sc_copytodesc = am7990_copytobuf_contig; + sc->sc_copyfromdesc = am7990_copyfrombuf_contig; + sc->sc_copytobuf = am7990_copytobuf_contig; + sc->sc_copyfrombuf = am7990_copyfrombuf_contig; + sc->sc_zerobuf = am7990_zerobuf_contig; + + sc->sc_rdcsr = le_pci_rdcsr; + sc->sc_wrcsr = le_pci_wrcsr; + sc->sc_hwinit = NULL; + + printf("%s", sc->sc_dev.dv_xname); + am7990_config(sc); + + /* Enable the card. */ + csr = pci_conf_read(pa->pa_bc, pa->pa_tag, + PCI_COMMAND_STATUS_REG); + pci_conf_write(pa->pa_bc, pa->pa_tag, PCI_COMMAND_STATUS_REG, + csr | PCI_COMMAND_MASTER_ENABLE); + + /* Map and establish the interrupt. */ + if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin, + pa->pa_intrline, &ih)) { + printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname); + return; + } + intrstr = pci_intr_string(pc, ih); + lesc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, am7990_intr, sc, + sc->sc_dev.dv_xname); + if (lesc->sc_ih == NULL) { + printf("%s: couldn't establish interrupt", + sc->sc_dev.dv_xname); + if (intrstr != NULL) + printf(" at %s", intrstr); + printf("\n"); + return; + } + printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr); +} diff --git a/sys/dev/pci/if_levar.h b/sys/dev/pci/if_levar.h new file mode 100644 index 00000000000..03f5e0c9312 --- /dev/null +++ b/sys/dev/pci/if_levar.h @@ -0,0 +1,31 @@ +/* $NetBSD: if_levar.h,v 1.1 1996/05/07 02:03:04 thorpej Exp $ */ + +/* + * LANCE Ethernet driver header file + * + * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. + * + * Copyright (C) 1993, Paul Richards. This software may be used, modified, + * copied, distributed, and sold, in both source and binary form provided + * that the above copyright and these terms are retained. Under no + * circumstances is the author responsible for the proper functioning + * of this software, nor does the author assume any responsibility + * for damages incurred with its use. + */ + +#define PCNET_PCI_RDP 0x10 +#define PCNET_PCI_RAP 0x12 + +/* + * Ethernet software status per interface. + * + * 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, ... + */ +struct le_softc { + struct am7990_softc sc_am7990; /* glue to MI code */ + + void *sc_ih; + int sc_rap, sc_rdp; /* offsets to LANCE registers */ +}; diff --git a/sys/dev/tc/if_le.c b/sys/dev/tc/if_le.c index 51415a94208..67368f06e8d 100644 --- a/sys/dev/tc/if_le.c +++ b/sys/dev/tc/if_le.c @@ -1,170 +1 @@ -/* $OpenBSD: if_le.c,v 1.4 1996/05/02 13:51:48 deraadt Exp $ */ -/* $NetBSD: if_le.c,v 1.9 1996/04/22 02:54:10 christos Exp $ */ - -/*- - * Copyright (c) 1995 Charles M. Hannum. All rights reserved. - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell and Rick Macklem. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)if_le.c 8.2 (Berkeley) 11/16/93 - */ - -#include "bpfilter.h" - -#include -#include -#include -#include -#include -#include - -#include - -#ifdef INET -#include -#include -#endif - -#include -#include -#define LE_NEED_BUF_CONTIG -#define LE_NEED_BUF_GAP2 -#define LE_NEED_BUF_GAP16 -#include -#include - -/* access LANCE registers */ -void lewritereg __P((volatile u_short *regptr, u_short val)); -#define LERDWR(cntl, src, dst) { (dst) = (src); tc_mb(); } -#define LEWREG(src, dst) lewritereg(&(dst), (src)) - -#define LE_SOFTC(unit) le_cd.cd_devs[unit] -#define LE_DELAY(x) DELAY(x) - -struct cfdriver le_cd = { - NULL, "le", DV_IFNET -}; - -void -dec_le_common_attach(sc, eap) - struct le_softc *sc; - u_char *eap; -{ - int i; - - sc->sc_conf3 = 0; - sc->sc_addr = 0; - sc->sc_memsize = 65536; - - /* - * Get the ethernet address out of rom - */ - for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++) { - sc->sc_arpcom.ac_enaddr[i] = *eap; - eap += 4; - } - - sc->sc_arpcom.ac_if.if_name = le_cd.cd_name; - leconfig(sc); -} - -integrate void -lehwinit(sc) - struct le_softc *sc; -{ -} - -integrate void -lewrcsr(sc, port, val) - struct le_softc *sc; - u_int16_t port, val; -{ - struct lereg1 *ler1 = sc->sc_r1; - - LEWREG(port, ler1->ler1_rap); - LERDWR(port, val, ler1->ler1_rdp); -} - -integrate u_int16_t -lerdcsr(sc, port) - struct le_softc *sc; - u_int16_t port; -{ - struct lereg1 *ler1 = sc->sc_r1; - u_int16_t val; - - LEWREG(port, ler1->ler1_rap); - LERDWR(0, ler1->ler1_rdp, val); - return (val); -} - -/* - * Write a lance register port, reading it back to ensure success. This seems - * to be necessary during initialization, since the chip appears to be a bit - * pokey sometimes. - */ -void -lewritereg(regptr, val) - register volatile u_short *regptr; - register u_short val; -{ - register int i = 0; - - while (*regptr != val) { - *regptr = val; - tc_mb(); - if (++i > 10000) { - printf("le: Reg did not settle (to x%x): x%x\n", val, - *regptr); - return; - } - DELAY(100); - } -} - -/* - * Routines for accessing the transmit and receive buffers are provided - * by am7990.c, because of the LE_NEED_BUF_* macros defined above. - * Unfortunately, CPU addressing of these buffers is done in one of - * 3 ways: - * - contiguous (for the 3max and turbochannel option card) - * - gap2, which means shorts (2 bytes) interspersed with short (2 byte) - * spaces (for the pmax) - * - gap16, which means 16bytes interspersed with 16byte spaces - * for buffers which must begin on a 32byte boundary (for 3min, maxine, - * and alpha) - * The buffer offset is the logical byte offset, assuming contiguous storage. - */ - -#include +/* $OpenBSD: if_le.c,v 1.5 1996/05/10 12:41:28 deraadt Exp $ */ diff --git a/sys/dev/tc/if_le_dec.c b/sys/dev/tc/if_le_dec.c new file mode 100644 index 00000000000..5e2093849f9 --- /dev/null +++ b/sys/dev/tc/if_le_dec.c @@ -0,0 +1,158 @@ +/* $NetBSD: if_le_dec.c,v 1.1 1996/05/07 02:24:55 thorpej Exp $ */ + +/*- + * Copyright (c) 1995 Charles M. Hannum. All rights reserved. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_le.c 8.2 (Berkeley) 11/16/93 + */ + +#include "bpfilter.h" + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef INET +#include +#include +#endif + +#include +#include + +#include +#include + +/* access LANCE registers */ +void le_dec_writereg __P((volatile u_short *regptr, u_short val)); +#define LERDWR(cntl, src, dst) { (dst) = (src); tc_mb(); } +#define LEWREG(src, dst) le_dec_writereg(&(dst), (src)) + +hide void le_dec_wrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t)); +hide u_int16_t le_dec_rdcsr __P((struct am7990_softc *, u_int16_t)); + +void +dec_le_common_attach(sc, eap) + struct am7990_softc *sc; + u_char *eap; +{ + int i; + + sc->sc_rdcsr = le_dec_rdcsr; + sc->sc_wrcsr = le_dec_wrcsr; + sc->sc_hwinit = NULL; + + sc->sc_conf3 = 0; + sc->sc_addr = 0; + sc->sc_memsize = 65536; + + /* + * Get the ethernet address out of rom + */ + for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++) { + sc->sc_arpcom.ac_enaddr[i] = *eap; + eap += 4; + } + + am7990_config(sc); +} + +hide void +le_dec_wrcsr(sc, port, val) + struct am7990_softc *sc; + u_int16_t port, val; +{ + struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; + + LEWREG(port, ler1->ler1_rap); + LERDWR(port, val, ler1->ler1_rdp); +} + +hide u_int16_t +le_dec_rdcsr(sc, port) + struct am7990_softc *sc; + u_int16_t port; +{ + struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; + u_int16_t val; + + LEWREG(port, ler1->ler1_rap); + LERDWR(0, ler1->ler1_rdp, val); + return (val); +} + +/* + * Write a lance register port, reading it back to ensure success. This seems + * to be necessary during initialization, since the chip appears to be a bit + * pokey sometimes. + */ +void +le_dec_writereg(regptr, val) + register volatile u_short *regptr; + register u_short val; +{ + register int i = 0; + + while (*regptr != val) { + *regptr = val; + tc_mb(); + if (++i > 10000) { + printf("le: Reg did not settle (to x%x): x%x\n", val, + *regptr); + return; + } + DELAY(100); + } +} + +/* + * Routines for accessing the transmit and receive buffers are provided + * by am7990.c, because of the LE_NEED_BUF_* macros defined above. + * Unfortunately, CPU addressing of these buffers is done in one of + * 3 ways: + * - contiguous (for the 3max and turbochannel option card) + * - gap2, which means shorts (2 bytes) interspersed with short (2 byte) + * spaces (for the pmax) + * - gap16, which means 16bytes interspersed with 16byte spaces + * for buffers which must begin on a 32byte boundary (for 3min, maxine, + * and alpha) + * The buffer offset is the logical byte offset, assuming contiguous storage. + */ diff --git a/sys/dev/tc/if_le_ioasic.c b/sys/dev/tc/if_le_ioasic.c index 2a1fea050b6..a0c22099583 100644 --- a/sys/dev/tc/if_le_ioasic.c +++ b/sys/dev/tc/if_le_ioasic.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_le_ioasic.c,v 1.1 1996/04/18 00:50:13 cgd Exp $ */ +/* $NetBSD: if_le_ioasic.c,v 1.2 1996/05/07 02:24:56 thorpej Exp $ */ /* * Copyright (c) 1996 Carnegie-Mellon University. @@ -45,12 +45,10 @@ #include #endif -#include #include -#define LE_NEED_BUF_GAP2 -#define LE_NEED_BUF_GAP16 #include +#include #include #include @@ -59,6 +57,17 @@ extern caddr_t le_iomem; int le_ioasic_match __P((struct device *, void *, void *)); void le_ioasic_attach __P((struct device *, struct device *, void *)); +hide void le_ioasic_copytobuf_gap2 __P((struct am7990_softc *, void *, + int, int)); +hide void le_ioasic_copyfrombuf_gap2 __P((struct am7990_softc *, void *, + int, int)); + +hide void le_ioasic_copytobuf_gap16 __P((struct am7990_softc *, void *, + int, int)); +hide void le_ioasic_copyfrombuf_gap16 __P((struct am7990_softc *, void *, + int, int)); +hide void le_ioasic_zerobuf_gap16 __P((struct am7990_softc *, int, int)); + struct cfattach le_ioasic_ca = { sizeof(struct le_softc), le_ioasic_match, le_ioasic_attach }; @@ -84,21 +93,170 @@ le_ioasic_attach(parent, self, aux) void *aux; { struct ioasicdev_attach_args *d = aux; - register struct le_softc *sc = (void *)self; + register struct le_softc *lesc = (void *)self; + register struct am7990_softc *sc = &lesc->sc_am7990; - sc->sc_r1 = (struct lereg1 *) + lesc->sc_r1 = (struct lereg1 *) TC_DENSE_TO_SPARSE(TC_PHYS_TO_UNCACHED(d->iada_addr)); sc->sc_mem = (void *)TC_PHYS_TO_UNCACHED(le_iomem); - sc->sc_copytodesc = am7990_copytobuf_gap2; - sc->sc_copyfromdesc = am7990_copyfrombuf_gap2; - sc->sc_copytobuf = am7990_copytobuf_gap16; - sc->sc_copyfrombuf = am7990_copyfrombuf_gap16; - sc->sc_zerobuf = am7990_zerobuf_gap16; + sc->sc_copytodesc = le_ioasic_copytobuf_gap2; + sc->sc_copyfromdesc = le_ioasic_copyfrombuf_gap2; + sc->sc_copytobuf = le_ioasic_copytobuf_gap16; + sc->sc_copyfrombuf = le_ioasic_copyfrombuf_gap16; + sc->sc_zerobuf = le_ioasic_zerobuf_gap16; ioasic_lance_dma_setup(le_iomem); /* XXX more thought */ dec_le_common_attach(sc, ioasic_lance_ether_address()); - ioasic_intr_establish(parent, d->iada_cookie, TC_IPL_NET, leintr, sc); + ioasic_intr_establish(parent, d->iada_cookie, TC_IPL_NET, + am7990_intr, sc); +} + +/* + * Special memory access functions needed by ioasic-attached LANCE + * chips. + */ + +/* + * gap2: two bytes of data followed by two bytes of pad. + * + * Buffers must be 4-byte aligned. The code doesn't worry about + * doing an extra byte. + */ + +void +le_ioasic_copytobuf_gap2(sc, fromv, boff, len) + struct am7990_softc *sc; + void *fromv; + int boff; + register int len; +{ + volatile caddr_t buf = sc->sc_mem; + register caddr_t from = fromv; + register volatile u_int16_t *bptr; + + if (boff & 0x1) { + /* handle unaligned first byte */ + bptr = ((volatile u_int16_t *)buf) + (boff - 1); + *bptr = (*from++ << 8) | (*bptr & 0xff); + bptr += 2; + len--; + } else + bptr = ((volatile u_int16_t *)buf) + boff; + while (len > 1) { + *bptr = (from[1] << 8) | (from[0] & 0xff); + bptr += 2; + from += 2; + len -= 2; + } + if (len == 1) + *bptr = (u_int16_t)*from; +} + +void +le_ioasic_copyfrombuf_gap2(sc, tov, boff, len) + struct am7990_softc *sc; + void *tov; + int boff, len; +{ + volatile caddr_t buf = sc->sc_mem; + register caddr_t to = tov; + register volatile u_int16_t *bptr; + register u_int16_t tmp; + + if (boff & 0x1) { + /* handle unaligned first byte */ + bptr = ((volatile u_int16_t *)buf) + (boff - 1); + *to++ = (*bptr >> 8) & 0xff; + bptr += 2; + len--; + } else + bptr = ((volatile u_int16_t *)buf) + boff; + while (len > 1) { + tmp = *bptr; + *to++ = tmp & 0xff; + *to++ = (tmp >> 8) & 0xff; + bptr += 2; + len -= 2; + } + if (len == 1) + *to = *bptr & 0xff; +} + +/* + * gap16: 16 bytes of data followed by 16 bytes of pad. + * + * Buffers must be 32-byte aligned. + */ + +void +le_ioasic_copytobuf_gap16(sc, fromv, boff, len) + struct am7990_softc *sc; + void *fromv; + int boff; + register int len; +{ + volatile caddr_t buf = sc->sc_mem; + register caddr_t from = fromv; + register caddr_t bptr; + register int xfer; + + bptr = buf + ((boff << 1) & ~0x1f); + boff &= 0xf; + xfer = min(len, 16 - boff); + while (len > 0) { + bcopy(from, bptr + boff, xfer); + from += xfer; + bptr += 32; + boff = 0; + len -= xfer; + xfer = min(len, 16); + } +} + +void +le_ioasic_copyfrombuf_gap16(sc, tov, boff, len) + struct am7990_softc *sc; + void *tov; + int boff, len; +{ + volatile caddr_t buf = sc->sc_mem; + register caddr_t to = tov; + register caddr_t bptr; + register int xfer; + + bptr = buf + ((boff << 1) & ~0x1f); + boff &= 0xf; + xfer = min(len, 16 - boff); + while (len > 0) { + bcopy(bptr + boff, to, xfer); + to += xfer; + bptr += 32; + boff = 0; + len -= xfer; + xfer = min(len, 16); + } +} + +void +le_ioasic_zerobuf_gap16(sc, boff, len) + struct am7990_softc *sc; + int boff, len; +{ + volatile caddr_t buf = sc->sc_mem; + register caddr_t bptr; + register int xfer; + + bptr = buf + ((boff << 1) & ~0x1f); + boff &= 0xf; + xfer = min(len, 16 - boff); + while (len > 0) { + bzero(bptr + boff, xfer); + bptr += 32; + boff = 0; + len -= xfer; + xfer = min(len, 16); + } } diff --git a/sys/dev/tc/if_le_tc.c b/sys/dev/tc/if_le_tc.c index 194a5e394d7..e329a3da2e3 100644 --- a/sys/dev/tc/if_le_tc.c +++ b/sys/dev/tc/if_le_tc.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_le_tc.c,v 1.1 1996/04/18 00:50:14 cgd Exp $ */ +/* $NetBSD: if_le_tc.c,v 1.2 1996/05/07 02:24:57 thorpej Exp $ */ /* * Copyright (c) 1996 Carnegie-Mellon University. @@ -45,11 +45,10 @@ #include #endif -#include #include -#define LE_NEED_BUF_CONTIG #include +#include #include int le_tc_match __P((struct device *, void *, void *)); @@ -82,14 +81,15 @@ le_tc_attach(parent, self, aux) struct device *parent, *self; void *aux; { - register struct le_softc *sc = (void *)self; + register struct le_softc *lesc = (void *)self; + register struct am7990_softc *sc = &lesc->sc_am7990; struct tc_attach_args *d = aux; /* * It's on the turbochannel proper, or a kn02 * baseboard implementation of a TC option card. */ - sc->sc_r1 = (struct lereg1 *)(d->ta_addr + LE_OFFSET_LANCE); + lesc->sc_r1 = (struct lereg1 *)(d->ta_addr + LE_OFFSET_LANCE); sc->sc_mem = (void *)(d->ta_addr + LE_OFFSET_RAM); sc->sc_copytodesc = am7990_copytobuf_contig; @@ -106,5 +106,5 @@ le_tc_attach(parent, self, aux) dec_le_common_attach(sc, (u_char *)(d->ta_addr + LE_OFFSET_ROM + 2)); - tc_intr_establish(parent, d->ta_cookie, TC_IPL_NET, leintr, sc); + tc_intr_establish(parent, d->ta_cookie, TC_IPL_NET, am7990_intr, sc); } diff --git a/sys/dev/tc/if_levar.h b/sys/dev/tc/if_levar.h index 5d6f0c44e8f..a8180677036 100644 --- a/sys/dev/tc/if_levar.h +++ b/sys/dev/tc/if_levar.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_levar.h,v 1.2 1996/04/18 00:50:15 cgd Exp $ */ +/* $NetBSD: if_levar.h,v 1.3 1996/05/07 02:24:58 thorpej Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -60,44 +60,9 @@ struct lereg1 { * This structure contains the output queue for the interface, its address, ... */ struct le_softc { - struct device sc_dev; /* base structure */ - struct arpcom sc_arpcom; /* Ethernet common part */ - - void (*sc_copytodesc) /* Copy to descriptor */ - __P((struct le_softc *, void *, int, int)); - void (*sc_copyfromdesc) /* Copy from descriptor */ - __P((struct le_softc *, void *, int, int)); - - void (*sc_copytobuf) /* Copy to buffer */ - __P((struct le_softc *, void *, int, int)); - void (*sc_copyfrombuf) /* Copy from buffer */ - __P((struct le_softc *, void *, int, int)); - void (*sc_zerobuf) /* and Zero bytes in buffer */ - __P((struct le_softc *, int, int)); - - u_int16_t sc_conf3; /* CSR3 value */ - - void *sc_mem; /* base addr of RAM -- CPU's view */ - u_long sc_addr; /* base addr 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 + struct am7990_softc sc_am7990; /* glue to MI code */ struct lereg1 *sc_r1; /* LANCE registers */ }; -int leintr __P((void *)); -void dec_le_common_attach __P((struct le_softc *, u_char *)); +void dec_le_common_attach __P((struct am7990_softc *, u_char *));