From d583784ae848d51c7839861bbea95e8ee9345c06 Mon Sep 17 00:00:00 2001 From: briggs Date: Sat, 29 Mar 1997 23:26:48 +0000 Subject: [PATCH] Update from Denton Gentry with minor bug fixes by me. Denny says: if_sn.c: - allocate sc->space using malloc (Scott wanted this). - make csr accesses use NIC_PUT/GET, remove sc->sc_csr. - add multicast and IFF_PROMISC support. multicast isn't well tested, but I made sure the unicast case still works. - finish the new arp interface, remove sc->sc_enaddr if_snreg.h: - remove struct sonic_reg if_snvar.h: - add NIC_PUT and NIC_GET macros a la if_ae - remove sc_txhead, it isn't used. if_sn_nubus.c: - clean up support for my SE/30 card. - Move add_nubus_intr from if_sn.c (to keep if_sn.c MI) if_sn_obio.c: - make Q610, C610, Q650, C650, Q800 use EXBUS. - PB500 had a "return" where "break" was intended. PB500 probably wasn't working. - move add_nubus_intr from if_sn.c. - add an "explanation" why Apple's ethernet addr is encoded in token ring format in the PROM. --- sys/arch/mac68k/dev/if_sn.c | 318 +++++++++++++++++------------- sys/arch/mac68k/dev/if_sn_nubus.c | 34 +++- sys/arch/mac68k/dev/if_sn_obio.c | 84 ++++++-- sys/arch/mac68k/dev/if_snreg.h | 134 +++++++------ sys/arch/mac68k/dev/if_snvar.h | 36 +++- 5 files changed, 368 insertions(+), 238 deletions(-) diff --git a/sys/arch/mac68k/dev/if_sn.c b/sys/arch/mac68k/dev/if_sn.c index 718370a16a9..e54842cdde5 100644 --- a/sys/arch/mac68k/dev/if_sn.c +++ b/sys/arch/mac68k/dev/if_sn.c @@ -1,5 +1,5 @@ /* $NetBSD: if_sn.c,v 1.7 1997/03/20 17:47:51 scottr Exp $ */ -/* $OpenBSD: if_sn.c,v 1.16 1997/03/25 05:02:39 briggs Exp $ */ +/* $OpenBSD: if_sn.c,v 1.17 1997/03/29 23:26:48 briggs Exp $ */ /* * National Semiconductor SONIC Driver @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -57,23 +58,10 @@ typedef unsigned char uchar; #include #include -#include "nubus.h" - -/* - * Register access macros: - * SWR is "Sonic Write Register" - * SRD is "Sonic Read Register" - */ -#define SWR(a, x) (a) = (x) -#define SRD(a) ((a) & 0xffff) - -#define wbflush() - static void snwatchdog __P((struct ifnet *)); static int sninit __P((struct sn_softc *sc)); static int snstop __P((struct sn_softc *sc)); static int sonicput __P((struct sn_softc *sc, struct mbuf *m0)); -static void snintr __P((void *, int)); static int snioctl __P((struct ifnet *ifp, u_long cmd, caddr_t data)); static void snstart __P((struct ifnet *ifp)); static void snreset __P((struct sn_softc *sc)); @@ -117,7 +105,7 @@ int ethdebug = 0; * record. System will initialize the interface when it is ready * to accept packets. */ -void +int snsetup(sc) struct sn_softc *sc; { @@ -126,21 +114,30 @@ snsetup(sc) unsigned char *pp; int i; - sc->sc_csr = (struct sonic_reg *) sc->sc_regh; /* - * Disable caching on the SONIC's data space. + * XXX if_sn.c is intended to be MI. Should it allocate memory + * for its descriptor areas, or expect the MD attach code + * to do that? */ - physaccess((caddr_t) sc->space, (caddr_t) kvtop((caddr_t) sc->space), - sizeof(sc->space), PG_V | PG_RW | PG_CI); + sc->space = malloc((SN_NPAGES + 1) * NBPG, M_DEVBUF, M_WAITOK); + if (sc->space == NULL) { + printf ("%s: memory allocation for descriptors failed\n", + sc->sc_dev.dv_xname); + return (1); + } /* - * Put the pup in reset mode (sninit() will fix it later) - * and clear any interrupts. + * Put the pup in reset mode (sninit() will fix it later), + * stop the timer, disable all interrupts and clear any interrupts. */ - sc->sc_csr->s_cr = CR_RST; + NIC_PUT(sc, SNR_CR, CR_RST); + wbflush(); + NIC_PUT(sc, SNR_CR, CR_STP); + wbflush(); + NIC_PUT(sc, SNR_IMR, 0); wbflush(); - sc->sc_csr->s_isr = 0x7fff; + NIC_PUT(sc, SNR_ISR, ISR_ALL); wbflush(); /* @@ -148,10 +145,22 @@ snsetup(sc) * a higher buffer address to a 16 bit offset--this will cause wrap * around problems near the end of 64k !! */ - p = &sc->space[0]; + p = sc->space; pp = (unsigned char *)ROUNDUP ((int)p, NBPG); p = pp; + /* + * Disable caching on the SONIC's data space. + * The pages might not be physically contiguous, so set + * each page individually. + */ + for (i = 0; i < SN_NPAGES; i++) { + physaccess (p, (caddr_t) kvtop(p), NBPG, + PG_V | PG_RW | PG_CI); + p += NBPG; + } + p = pp; + for (i = 0; i < NRRA; i++) { sc->p_rra[i] = (void *)p; sc->v_rra[i] = kvtop(p); @@ -185,14 +194,15 @@ snsetup(sc) p = (unsigned char *)SOALIGN(sc, p); if ((p - pp) > NBPG) { - printf ("sn: sizeof RRA (%ld) + CDA (%ld) +" + printf ("%s: sizeof RRA (%ld) + CDA (%ld) +" "RDA (%ld) + TDA (%ld) > NBPG (%d). Punt!\n", + sc->sc_dev.dv_xname, (ulong)sc->p_cda - (ulong)sc->p_rra[0], (ulong)sc->p_rda[0] - (ulong)sc->p_cda, (ulong)sc->mtda[0].mtd_txp - (ulong)sc->p_rda[0], (ulong)p - (ulong)sc->mtda[0].mtd_txp, NBPG); - return; + return(1); } p = pp + NBPG; @@ -225,7 +235,8 @@ printf("sonic buffers: rra=%p cda=0x%x rda=0x%x tda=0x%x\n", ifp->if_softc = sc; ifp->if_ioctl = snioctl; ifp->if_start = snstart; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_flags = + IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; ifp->if_watchdog = snwatchdog; #if NBPFILTER > 0 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); @@ -233,7 +244,7 @@ printf("sonic buffers: rra=%p cda=0x%x rda=0x%x tda=0x%x\n", if_attach(ifp); ether_ifattach(ifp); - add_nubus_intr(sc->slotno, snintr, (void *) sc); + return (0); } static int @@ -242,10 +253,10 @@ snioctl(ifp, cmd, data) u_long cmd; caddr_t data; { - struct ifaddr *ifa; - struct sn_softc *sc = ifp->if_softc; - int s = splnet(), err = 0; - int temp; + struct ifaddr *ifa; + struct sn_softc *sc = ifp->if_softc; + int s = splnet(), err = 0; + int temp; switch (cmd) { @@ -317,8 +328,6 @@ snioctl(ifp, cmd, data) /* * Encapsulate a packet of type family for the local net. - * Use trailer local net encapsulation if enough data in first - * packet leaves a multiple of 512 bytes of data in remainder. */ static void snstart(ifp) @@ -385,13 +394,13 @@ outloop: * This is called from sonicioctl() when /etc/ifconfig is run to set * the address or switch the i/f on. */ -void caminitialise __P((struct sn_softc *)); -void camentry __P((struct sn_softc *, int, unsigned char *ea)); -void camprogram __P((struct sn_softc *)); -void initialise_tda __P((struct sn_softc *)); -void initialise_rda __P((struct sn_softc *)); -void initialise_rra __P((struct sn_softc *)); -void initialise_tba __P((struct sn_softc *)); +static void caminitialise __P((struct sn_softc *)); +static void camentry __P((struct sn_softc *, int, unsigned char *ea)); +static void camprogram __P((struct sn_softc *)); +static void initialise_tda __P((struct sn_softc *)); +static void initialise_rda __P((struct sn_softc *)); +static void initialise_rra __P((struct sn_softc *)); +static void initialise_tba __P((struct sn_softc *)); /* * reset and restart the SONIC. Called in case of fatal @@ -401,7 +410,6 @@ static void snreset(sc) struct sn_softc *sc; { - printf("snreset\n"); snstop(sc); sninit(sc); } @@ -410,8 +418,8 @@ static int sninit(sc) struct sn_softc *sc; { - struct sonic_reg *csr = sc->sc_csr; - int s; + int s; + unsigned long s_rcr; if (sc->sc_if.if_flags & IFF_RUNNING) /* already running */ @@ -419,20 +427,28 @@ sninit(sc) s = splnet(); - csr->s_cr = CR_RST; /* s_dcr only accessable reset mode! */ + NIC_PUT(sc, SNR_CR, CR_RST); /* DCR only accessable in reset mode! */ /* config it */ - csr->s_dcr = sc->s_dcr | (sc->bitmode ? DCR_DW32 : DCR_DW16); - csr->s_rcr = RCR_BRD | RCR_LBNONE; - csr->s_imr = IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN; + NIC_PUT(sc, SNR_DCR, sc->snr_dcr); + NIC_PUT(sc, SNR_DCR2, sc->snr_dcr2); + + s_rcr = RCR_BRD | RCR_LBNONE; + if (sc->sc_if.if_flags & IFF_PROMISC) + s_rcr |= RCR_PRO; + if (sc->sc_if.if_flags & IFF_ALLMULTI) + s_rcr |= RCR_AMC; + NIC_PUT(sc, SNR_RCR, s_rcr); + + NIC_PUT(sc, SNR_IMR, (IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN)); /* clear pending interrupts */ - csr->s_isr = 0x7fff; + NIC_PUT(sc, SNR_ISR, ISR_ALL); /* clear tally counters */ - csr->s_crct = -1; - csr->s_faet = -1; - csr->s_mpt = -1; + NIC_PUT(sc, SNR_CRCT, -1); + NIC_PUT(sc, SNR_FAET, -1); + NIC_PUT(sc, SNR_MPT, -1); initialise_tda(sc); initialise_rda(sc); @@ -440,22 +456,20 @@ sninit(sc) initialise_tba(sc); /* enable the chip */ - csr->s_cr = 0; + NIC_PUT(sc, SNR_CR, 0); wbflush(); - /* program the CAM with our address */ - caminitialise(sc); - camentry(sc, 0, sc->sc_enaddr); + /* program the CAM */ camprogram(sc); /* get it to read resource descriptors */ - csr->s_cr = CR_RRRA; + NIC_PUT(sc, SNR_CR, CR_RRRA); wbflush(); - while (csr->s_cr & CR_RRRA) + while ((NIC_GET(sc, SNR_CR)) & CR_RRRA) continue; /* enable rx */ - csr->s_cr = CR_RXEN; + NIC_PUT(sc, SNR_CR, CR_RXEN); wbflush(); /* flag interface as "running" */ @@ -478,7 +492,7 @@ snstop(sc) int s = splnet(); /* stick chip in reset */ - sc->sc_csr->s_cr = CR_RST; + NIC_PUT(sc, SNR_CR, CR_RST); wbflush(); /* free all receive buffers (currently static so nothing to do) */ @@ -534,7 +548,6 @@ sonicput(sc, m0) struct sn_softc *sc; struct mbuf *m0; { - struct sonic_reg *csr = sc->sc_csr; unsigned char *buff, *buffer; void *txp; struct mtd *mtdp; @@ -545,7 +558,7 @@ sonicput(sc, m0) int mtd_next; int txb_new = sc->txb_new; - if (sc->sc_csr->s_cr & CR_TXP) { + if (NIC_GET(sc, SNR_CR) & CR_TXP) { return (0); } @@ -610,36 +623,42 @@ sonicput(sc, m0) /* make sure chip is running */ wbflush(); - csr->s_cr = CR_TXP; + NIC_PUT(sc, SNR_CR, CR_TXP); wbflush(); sc->sc_if.if_timer = 5; /* 5 seconds to watch for failing to transmit */ return (totlen); } -void sonictxint __P((struct sn_softc *)); -void sonicrxint __P((struct sn_softc *)); +static void sonictxint __P((struct sn_softc *)); +static void sonicrxint __P((struct sn_softc *)); -int sonic_read __P((struct sn_softc *, caddr_t, int)); -struct mbuf *sonic_get __P((struct sn_softc *, struct ether_header *, int)); +static int sonic_read __P((struct sn_softc *, caddr_t, int)); +static struct mbuf *sonic_get __P((struct sn_softc *, struct ether_header *, int)); /* * CAM support */ -void +static void caminitialise(sc) struct sn_softc *sc; { int i; void *p_cda = sc->p_cda; int bitmode = sc->bitmode; - - for (i = 0; i < MAXCAM; i++) - SWO(bitmode, p_cda, (CDA_CAMDESC * i + CDA_CAMEP), i); + int camoffset; + + for (i = 0; i < MAXCAM; i++) { + camoffset = i * CDA_CAMDESC; + SWO(bitmode, p_cda, (camoffset + CDA_CAMEP), i); + SWO(bitmode, p_cda, (camoffset + CDA_CAMAP2), 0); + SWO(bitmode, p_cda, (camoffset + CDA_CAMAP1), 0); + SWO(bitmode, p_cda, (camoffset + CDA_CAMAP0), 0); + } SWO(bitmode, p_cda, CDA_ENABLE, 0); } -void +static void camentry(sc, entry, ea) int entry; unsigned char *ea; @@ -647,30 +666,73 @@ camentry(sc, entry, ea) { int bitmode = sc->bitmode; void *p_cda = sc->p_cda; - int camoffset = entry * CDA_CAMDESC; + int camoffset = entry * CDA_CAMDESC; SWO(bitmode, p_cda, camoffset + CDA_CAMEP, entry); SWO(bitmode, p_cda, camoffset + CDA_CAMAP2, (ea[5] << 8) | ea[4]); SWO(bitmode, p_cda, camoffset + CDA_CAMAP1, (ea[3] << 8) | ea[2]); SWO(bitmode, p_cda, camoffset + CDA_CAMAP0, (ea[1] << 8) | ea[0]); - SWO(bitmode, p_cda, CDA_ENABLE, (1 << entry)); + SWO(bitmode, p_cda, CDA_ENABLE, + (SRO(bitmode, p_cda, CDA_ENABLE) | (1 << entry))); } -void +static void camprogram(sc) struct sn_softc *sc; { - struct sonic_reg *csr; - int timeout; + int timeout; + int mcount = 0; + struct ether_multi *enm; + struct ether_multistep step; + struct ifnet *ifp; - csr = sc->sc_csr; - csr->s_cdp = LOWER(sc->v_cda); - csr->s_cdc = MAXCAM; - csr->s_cr = CR_LCAM; + caminitialise(sc); + + ifp = &sc->sc_if; + + /* Always load our own address first. */ + camentry (sc, 0, sc->sc_enaddr); + mcount++; + + /* Assume we won't need allmulti bit. */ + ifp->if_flags &= ~IFF_ALLMULTI; + + mcount++; + /* Loop through multicast addresses */ + ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm); + while (enm != NULL) { + if (mcount == MAXCAM) { + ifp->if_flags |= IFF_ALLMULTI; + break; + } + + if (bcmp(enm->enm_addrlo, enm->enm_addrhi, + sizeof(enm->enm_addrlo)) != 0) { + /* + * SONIC's CAM is programmed with specific + * addresses. It has no way to specify a range. + * (Well, thats not exactly true. If the + * range is small one could program each addr + * within the range as a seperate CAM entry) + */ + ifp->if_flags |= IFF_ALLMULTI; + break; + } + + /* program the CAM with the specified entry */ + camentry(sc, mcount, enm->enm_addrlo); + mcount++; + + ETHER_NEXT_MULTI(step, enm); + } + + NIC_PUT(sc, SNR_CDP, LOWER(sc->v_cda)); + NIC_PUT(sc, SNR_CDC, MAXCAM); + NIC_PUT(sc, SNR_CR, CR_LCAM); wbflush(); timeout = 10000; - while (csr->s_cr & CR_LCAM && timeout--) + while ((NIC_GET(sc, SNR_CR) & CR_LCAM) && timeout--) continue; if (timeout == 0) { /* XXX */ @@ -678,54 +740,50 @@ camprogram(sc) sc->sc_dev.dv_xname); } timeout = 10000; - while ((csr->s_isr & ISR_LCD) == 0 && timeout--) + while (((NIC_GET(sc, SNR_ISR) & ISR_LCD) == 0) && timeout--) continue; - if (csr->s_isr & ISR_LCD) - csr->s_isr = ISR_LCD; + if (NIC_GET(sc, SNR_ISR) & ISR_LCD) + NIC_PUT(sc, SNR_ISR, ISR_LCD); else printf("%s: CAM initialisation without interrupt\n", sc->sc_dev.dv_xname); } #if 0 -void +static void camdump(sc) struct sn_softc *sc; { - struct sonic_reg *csr = sc->sc_csr; int i; printf("CAM entries:\n"); - csr->s_cr = CR_RST; + NIC_PUT(sc, SNR_CR, CR_RST); wbflush(); for (i = 0; i < 16; i++) { ushort ap2, ap1, ap0; - csr->s_cep = i; + NIC_PUT(sc, SNR_CEP, i); wbflush(); - ap2 = csr->s_cap2; - ap1 = csr->s_cap1; - ap0 = csr->s_cap0; + ap2 = NIC_GET(sc, SNR_CAP2); + ap1 = NIC_GET(sc, SNR_CAP1); + ap0 = NIC_GET(sc, SNR_CAP0); printf("%d: ap2=0x%x ap1=0x%x ap0=0x%x\n", i, ap2, ap1, ap0); } - printf("CAM enable 0x%lx\n", csr->s_cep); + printf("CAM enable 0x%x\n", NIC_GET(sc, SNR_CE)); - csr->s_cr = 0; + NIC_PUT(sc, SNR_CR, 0); wbflush(); } #endif -void +static void initialise_tda(sc) struct sn_softc *sc; { - struct sonic_reg *csr; struct mtd *mtd; int i; - csr = sc->sc_csr; - for (i = 0; i < NTDA; i++) { mtd = &sc->mtda[i]; mtd->mtd_buf = 0; @@ -736,20 +794,17 @@ initialise_tda(sc) sc->mtd_free = 0; sc->mtd_tlinko = TXP_FRAGOFF + 1*TXP_FRAGSIZE + TXP_FPTRLO; - csr->s_utda = UPPER(sc->mtda[0].mtd_vtxp); - csr->s_ctda = LOWER(sc->mtda[0].mtd_vtxp); + NIC_PUT(sc, SNR_UTDA, UPPER(sc->mtda[0].mtd_vtxp)); + NIC_PUT(sc, SNR_CTDA, LOWER(sc->mtda[0].mtd_vtxp)); } -void +static void initialise_rda(sc) struct sn_softc *sc; { - struct sonic_reg *csr; int bitmode = sc->bitmode; int i; - csr = sc->sc_csr; - /* link the RDA's together into a circular list */ for (i = 0; i < (NRDA - 1); i++) { SWO(bitmode, sc->p_rda[i], RXPKT_RLINK, LOWER(sc->v_rda[i+1])); @@ -763,31 +818,28 @@ initialise_rda(sc) sc->sc_rxmark = 0; - SWR(csr->s_urda, UPPER(sc->v_rda[0])); - SWR(csr->s_crda, LOWER(sc->v_rda[0])); + NIC_PUT(sc, SNR_URDA, UPPER(sc->v_rda[0])); + NIC_PUT(sc, SNR_CRDA, LOWER(sc->v_rda[0])); wbflush(); } -void +static void initialise_rra(sc) struct sn_softc *sc; { - struct sonic_reg *csr; int i; unsigned int v; int bitmode = sc->bitmode; - csr = sc->sc_csr; - - if (bitmode) - csr->s_eobc = RBASIZE(sc) / 2 - 2; /* must be >= MAXETHERPKT */ + if (bitmode) /* eobc must be >= MAXETHERPKT */ + NIC_PUT(sc, SNR_EOBC, RBASIZE(sc) / 2 - 2); else - csr->s_eobc = RBASIZE(sc) / 2 - 1; /* must be >= MAXETHERPKT */ - csr->s_urra = UPPER(sc->v_rra[0]); - csr->s_rsa = LOWER(sc->v_rra[0]); + NIC_PUT(sc, SNR_EOBC, RBASIZE(sc) / 2 - 1); + NIC_PUT(sc, SNR_URRA, UPPER(sc->v_rra[0])); + NIC_PUT(sc, SNR_RSA, LOWER(sc->v_rra[0])); /* rea must point just past the end of the rra space */ - csr->s_rea = LOWER(sc->v_rea); - csr->s_rrp = LOWER(sc->v_rra[0]); + NIC_PUT(sc, SNR_REA, LOWER(sc->v_rea)); + NIC_PUT(sc, SNR_RRP, LOWER(sc->v_rra[0])); /* fill up SOME of the rra with buffers */ for (i = 0; i < NRBA; i++) { @@ -798,11 +850,11 @@ initialise_rra(sc) SWO(bitmode, sc->p_rra[i], RXRSRC_WCLO, LOWER(RBASIZE(sc) / 2)); } sc->sc_rramark = NRBA; - csr->s_rwp = LOWER(sc->v_rra[sc->sc_rramark]); + NIC_PUT(sc, SNR_RWP, LOWER(sc->v_rra[sc->sc_rramark])); wbflush(); } -void +static void initialise_tba(sc) struct sn_softc *sc; { @@ -811,18 +863,17 @@ initialise_tba(sc) sc->txb_new = 0; } -static void +void snintr(arg, slot) void *arg; int slot; { struct sn_softc *sc = (struct sn_softc *)arg; - struct sonic_reg *csr = sc->sc_csr; int isr; - while ((isr = (csr->s_isr & ISR_ALL)) != 0) { + while ((isr = (NIC_GET(sc, SNR_ISR) & ISR_ALL)) != 0) { /* scrub the interrupts that we are going to service */ - csr->s_isr = isr; + NIC_PUT(sc, SNR_ISR, isr); wbflush(); if (isr & (ISR_BR | ISR_LCD | ISR_PINT | ISR_TC)) @@ -877,20 +928,17 @@ snintr(arg, slot) /* * Transmit interrupt routine */ -void +static void sonictxint(sc) struct sn_softc *sc; { void *txp; - struct sonic_reg *csr; struct mtd *mtd; /* XXX DG make mtd_hw a local var */ if (sc->mtd_hw == sc->mtd_free) return; - csr = sc->sc_csr; - while (sc->mtd_hw != sc->mtd_free) { mtd = &sc->mtda[sc->mtd_hw]; if (mtd->mtd_buf == 0) @@ -927,8 +975,8 @@ sonictxint(sc) if (sc->mtd_hw != sc->mtd_free) { printf("resubmitting remaining packets\n"); mtd = &sc->mtda[sc->mtd_hw]; - csr->s_ctda = LOWER(mtd->mtd_vtxp); - csr->s_cr = CR_TXP; + NIC_PUT(sc, SNR_CTDA, LOWER(mtd->mtd_vtxp)); + NIC_PUT(sc, SNR_CR, CR_TXP); wbflush(); return; } @@ -939,11 +987,10 @@ sonictxint(sc) /* * Receive interrupt routine */ -void +static void sonicrxint(sc) struct sn_softc *sc; { - struct sonic_reg *csr = sc->sc_csr; void *rda; int orra; int len; @@ -1002,7 +1049,7 @@ sonicrxint(sc) SWO(bitmode, tmp2, RXRSRC_WCLO, 0); sc->sc_rramark = (++rramark) & RRAMASK; - csr->s_rwp = LOWER(sc->v_rra[rramark]); + NIC_PUT(sc, SNR_RWP, LOWER(sc->v_rra[rramark])); wbflush(); /* @@ -1027,7 +1074,7 @@ sonicrxint(sc) * sonic_read -- pull packet off interface and forward to * appropriate protocol handler */ -int +static int sonic_read(sc, pkt, len) struct sn_softc *sc; caddr_t pkt; @@ -1039,9 +1086,6 @@ sonic_read(sc, pkt, len) /* * Get pointer to ethernet header (in input buffer). - * Deal with trailer protocol: if type is PUP trailer - * get true type from first 16-bit word past data. - * Remember that type was trailer by setting off. */ et = (struct ether_header *)pkt; @@ -1087,7 +1131,7 @@ sonic_read(sc, pkt, len) * because we are using stupid buffer management this * is slow. */ -struct mbuf * +static struct mbuf * sonic_get(sc, eh, datalen) struct sn_softc *sc; struct ether_header *eh; diff --git a/sys/arch/mac68k/dev/if_sn_nubus.c b/sys/arch/mac68k/dev/if_sn_nubus.c index 745309a3b25..977d14ce759 100644 --- a/sys/arch/mac68k/dev/if_sn_nubus.c +++ b/sys/arch/mac68k/dev/if_sn_nubus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_sn_nubus.c,v 1.3 1997/03/17 04:16:59 briggs Exp $ */ +/* $OpenBSD: if_sn_nubus.c,v 1.4 1997/03/29 23:26:49 briggs Exp $ */ /* * Copyright (C) 1997 Allen Briggs @@ -124,8 +124,9 @@ sn_nubus_attach(parent, self, aux) switch (sn_nb_card_vendor(na)) { case AE_VENDOR_DAYNA: - sc->s_dcr = DCR_ASYNC | DCR_WAIT0 | DCR_USR1 | - DCR_DW32 | DCR_DMABLOCK | DCR_RFT16 | DCR_TFT16; + sc->snr_dcr = DCR_ASYNC | DCR_WAIT0 | DCR_DW32 | + DCR_DMABLOCK | DCR_RFT16 | DCR_TFT16; + sc->snr_dcr2 = 0; if (bus_space_subregion(bst, bsh, 0x00180000, SN_REGSIZE, &sc->sc_regh)) { @@ -141,6 +142,11 @@ sn_nubus_attach(parent, self, aux) /* * Copy out the ethernet address from the card's ROM + * + * See if_sn_obio.c for a discussion of bit reversal + * in Apple's MAC address PROMs. As far as I can tell + * Dayna stores their Mac address in ethernet format, + * not Token Ring. */ for (i = 0; i < ETHER_ADDR_LEN; ++i) sc->sc_arpcom.ac_enaddr[i] = @@ -156,8 +162,9 @@ sn_nubus_attach(parent, self, aux) * for a new card, the following defaults are a * good starting point. */ - sc->s_dcr = DCR_LBR | DCR_SYNC | DCR_WAIT0 | - DCR_DW32 | DCR_DMABLOCK | DCR_RFT16 | DCR_TFT16; + sc->snr_dcr = DCR_SYNC | DCR_WAIT0 | DCR_DW32 | + DCR_DMABLOCK | DCR_RFT16 | DCR_TFT16; + sc->snr_dcr2 = 0; return; } @@ -167,6 +174,20 @@ sn_nubus_attach(parent, self, aux) } snsetup(sc); + /* Regs are addressed as words, big endian. */ + for (i = 0; i < SN_NREGS; i++) { + sc->sc_reg_map[i] = (bus_size_t)((i * 4) + 2); + } + + /* snsetup returns 1 if something fails */ + if (snsetup(sc)) { + bus_space_unmap(bst, bsh, NBMEMSIZE); + return; + } + + add_nubus_intr(sc->slotno, snintr, (void *)sc); + + return; } static int @@ -205,6 +226,9 @@ sn_nb_card_vendor(na) break; } break; + case NUBUS_DRSW_DAYNA: + vendor = AE_VENDOR_DAYNA; + break; default: #ifdef DIAGNOSTIC printf("Unknown ethernet drsw: %x\n", na->drsw); diff --git a/sys/arch/mac68k/dev/if_sn_obio.c b/sys/arch/mac68k/dev/if_sn_obio.c index 358c53415bf..831209f4868 100644 --- a/sys/arch/mac68k/dev/if_sn_obio.c +++ b/sys/arch/mac68k/dev/if_sn_obio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_sn_obio.c,v 1.4 1997/03/29 02:27:11 briggs Exp $ */ +/* $OpenBSD: if_sn_obio.c,v 1.5 1997/03/29 23:26:49 briggs Exp $ */ /* * Copyright (C) 1997 Allen Briggs @@ -84,25 +84,33 @@ sn_obio_attach(parent, self, aux) { struct obio_attach_args *oa = (struct obio_attach_args *) aux; struct sn_softc *sc = (void *)self; + int i; - sc->s_dcr = DCR_LBR | DCR_SYNC | DCR_WAIT0 | - DCR_DMABLOCK | DCR_RFT16 | DCR_TFT16; + sc->snr_dcr = DCR_SYNC | DCR_WAIT0 | DCR_DMABLOCK | + DCR_RFT16 | DCR_TFT16; + sc->snr_dcr2 = 0; - switch (current_mac_model->class) { - case MACH_CLASSQ: - case MACH_CLASSQ2: - sc->s_dcr |= DCR_DW32; + switch (current_mac_model->machineid) { + case MACH_MACQ700: /* only tested on Q700 */ + case MACH_MACQ900: + case MACH_MACQ950: + sc->snr_dcr |= DCR_LBR | DCR_DW32; sc->bitmode = 1; - break; - - case MACH_CLASSPB: - sc->s_dcr |= DCR_DW16; - sc->bitmode = 0; - break; + break; + + case MACH_MACQ800: + case MACH_MACQ650: + case MACH_MACC650: + case MACH_MACC610: + case MACH_MACQ610: + sc->snr_dcr |= DCR_EXBUS | DCR_DW32; + sc->bitmode = 1; + break; - default: - printf("unsupported machine type\n"); - return; + case MACH_MACPB500: + sc->snr_dcr |= DCR_LBR | DCR_DW16; + sc->bitmode = 0; + break; } sc->sc_regt = oa->oa_tag; @@ -115,7 +123,18 @@ sn_obio_attach(parent, self, aux) sn_obio_getaddr(sc); - snsetup(sc); + /* regs are addressed as words, big-endian. */ + for (i = 0; i < SN_NREGS; i++) { + sc->sc_reg_map[i] = (bus_size_t)((i * 4) + 2); + } + + /* snsetup returns 1 if something fails */ + if (snsetup(sc)) { + bus_space_unmap(sc->sc_regt, sc->sc_regh, SN_REGSIZE); + return; + } + + add_nubus_intr(sc->slotno, snintr, (void *)sc); } static u_char bbr4[] = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15}; @@ -134,9 +153,34 @@ sn_obio_getaddr(sc) } /* - * Apparently Apple goofed here. The ethernet MAC address is - * stored in bit-byte-reversed format. It is rumored that this - * is only true for some systems. + * For reasons known only to Apple, MAC addresses in the ethernet + * PROM are stored in Token Ring (IEEE 802.5) format, that is + * with all of the bits in each byte reversed (canonical bit format). + * When the address is read out it must be reversed to ethernet format + * before use. + * + * Apple has been assigned OUI's 00:08:07 and 00:a0:40. All onboard + * ethernet addresses on 68K machines should be in one of these + * two ranges. + * + * Here is where it gets complicated. + * + * The PMac 7200, 7500, 8500, and 9500 accidentally had the PROM + * written in standard ethernet format. The MacOS accounted for this + * in these systems, and did not reverse the bytes. Some other + * networking utilities were not so forgiving, and got confused. + * "Some" of Apple's Nubus ethernet cards also had their bits + * burned in ethernet format. + * + * Apple petitioned the IEEE and was granted the 00:05:02 (bit reversal + * of 00:a0:40) as well. As of OpenTransport 1.1.1, Apple removed + * their workaround and now reverses the bits regardless of + * what kind of machine it is. So PMac systems and the affected + * Nubus cards now use 00:05:02, instead of the 00:a0:40 for which they + * were intended. + * + * See Apple Techinfo article TECHINFO-0020552, "OpenTransport 1.1.1 + * and MacOS System 7.5.3 FAQ (10/96)" for more details. */ do_bbr = 0; b = bus_space_read_1(sc->sc_regt, bsh, 0); diff --git a/sys/arch/mac68k/dev/if_snreg.h b/sys/arch/mac68k/dev/if_snreg.h index 3f480d08dfe..8fd0a819e02 100644 --- a/sys/arch/mac68k/dev/if_snreg.h +++ b/sys/arch/mac68k/dev/if_snreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_snreg.h,v 1.1 1997/03/12 13:20:33 briggs Exp $ */ +/* $OpenBSD: if_snreg.h,v 1.2 1997/03/29 23:26:50 briggs Exp $ */ /* * Copyright (c) 1991 Algorithmics Ltd (http://www.algor.co.uk) @@ -13,74 +13,72 @@ /* * SONIC registers as seen by the processor */ -struct sonic_reg { - volatile u_long s_cr; /* 00: Command */ - volatile u_long s_dcr; /* 01: Data Configuration */ - volatile u_long s_rcr; /* 02: Receive Control */ - volatile u_long s_tcr; /* 03: Transmit Control */ - volatile u_long s_imr; /* 04: Interrupt Mask */ - volatile u_long s_isr; /* 05: Interrupt Status */ - volatile u_long s_utda; /* 06: Upper Transmit Descriptor Address */ - volatile u_long s_ctda; /* 07: Current Transmit Descriptor Address */ - volatile u_long _s_tps; /* 08* Transmit Packet Size */ - volatile u_long _s_tfc; /* 09* Transmit Fragment Count */ - volatile u_long _s_tsa0; /* 0a* Transmit Start Address 0 */ - volatile u_long _s_tsa1; /* 0b* Transmit Start Address 1 */ - volatile u_long _s_tfs; /* 0c* Transmit Fragment Size */ - volatile u_long s_urda; /* 0d: Upper Receive Descriptor Address */ - volatile u_long s_crda; /* 0e: Current Receive Descriptor Address */ - volatile u_long _s_crba0; /* 0f* Current Receive Buffer Address 0 */ - volatile u_long _s_crba1; /* 10* Current Receive Buffer Address 1 */ - volatile u_long _s_rbwc0; /* 11* Remaining Buffer Word Count 0 */ - volatile u_long _s_rbwc1; /* 12* Remaining Buffer Word Count 1 */ - volatile u_long s_eobc; /* 13: End Of Buffer Word Count */ - volatile u_long s_urra; /* 14: Upper Receive Resource Address */ - volatile u_long s_rsa; /* 15: Resource Start Address */ - volatile u_long s_rea; /* 16: Resource End Address */ - volatile u_long s_rrp; /* 17: Resource Read Pointer */ - volatile u_long s_rwp; /* 18: Resource Write Pointer */ - volatile u_long _s_trba0; /* 19* Temporary Receive Buffer Address 0 */ - volatile u_long _s_trba1; /* 1a* Temporary Receive Buffer Address 1 */ - volatile u_long _s_tbwc0; /* 1b* Temporary Buffer Word Count 0 */ - volatile u_long _s_tbwc1; /* 1c* Temporary Buffer Word Count 1 */ - volatile u_long _s_addr0; /* 1d* Address Generator 0 */ - volatile u_long _s_addr1; /* 1e* Address Generator 1 */ - volatile u_long _s_llfa; /* 1f* Last Link Field Address */ - volatile u_long _s_ttda; /* 20* Temp Transmit Descriptor Address */ - volatile u_long s_cep; /* 21: CAM Entry Pointer */ - volatile u_long s_cap2; /* 22: CAM Address Port 2 */ - volatile u_long s_cap1; /* 23: CAM Address Port 1 */ - volatile u_long s_cap0; /* 24: CAM Address Port 0 */ - volatile u_long s_ce; /* 25: CAM Enable */ - volatile u_long s_cdp; /* 26: CAM Descriptor Pointer */ - volatile u_long s_cdc; /* 27: CAM Descriptor Count */ - volatile u_long s_sr; /* 28: Silicon Revision */ - volatile u_long s_wt0; /* 29: Watchdog Timer 0 */ - volatile u_long s_wt1; /* 2a: Watchdog Timer 1 */ - volatile u_long s_rsc; /* 2b: Receive Sequence Counter */ - volatile u_long s_crct; /* 2c: CRC Error Tally */ - volatile u_long s_faet; /* 2d: FAE Tally */ - volatile u_long s_mpt; /* 2e: Missed Packet Tally */ - volatile u_long _s_mdt; /* 2f* Maximum Deferral Timer */ - volatile u_long _s_rtc; /* 30* Receive Test Control */ - volatile u_long _s_ttc; /* 31* Transmit Test Control */ - volatile u_long _s_dtc; /* 32* DMA Test Control */ - volatile u_long _s_cc0; /* 33* CAM Comparison 0 */ - volatile u_long _s_cc1; /* 34* CAM Comparison 1 */ - volatile u_long _s_cc2; /* 35* CAM Comparison 2 */ - volatile u_long _s_cm; /* 36* CAM Match */ - volatile u_long :32; /* 37* reserved */ - volatile u_long :32; /* 38* reserved */ - volatile u_long _s_rbc; /* 39* Receiver Byte Count */ - volatile u_long :32; /* 3a* reserved */ - volatile u_long _s_tbo; /* 3b* Transmitter Backoff Counter */ - volatile u_long _s_trc; /* 3c* Transmitter Random Counter */ - volatile u_long _s_tbm; /* 3d* Transmitter Backoff Mask */ - volatile u_long :32; /* 3e* Reserved */ - volatile u_long s_dcr2; /* 3f Data Configuration 2 (AVF) */ -}; +#define SNR_CR 0x00 /* Command */ +#define SNR_DCR 0x01 /* Data Configuration */ +#define SNR_RCR 0x02 /* Receive Control */ +#define SNR_TCR 0x03 /* Transmit Control */ +#define SNR_IMR 0x04 /* Interrupt Mask */ +#define SNR_ISR 0x05 /* Interrupt Status */ +#define SNR_UTDA 0x06 /* Upper Transmit Descriptor Address */ +#define SNR_CTDA 0x07 /* Current Transmit Descriptor Address */ +#define SNR_TPS 0x08 /* Transmit Packet Size */ +#define SNR_TFC 0x09 /* Transmit Fragment Count */ +#define SNR_TSA0 0x0a /* Transmit Start Address 0 */ +#define SNR_TSA1 0x0b /* Transmit Start Address 1 */ +#define SNR_TFS 0x0c /* Transmit Fragment Size */ +#define SNR_URDA 0x0d /* Upper Receive Descriptor Address */ +#define SNR_CRDA 0x0e /* Current Receive Descriptor Address */ +#define SNR_CRBA0 0x0f /* Current Receive Buffer Address 0 */ +#define SNR_CRBA1 0x10 /* Current Receive Buffer Address 1 */ +#define SNR_RBWC0 0x11 /* Remaining Buffer Word Count 0 */ +#define SNR_RBWC1 0x12 /* Remaining Buffer Word Count 1 */ +#define SNR_EOBC 0x13 /* End Of Buffer Word Count */ +#define SNR_URRA 0x14 /* Upper Receive Resource Address */ +#define SNR_RSA 0x15 /* Resource Start Address */ +#define SNR_REA 0x16 /* Resource End Address */ +#define SNR_RRP 0x17 /* Resource Read Pointer */ +#define SNR_RWP 0x18 /* Resource Write Pointer */ +#define SNR_TRBA0 0x19 /* Temporary Receive Buffer Address 0 */ +#define SNR_TRBA1 0x1a /* Temporary Receive Buffer Address 1 */ +#define SNR_TBWC0 0x1b /* Temporary Buffer Word Count 0 */ +#define SNR_TBWC1 0x1c /* Temporary Buffer Word Count 1 */ +#define SNR_ADDR0 0x1d /* Address Generator 0 */ +#define SNR_ADDR1 0x1e /* Address Generator 1 */ +#define SNR_LLFA 0x1f /* Last Link Field Address */ +#define SNR_TTDA 0x20 /* Temp Transmit Descriptor Address */ +#define SNR_CEP 0x21 /* CAM Entry Pointer */ +#define SNR_CAP2 0x22 /* CAM Address Port 2 */ +#define SNR_CAP1 0x23 /* CAM Address Port 1 */ +#define SNR_CAP0 0x24 /* CAM Address Port 0 */ +#define SNR_CE 0x25 /* CAM Enable */ +#define SNR_CDP 0x26 /* CAM Descriptor Pointer */ +#define SNR_CDC 0x27 /* CAM Descriptor Count */ +#define SNR_SR 0x28 /* Silicon Revision */ +#define SNR_WT0 0x29 /* Watchdog Timer 0 */ +#define SNR_WT1 0x2a /* Watchdog Timer 1 */ +#define SNR_RSC 0x2b /* Receive Sequence Counter */ +#define SNR_CRCT 0x2c /* CRC Error Tally */ +#define SNR_FAET 0x2d /* FAE Tally */ +#define SNR_MPT 0x2e /* Missed Packet Tally */ +#define SNR_MDT 0x2f /* Maximum Deferral Timer */ +#define SNR_RTC 0x30 /* Receive Test Control */ +#define SNR_TTC 0x31 /* Transmit Test Control */ +#define SNR_DTC 0x32 /* DMA Test Control */ +#define SNR_CC0 0x33 /* CAM Comparison 0 */ +#define SNR_CC1 0x34 /* CAM Comparison 1 */ +#define SNR_CC2 0x35 /* CAM Comparison 2 */ +#define SNR_CM 0x36 /* CAM Match */ +#define SNR_RES1 0x37 /* reserved */ +#define SNR_RES2 0x38 /* reserved */ +#define SNR_RBC 0x39 /* Receiver Byte Count */ +#define SNR_RES3 0x3a /* reserved */ +#define SNR_TBO 0x3b /* Transmitter Backoff Counter */ +#define SNR_TRC 0x3c /* Transmitter Random Counter */ +#define SNR_TBM 0x3d /* Transmitter Backoff Mask */ +#define SNR_RES4 0x3e /* Reserved */ +#define SNR_DCR2 0x3f /* Data Configuration 2 (AVF) */ -#define SN_REGSIZE (0x40 * 4) +#define SN_NREGS 0x40 /* * Register Interpretations diff --git a/sys/arch/mac68k/dev/if_snvar.h b/sys/arch/mac68k/dev/if_snvar.h index e89d0f50966..fa6c3aecc1d 100644 --- a/sys/arch/mac68k/dev/if_snvar.h +++ b/sys/arch/mac68k/dev/if_snvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_snvar.h,v 1.2 1997/03/14 14:11:36 briggs Exp $ */ +/* $OpenBSD: if_snvar.h,v 1.3 1997/03/29 23:26:50 briggs Exp $ */ /* * Copyright (c) 1991 Algorithmics Ltd (http://www.algor.co.uk) @@ -7,7 +7,7 @@ */ /* - * if_sonic.h -- National Semiconductor DP83932BVF (SONIC) + * if_snvar.h -- National Semiconductor DP83932BVF (SONIC) NetBSD/mac68k vars */ /* @@ -21,6 +21,23 @@ #define SRO(m, a, o) (m ? (*(u_int32_t *)((u_int32_t *)a + o) & 0xffff) : \ (*(u_int16_t *)((u_int16_t *)a + o) & 0xffff)) +/* + * Register access macros. We use bus_space_* to talk to the Sonic + * registers. A mapping table is used in case a particular configuration + * hooked the regs up at non-word offsets. + */ +#define NIC_GET(sc, reg) (bus_space_read_2((sc)->sc_regt, \ + (sc)->sc_regh, \ + ((sc)->sc_reg_map[reg]))) +#define NIC_PUT(sc, reg, val) (bus_space_write_2((sc)->sc_regt, \ + (sc)->sc_regh, \ + ((sc)->sc_reg_map[reg]), \ + (val))) +#define SN_REGSIZE SN_NREGS*4 + +/* mac68k does not have any write buffers to flush... */ +#define wbflush() + /* * buffer sizes in 32 bit mode * 1 TXpkt is 4 hdr words + (3 * FRAGMAX) + 1 link word @@ -52,6 +69,8 @@ #define NTXB 10 /* Number of xmit buffers */ #define TXBSIZE 1536 /* 6*2^8 -- the same size as the 8390 TXBUF */ +#define SN_NPAGES 1 + 8 + 5 + /* * Statistics collected over time */ @@ -102,12 +121,13 @@ typedef struct sn_softc { struct sn_stats sc_sum; short sc_iflags; unsigned short bitmode; /* 32 bit mode == 1, 16 == 0 */ + bus_size_t sc_reg_map[SN_NREGS]; /* register offsets */ - unsigned int s_dcr; /* DCR for this instance */ + u_int16_t snr_dcr; /* DCR for this instance */ + u_int16_t snr_dcr2; /* DCR2 for this instance */ int slotno; /* Slot number */ - struct sonic_reg *sc_csr; /* hardware pointer */ - int sc_rxmark; /* pos. in rx ring for reading buffs */ + int sc_rxmark; /* pos. in rx ring for reading buffs */ int sc_rramark; /* index into p_rra of wp */ void *p_rra[NRRA]; /* RX resource descs */ int v_rra[NRRA]; /* DMA addresses of p_rra */ @@ -119,7 +139,6 @@ typedef struct sn_softc { caddr_t rbuf[NRBA]; - int sc_txhead; /*XXX idx of first TDA passed to chip */ int sc_missed; /* missed packet counter */ int txb_cnt; /* total number of xmit buffers */ @@ -142,7 +161,7 @@ typedef struct sn_softc { void *p_cda; int v_cda; - unsigned char space[(1 + 1 + 8 + 5) * NBPG]; + unsigned char *space; } sn_softc_t; /* @@ -217,4 +236,5 @@ typedef struct sn_softc { #define CDA_ENABLE 64 /* mask enabling CAM entries */ #define CDA_SIZE(sc) ((4*16 + 1) * ((sc->bitmode) ? 4 : 2)) -void snsetup __P((struct sn_softc *sc)); +int snsetup __P((struct sn_softc *sc)); +void snintr __P((void *, int)); -- 2.20.1