From 9ba2b298dfda78b6669281507b314a4c441cd706 Mon Sep 17 00:00:00 2001 From: Marius Strobl Date: Tue, 23 Jun 2009 20:36:59 +0000 Subject: [PATCH] - Initialize the ifnet structure, especially if_dname, before probing the PHYs as some PHY drivers use it (but probably shouldn't). How gem(4) has worked with brgphy(4) on powerpc without this so far is unclear to me. - Introduce a dying flag which is set during detach and checked in gem_ioctl() in order to prevent active BPF listeners to clear promiscuous mode which may lead to the tick callout being restarted which will trigger a panic once it's actually gone. - In gem_stop() reset rather than just disable the transmitter and receiver in order to ensure we're not unloading DMA maps still in use by the hardware. [1] - The blanking time is specified in PCI clocks so we should use twice the value when operating at 66MHz. - Spell some 2 as ETHER_ALIGN and a 19 as GEM_STATUS_TX_COMPLETION_SHFT to make the actual intentions clear. - As we don't unload the peak attempts counter ignore its overflow interrupts. - Remove a stale setting of a variable to GEM_TD_INTERRUPT_ME which isn't used afterwards. - For optimum performance increment the TX kick register in multiples of 4 if possible as suggested by the documentation. - Partially revert r164931; drivers should only clear the watchdog timer if all outstanding TX descriptors are done. - Fix some debugging strings. - Add a missing BUS_DMASYNC_POSTWRITE in gem_rint(). - As the error paths in the interrupt handler are generally unlikely predict them as false. - Add support for the SBus version of the GEM controller. [2] - Add some lock assertions. - Improve some comments. - Fix some more or less cosmetic issues in the code of the PCI front-end. - Change some softc members to be unsigned where more appropriate and remove unused ones. Approved by: re (kib) Obtained from: NetBSD (partially) [2], OpenBSD [1] MFC after: 2 weeks --- sys/conf/files | 1 + sys/dev/gem/if_gem.c | 237 +++++++++++++++---------- sys/dev/gem/if_gem_pci.c | 46 ++--- sys/dev/gem/if_gem_sbus.c | 210 ++++++++++++++++++++++ sys/dev/gem/if_gemreg.h | 362 ++++++++++++++++++-------------------- sys/dev/gem/if_gemvar.h | 50 +++--- sys/modules/gem/Makefile | 6 +- 7 files changed, 585 insertions(+), 327 deletions(-) create mode 100644 sys/dev/gem/if_gem_sbus.c diff --git a/sys/conf/files b/sys/conf/files index beb66bb4e4fd..3974b7285e85 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -923,6 +923,7 @@ dev/flash/at45d.c optional at45d dev/fxp/if_fxp.c optional fxp inet dev/gem/if_gem.c optional gem dev/gem/if_gem_pci.c optional gem pci +dev/gem/if_gem_sbus.c optional gem sbus dev/hatm/if_hatm.c optional hatm pci dev/hatm/if_hatm_intr.c optional hatm pci dev/hatm/if_hatm_ioctl.c optional hatm pci diff --git a/sys/dev/gem/if_gem.c b/sys/dev/gem/if_gem.c index da8c1e73bffb..6361519e217a 100644 --- a/sys/dev/gem/if_gem.c +++ b/sys/dev/gem/if_gem.c @@ -84,7 +84,7 @@ __FBSDID("$FreeBSD$"); CTASSERT(powerof2(GEM_NRXDESC) && GEM_NRXDESC >= 32 && GEM_NRXDESC <= 8192); CTASSERT(powerof2(GEM_NTXDESC) && GEM_NTXDESC >= 32 && GEM_NTXDESC <= 8192); -#define TRIES 10000 +#define GEM_TRIES 10000 /* * The hardware supports basic TCP/UDP checksum offloading. However, @@ -119,7 +119,7 @@ static void gem_rint(struct gem_softc *sc); #ifdef GEM_RINT_TIMEOUT static void gem_rint_timeout(void *arg); #endif -static __inline void gem_rxcksum(struct mbuf *m, uint64_t flags); +static inline void gem_rxcksum(struct mbuf *m, uint64_t flags); static void gem_rxdrain(struct gem_softc *sc); static void gem_setladrf(struct gem_softc *sc); static void gem_start(struct ifnet *ifp); @@ -127,6 +127,7 @@ static void gem_start_locked(struct ifnet *ifp); static void gem_stop(struct ifnet *ifp, int disable); static void gem_tick(void *arg); static void gem_tint(struct gem_softc *sc); +static inline void gem_txkick(struct gem_softc *sc); static int gem_watchdog(struct gem_softc *sc); devclass_t gem_devclass; @@ -151,9 +152,24 @@ gem_attach(struct gem_softc *sc) int error, i; uint32_t v; + if (bootverbose) + device_printf(sc->sc_dev, "flags=0x%x\n", sc->sc_flags); + + /* Set up ifnet structure. */ ifp = sc->sc_ifp = if_alloc(IFT_ETHER); if (ifp == NULL) return (ENOSPC); + sc->sc_csum_features = GEM_CSUM_FEATURES; + ifp->if_softc = sc; + if_initname(ifp, device_get_name(sc->sc_dev), + device_get_unit(sc->sc_dev)); + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_start = gem_start; + ifp->if_ioctl = gem_ioctl; + ifp->if_init = gem_init; + IFQ_SET_MAXLEN(&ifp->if_snd, GEM_TXQUEUELEN); + ifp->if_snd.ifq_drv_maxlen = GEM_TXQUEUELEN; + IFQ_SET_READY(&ifp->if_snd); callout_init_mtx(&sc->sc_tick_ch, &sc->sc_mtx, 0); #ifdef GEM_RINT_TIMEOUT @@ -161,27 +177,26 @@ gem_attach(struct gem_softc *sc) #endif /* Make sure the chip is stopped. */ - ifp->if_softc = sc; gem_reset(sc); error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, 0, NULL, NULL, &sc->sc_pdmatag); - if (error) + if (error != 0) goto fail_ifnet; error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 1, MCLBYTES, BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_rdmatag); - if (error) + if (error != 0) goto fail_ptag; error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES * GEM_NTXSEGS, GEM_NTXSEGS, MCLBYTES, BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_tdmatag); - if (error) + if (error != 0) goto fail_rtag; error = bus_dma_tag_create(sc->sc_pdmatag, PAGE_SIZE, 0, @@ -189,7 +204,7 @@ gem_attach(struct gem_softc *sc) sizeof(struct gem_control_data), 1, sizeof(struct gem_control_data), 0, NULL, NULL, &sc->sc_cdmatag); - if (error) + if (error != 0) goto fail_ttag; /* @@ -199,7 +214,7 @@ gem_attach(struct gem_softc *sc) if ((error = bus_dmamem_alloc(sc->sc_cdmatag, (void **)&sc->sc_control_data, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, - &sc->sc_cddmamap))) { + &sc->sc_cddmamap)) != 0) { device_printf(sc->sc_dev, "unable to allocate control data, error = %d\n", error); goto fail_ctag; @@ -338,19 +353,6 @@ gem_attach(struct gem_softc *sc) device_printf(sc->sc_dev, "%ukB RX FIFO, %ukB TX FIFO\n", sc->sc_rxfifosize / 1024, v / 16); - sc->sc_csum_features = GEM_CSUM_FEATURES; - /* Initialize ifnet structure. */ - ifp->if_softc = sc; - if_initname(ifp, device_get_name(sc->sc_dev), - device_get_unit(sc->sc_dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_start = gem_start; - ifp->if_ioctl = gem_ioctl; - ifp->if_init = gem_init; - IFQ_SET_MAXLEN(&ifp->if_snd, GEM_TXQUEUELEN); - ifp->if_snd.ifq_drv_maxlen = GEM_TXQUEUELEN; - IFQ_SET_READY(&ifp->if_snd); - /* Attach the interface. */ ether_ifattach(ifp, sc->sc_enaddr); @@ -402,6 +404,7 @@ gem_detach(struct gem_softc *sc) int i; GEM_LOCK(sc); + sc->sc_flags |= GEM_DYING; gem_stop(ifp, 1); GEM_UNLOCK(sc); callout_drain(&sc->sc_tick_ch); @@ -456,7 +459,7 @@ gem_resume(struct gem_softc *sc) GEM_UNLOCK(sc); } -static __inline void +static inline void gem_rxcksum(struct mbuf *m, uint64_t flags) { struct ether_header *eh; @@ -535,12 +538,11 @@ static void gem_tick(void *arg) { struct gem_softc *sc = arg; - struct ifnet *ifp; + struct ifnet *ifp = sc->sc_ifp; uint32_t v; GEM_LOCK_ASSERT(sc, MA_OWNED); - ifp = sc->sc_ifp; /* * Unload collision and error counters. */ @@ -584,7 +586,7 @@ gem_bitwait(struct gem_softc *sc, u_int bank, bus_addr_t r, uint32_t clr, int i; uint32_t reg; - for (i = TRIES; i--; DELAY(100)) { + for (i = GEM_TRIES; i--; DELAY(100)) { reg = GEM_BANKN_READ_M(bank, 4, sc, r); if ((reg & clr) == 0 && (reg & set) == set) return (1); @@ -593,8 +595,7 @@ gem_bitwait(struct gem_softc *sc, u_int bank, bus_addr_t r, uint32_t clr, } static void -gem_reset(sc) - struct gem_softc *sc; +gem_reset(struct gem_softc *sc) { #ifdef GEM_DEBUG @@ -644,9 +645,8 @@ gem_stop(struct ifnet *ifp, int disable) callout_stop(&sc->sc_rx_ch); #endif - /* XXX should we reset these instead? */ - gem_disable_tx(sc); - gem_disable_rx(sc); + gem_reset_tx(sc); + gem_reset_rx(sc); /* * Release any queued transmit buffers. @@ -721,7 +721,7 @@ gem_reset_rxdma(struct gem_softc *sc) if (sc->sc_rxsoft[i].rxs_mbuf != NULL) GEM_UPDATE_RXDESC(sc, i); sc->sc_rxptr = 0; - GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); /* NOTE: we use only 32-bit DMA addresses here. */ GEM_BANK1_WRITE_4(sc, GEM_RX_RING_PTR_HI, 0); @@ -732,9 +732,11 @@ gem_reset_rxdma(struct gem_softc *sc) ((ETHER_HDR_LEN + sizeof(struct ip)) << GEM_RX_CONFIG_CXM_START_SHFT) | (GEM_THRSH_1024 << GEM_RX_CONFIG_FIFO_THRS_SHIFT) | - (2 << GEM_RX_CONFIG_FBOFF_SHFT)); + (ETHER_ALIGN << GEM_RX_CONFIG_FBOFF_SHFT)); + /* Adjust for the SBus clock probably isn't worth the fuzz. */ GEM_BANK1_WRITE_4(sc, GEM_RX_BLANKING, - (6 << GEM_RX_BLANKING_TIME_SHIFT) | 6); + ((6 * (sc->sc_flags & GEM_PCI66) != 0 ? 2 : 1) << + GEM_RX_BLANKING_TIME_SHIFT) | 6); GEM_BANK1_WRITE_4(sc, GEM_RX_PAUSE_THRESH, (3 * sc->sc_rxfifosize / 256) | ((sc->sc_rxfifosize / 256) << 12)); @@ -798,12 +800,13 @@ gem_disable_tx(struct gem_softc *sc) } static int -gem_meminit(sc) - struct gem_softc *sc; +gem_meminit(struct gem_softc *sc) { struct gem_rxsoft *rxs; int error, i; + GEM_LOCK_ASSERT(sc, MA_OWNED); + /* * Initialize the transmit descriptor ring. */ @@ -837,7 +840,8 @@ gem_meminit(sc) GEM_INIT_RXDESC(sc, i); } sc->sc_rxptr = 0; - GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + + GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); return (0); } @@ -938,6 +942,20 @@ gem_init_locked(struct gem_softc *sc) #endif /* step 8. Global Configuration & Interrupt Mask */ + + /* + * Set the internal arbitration to "infinite" bursts of the + * maximum length of 31 * 64 bytes so DMA transfers aren't + * split up in cache line size chunks. This greatly improves + * RX performance. + * Enable silicon bug workarounds for the Apple variants. + */ + GEM_BANK1_WRITE_4(sc, GEM_CONFIG, + GEM_CONFIG_TXDMA_LIMIT | GEM_CONFIG_RXDMA_LIMIT | + ((sc->sc_flags & GEM_PCI) != 0 ? GEM_CONFIG_BURST_INF : + GEM_CONFIG_BURST_64) | (GEM_IS_APPLE(sc) ? + GEM_CONFIG_RONPAULBIT | GEM_CONFIG_BUG2FIX : 0)); + GEM_BANK1_WRITE_4(sc, GEM_INTMASK, ~(GEM_INTR_TX_INTME | GEM_INTR_TX_EMPTY | GEM_INTR_RX_DONE | GEM_INTR_RX_NOBUF | GEM_INTR_RX_TAG_ERR | GEM_INTR_PERR | @@ -949,7 +967,8 @@ gem_init_locked(struct gem_softc *sc) GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_MASK, GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT); GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_MASK, - GEM_MAC_TX_XMIT_DONE | GEM_MAC_TX_DEFER_EXP); + GEM_MAC_TX_XMIT_DONE | GEM_MAC_TX_DEFER_EXP | + GEM_MAC_TX_PEAK_EXP); #ifdef GEM_DEBUG GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_MASK, ~(GEM_MAC_PAUSED | GEM_MAC_PAUSE | GEM_MAC_RESUME)); @@ -961,7 +980,8 @@ gem_init_locked(struct gem_softc *sc) /* step 9. ETX Configuration: use mostly default values. */ /* Enable DMA. */ - v = gem_ringsize(GEM_NTXDESC /* XXX */); + v = gem_ringsize(GEM_NTXDESC); + /* Set TX FIFO threshold and enable DMA. */ v |= ((sc->sc_variant == GEM_SUN_ERI ? 0x100 : 0x4ff) << 10) & GEM_TX_CONFIG_TXFIFO_TH; GEM_BANK1_WRITE_4(sc, GEM_TX_CONFIG, v | GEM_TX_CONFIG_TXDMA_EN); @@ -973,14 +993,16 @@ gem_init_locked(struct gem_softc *sc) /* RX TCP/UDP checksum offset */ v |= ((ETHER_HDR_LEN + sizeof(struct ip)) << GEM_RX_CONFIG_CXM_START_SHFT); - - /* Enable DMA. */ + /* Set RX FIFO threshold, set first byte offset and enable DMA. */ GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, v | (GEM_THRSH_1024 << GEM_RX_CONFIG_FIFO_THRS_SHIFT) | - (2 << GEM_RX_CONFIG_FBOFF_SHFT) | GEM_RX_CONFIG_RXDMA_EN); + (ETHER_ALIGN << GEM_RX_CONFIG_FBOFF_SHFT) | + GEM_RX_CONFIG_RXDMA_EN); + /* Adjust for the SBus clock probably isn't worth the fuzz. */ GEM_BANK1_WRITE_4(sc, GEM_RX_BLANKING, - (6 << GEM_RX_BLANKING_TIME_SHIFT) | 6); + ((6 * (sc->sc_flags & GEM_PCI66) != 0 ? 2 : 1) << + GEM_RX_BLANKING_TIME_SHIFT) | 6); /* * The following value is for an OFF Threshold of about 3/4 full @@ -1002,7 +1024,7 @@ gem_init_locked(struct gem_softc *sc) device_printf(sc->sc_dev, "cannot configure RX MAC\n"); GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v); - /* step 13. TX_MAC Configuration Register */ + /* step 13. TX_MAC Configuration Register */ v = GEM_BANK1_READ_4(sc, GEM_MAC_TX_CONFIG); v |= GEM_MAC_TX_ENABLE; GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, 0); @@ -1037,6 +1059,8 @@ gem_load_txmbuf(struct gem_softc *sc, struct mbuf **m_head) uint64_t cflags, flags; int error, nexttx, nsegs, offset, seg; + GEM_LOCK_ASSERT(sc, MA_OWNED); + /* Get a work queue entry. */ if ((txs = STAILQ_FIRST(&sc->sc_txfreeq)) == NULL) { /* Ran out of descriptors. */ @@ -1143,7 +1167,6 @@ gem_load_txmbuf(struct gem_softc *sc, struct mbuf **m_head) #endif if (++sc->sc_txwin > GEM_NTXSEGS * 2 / 3) { sc->sc_txwin = 0; - flags |= GEM_TD_INTERRUPT_ME; sc->sc_txdescs[txs->txs_firstdesc].gd_flags |= GEM_DMA_WRITE(sc, GEM_TD_INTERRUPT_ME | GEM_TD_START_OF_PACKET); @@ -1175,6 +1198,8 @@ gem_init_regs(struct gem_softc *sc) { const u_char *laddr = IF_LLADDR(sc->sc_ifp); + GEM_LOCK_ASSERT(sc, MA_OWNED); + /* These registers are not cleared on reset. */ if ((sc->sc_flags & GEM_INITED) == 0) { /* magic values */ @@ -1182,16 +1207,19 @@ gem_init_regs(struct gem_softc *sc) GEM_BANK1_WRITE_4(sc, GEM_MAC_IPG1, 8); GEM_BANK1_WRITE_4(sc, GEM_MAC_IPG2, 4); + /* min frame length */ GEM_BANK1_WRITE_4(sc, GEM_MAC_MAC_MIN_FRAME, ETHER_MIN_LEN); - /* max frame and max burst size */ + /* max frame length and max burst size */ GEM_BANK1_WRITE_4(sc, GEM_MAC_MAC_MAX_FRAME, (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN) | (0x2000 << 16)); + /* more magic values */ GEM_BANK1_WRITE_4(sc, GEM_MAC_PREAMBLE_LEN, 0x7); GEM_BANK1_WRITE_4(sc, GEM_MAC_JAM_SIZE, 0x4); GEM_BANK1_WRITE_4(sc, GEM_MAC_ATTEMPT_LIMIT, 0x10); - /* dunno... */ GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_TYPE, 0x8088); + + /* random number seed */ GEM_BANK1_WRITE_4(sc, GEM_MAC_RANDOM_SEED, ((laddr[5] << 8) | laddr[4]) & 0x3ff); @@ -1209,7 +1237,6 @@ gem_init_regs(struct gem_softc *sc) GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR_FILTER0, 0); GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR_FILTER1, 0); GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR_FILTER2, 0); - GEM_BANK1_WRITE_4(sc, GEM_MAC_ADR_FLT_MASK1_2, 0); GEM_BANK1_WRITE_4(sc, GEM_MAC_ADR_FLT_MASK0, 0); @@ -1232,18 +1259,6 @@ gem_init_regs(struct gem_softc *sc) /* Set XOFF PAUSE time. */ GEM_BANK1_WRITE_4(sc, GEM_MAC_SEND_PAUSE_CMD, 0x1BF0); - /* - * Set the internal arbitration to "infinite" bursts of the - * maximum length of 31 * 64 bytes so DMA transfers aren't - * split up in cache line size chunks. This greatly improves - * especially RX performance. - * Enable silicon bug workarounds for the Apple variants. - */ - GEM_BANK1_WRITE_4(sc, GEM_CONFIG, - GEM_CONFIG_TXDMA_LIMIT | GEM_CONFIG_RXDMA_LIMIT | - GEM_CONFIG_BURST_INF | (GEM_IS_APPLE(sc) ? - GEM_CONFIG_RONPAULBIT | GEM_CONFIG_BUG2FIX : 0)); - /* Set the station address. */ GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR0, (laddr[4] << 8) | laddr[5]); GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR1, (laddr[2] << 8) | laddr[3]); @@ -1263,12 +1278,32 @@ gem_start(struct ifnet *ifp) GEM_UNLOCK(sc); } +static inline void +gem_txkick(struct gem_softc *sc) +{ + + /* + * Update the TX kick register. This register has to point to the + * descriptor after the last valid one and for optimum performance + * should be incremented in multiples of 4 (the DMA engine fetches/ + * updates descriptors in batches of 4). + */ +#ifdef GEM_DEBUG + CTR3(KTR_GEM, "%s: %s: kicking TX %d", + device_get_name(sc->sc_dev), __func__, sc->sc_txnext); +#endif + GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + GEM_BANK1_WRITE_4(sc, GEM_TX_KICK, sc->sc_txnext); +} + static void gem_start_locked(struct ifnet *ifp) { struct gem_softc *sc = ifp->if_softc; struct mbuf *m; - int ntx; + int kicked, ntx; + + GEM_LOCK_ASSERT(sc, MA_OWNED); if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING || (sc->sc_flags & GEM_LINK) == 0) @@ -1280,6 +1315,7 @@ gem_start_locked(struct ifnet *ifp) sc->sc_txnext); #endif ntx = 0; + kicked = 0; for (; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) && sc->sc_txfree > 1;) { IFQ_DRV_DEQUEUE(&ifp->if_snd, m); if (m == NULL) @@ -1291,19 +1327,18 @@ gem_start_locked(struct ifnet *ifp) IFQ_DRV_PREPEND(&ifp->if_snd, m); break; } + if ((sc->sc_txnext % 4) == 0) { + gem_txkick(sc); + kicked = 1; + } else + kicked = 0; ntx++; - /* Kick the transmitter. */ -#ifdef GEM_DEBUG - CTR3(KTR_GEM, "%s: %s: kicking TX %d", - device_get_name(sc->sc_dev), __func__, sc->sc_txnext); -#endif - GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - GEM_BANK1_WRITE_4(sc, GEM_TX_KICK, sc->sc_txnext); - BPF_MTAP(ifp, m); } if (ntx > 0) { + if (kicked == 0) + gem_txkick(sc); #ifdef GEM_DEBUG CTR2(KTR_GEM, "%s: packets enqueued, OWN on %d", device_get_name(sc->sc_dev), sc->sc_txnext); @@ -1324,10 +1359,13 @@ gem_tint(struct gem_softc *sc) { struct ifnet *ifp = sc->sc_ifp; struct gem_txsoft *txs; - int txlast, progress; + int progress; + uint32_t txlast; #ifdef GEM_DEBUG int i; + GEM_LOCK_ASSERT(sc, MA_OWNED); + CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); #endif @@ -1338,7 +1376,6 @@ gem_tint(struct gem_softc *sc) progress = 0; GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { - #ifdef GEM_DEBUG if ((ifp->if_flags & IFF_DEBUG) != 0) { printf(" txsoft %p transmit chain:\n", txs); @@ -1419,8 +1456,8 @@ gem_tint(struct gem_softc *sc) * and restart. */ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - sc->sc_wdog_timer = STAILQ_EMPTY(&sc->sc_txdirtyq) ? 0 : 5; - + if (STAILQ_EMPTY(&sc->sc_txdirtyq)) + sc->sc_wdog_timer = 0; gem_start_locked(ifp); } @@ -1437,6 +1474,7 @@ gem_rint_timeout(void *arg) struct gem_softc *sc = arg; GEM_LOCK_ASSERT(sc, MA_OWNED); + gem_rint(sc); } #endif @@ -1449,6 +1487,8 @@ gem_rint(struct gem_softc *sc) uint64_t rxstat; uint32_t rxcomp; + GEM_LOCK_ASSERT(sc, MA_OWNED); + #ifdef GEM_RINT_TIMEOUT callout_stop(&sc->sc_rx_ch); #endif @@ -1461,12 +1501,11 @@ gem_rint(struct gem_softc *sc) * how long the following loop can execute. */ rxcomp = GEM_BANK1_READ_4(sc, GEM_RX_COMPLETION); - #ifdef GEM_DEBUG - CTR3(KTR_GEM, "%s: sc->rxptr %d, complete %d", + CTR3(KTR_GEM, "%s: sc->sc_rxptr %d, complete %d", __func__, sc->sc_rxptr, rxcomp); #endif - GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); + GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); for (; sc->sc_rxptr != rxcomp;) { m = sc->sc_rxsoft[sc->sc_rxptr].rxs_mbuf; rxstat = GEM_DMA_READ(sc, @@ -1525,9 +1564,9 @@ gem_rint(struct gem_softc *sc) /* * Update the RX kick register. This register has to point * to the descriptor after the last valid one (before the - * current batch) and must be incremented in multiples of - * 4 (because the DMA engine fetches/updates descriptors - * in batches of 4). + * current batch) and for optimum performance should be + * incremented in multiples of 4 (the DMA engine fetches/ + * updates descriptors in batches of 4). */ sc->sc_rxptr = GEM_NEXTRX(sc->sc_rxptr); if ((sc->sc_rxptr % 4) == 0) { @@ -1545,7 +1584,7 @@ gem_rint(struct gem_softc *sc) } ifp->if_ipackets++; - m->m_data += 2; /* We're already off by two */ + m->m_data += ETHER_ALIGN; /* first byte offset */ m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = m->m_len = GEM_RD_BUFLEN(rxstat); @@ -1559,7 +1598,7 @@ gem_rint(struct gem_softc *sc) } #ifdef GEM_DEBUG - CTR3(KTR_GEM, "%s: done sc->rxptr %d, complete %d", __func__, + CTR3(KTR_GEM, "%s: done sc->sc_rxptr %d, complete %d", __func__, sc->sc_rxptr, GEM_BANK1_READ_4(sc, GEM_RX_COMPLETION)); #endif } @@ -1572,6 +1611,8 @@ gem_add_rxbuf(struct gem_softc *sc, int idx) bus_dma_segment_t segs[1]; int error, nsegs; + GEM_LOCK_ASSERT(sc, MA_OWNED); + m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); if (m == NULL) return (ENOBUFS); @@ -1620,7 +1661,15 @@ gem_eint(struct gem_softc *sc, u_int status) return; } - device_printf(sc->sc_dev, "%s: status=%x\n", __func__, status); + device_printf(sc->sc_dev, "%s: status 0x%x", __func__, status); + if ((status & GEM_INTR_BERR) != 0) { + if ((sc->sc_flags & GEM_PCI) != 0) + printf(", PCI bus error 0x%x\n", + GEM_BANK1_READ_4(sc, GEM_PCI_ERROR_STATUS)); + else + printf(", SBus error 0x%x\n", + GEM_BANK1_READ_4(sc, GEM_SBUS_STATUS)); + } } void @@ -1634,8 +1683,8 @@ gem_intr(void *v) #ifdef GEM_DEBUG CTR4(KTR_GEM, "%s: %s: cplt %x, status %x", - device_get_name(sc->sc_dev), __func__, (status >> 19), - (u_int)status); + device_get_name(sc->sc_dev), __func__, + (status >> GEM_STATUS_TX_COMPLETION_SHFT), (u_int)status); /* * PCS interrupts must be cleared, otherwise no traffic is passed! @@ -1665,7 +1714,7 @@ gem_intr(void *v) device_printf(sc->sc_dev, "%s: MIF interrupt\n", __func__); #endif - if ((status & + if (__predict_false(status & (GEM_INTR_RX_TAG_ERR | GEM_INTR_PERR | GEM_INTR_BERR)) != 0) gem_eint(sc, status); @@ -1675,17 +1724,20 @@ gem_intr(void *v) if ((status & (GEM_INTR_TX_EMPTY | GEM_INTR_TX_INTME)) != 0) gem_tint(sc); - if (status & GEM_INTR_TX_MAC) { + if (__predict_false((status & GEM_INTR_TX_MAC) != 0)) { status2 = GEM_BANK1_READ_4(sc, GEM_MAC_TX_STATUS); if ((status2 & - ~(GEM_MAC_TX_XMIT_DONE | GEM_MAC_TX_DEFER_EXP)) != 0) + ~(GEM_MAC_TX_XMIT_DONE | GEM_MAC_TX_DEFER_EXP | + GEM_MAC_TX_PEAK_EXP)) != 0) device_printf(sc->sc_dev, "MAC TX fault, status %x\n", status2); if ((status2 & - (GEM_MAC_TX_UNDERRUN | GEM_MAC_TX_PKT_TOO_LONG)) != 0) + (GEM_MAC_TX_UNDERRUN | GEM_MAC_TX_PKT_TOO_LONG)) != 0) { + sc->sc_ifp->if_oerrors++; gem_init_locked(sc); + } } - if (status & GEM_INTR_RX_MAC) { + if (__predict_false((status & GEM_INTR_RX_MAC) != 0)) { status2 = GEM_BANK1_READ_4(sc, GEM_MAC_RX_STATUS); /* * At least with GEM_SUN_GEM and some GEM_SUN_ERI @@ -1906,6 +1958,8 @@ gem_mii_statchg(device_t dev) sc = device_get_softc(dev); + GEM_LOCK_ASSERT(sc, MA_OWNED); + #ifdef GEM_DEBUG if ((sc->sc_ifp->if_flags & IFF_DEBUG) != 0) device_printf(sc->sc_dev, "%s: status change: PHY = %d\n", @@ -1985,7 +2039,7 @@ gem_mii_statchg(device_t dev) if ((GEM_BANK1_READ_4(sc, GEM_MIF_CONFIG) & GEM_MIF_CONFIG_PHY_SEL) != 0) { /* External MII needs echo disable if half duplex. */ - if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & + if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) == 0) v |= GEM_MAC_XIF_ECHO_DISABL; } else @@ -2053,6 +2107,11 @@ gem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) switch (cmd) { case SIOCSIFFLAGS: GEM_LOCK(sc); + if ((sc->sc_flags & GEM_DYING) != 0) { + error = EINVAL; + GEM_UNLOCK(sc); + break; + } if ((ifp->if_flags & IFF_UP) != 0) { if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && ((ifp->if_flags ^ sc->sc_ifflags) & diff --git a/sys/dev/gem/if_gem_pci.c b/sys/dev/gem/if_gem_pci.c index 275b44eadc7b..05be3236ca7e 100644 --- a/sys/dev/gem/if_gem_pci.c +++ b/sys/dev/gem/if_gem_pci.c @@ -90,7 +90,7 @@ static device_method_t gem_pci_methods[] = { DEVMETHOD(miibus_writereg, gem_mii_writereg), DEVMETHOD(miibus_statchg, gem_mii_statchg), - { 0, 0 } + KOBJMETHOD_END }; static driver_t gem_pci_driver = { @@ -107,7 +107,7 @@ static const struct gem_pci_dev { uint32_t gpd_devid; int gpd_variant; const char *gpd_desc; -} gem_pci_devlist[] = { +} const gem_pci_devlist[] = { { 0x1101108e, GEM_SUN_ERI, "Sun ERI 10/100 Ethernet" }, { 0x2bad108e, GEM_SUN_GEM, "Sun GEM Gigabit Ethernet" }, { 0x0021106b, GEM_APPLE_GMAC, "Apple UniNorth GMAC Ethernet" }, @@ -200,13 +200,18 @@ gem_pci_attach(device_t dev) GEM_PCI_BANK2_OFFSET, GEM_PCI_BANK2_SIZE, &sc->sc_res[GEM_RES_BANK2]->r_bushandle); + /* Determine whether we're running at 66MHz. */ + if ((GEM_BANK2_READ_4(sc, GEM_PCI_BIF_CONFIG) & + GEM_PCI_BIF_CNF_M66EN) != 0) + sc->sc_flags |= GEM_PCI66; + #if defined(__powerpc__) || defined(__sparc64__) OF_getetheraddr(dev, sc->sc_enaddr); #else /* * Dig out VPD (vital product data) and read NA (network address). - * The VPD of GEM resides in the PCI Expansion ROM (PCI FCode) and - * can't be accessed via the PCI capability pointer. + * The VPD resides in the PCI Expansion ROM (PCI FCode) and can't + * be accessed via the PCI capability pointer. * ``Writing FCode 3.x Programs'' (newer ones, dated 1997 and later) * chapter 2 describes the data structure. */ @@ -225,22 +230,21 @@ gem_pci_attach(device_t dev) #define PCI_VPDRES_BYTE0 0x00 #define PCI_VPDRES_ISLARGE(x) ((x) & 0x80) #define PCI_VPDRES_LARGE_NAME(x) ((x) & 0x7f) -#define PCI_VPDRES_TYPE_VPD 0x10 /* large */ #define PCI_VPDRES_LARGE_LEN_LSB 0x01 #define PCI_VPDRES_LARGE_LEN_MSB 0x02 -#define PCI_VPDRES_LARGE_DATA 0x03 -#define PCI_VPD_SIZE 0x03 +#define PCI_VPDRES_LARGE_SIZE 0x03 +#define PCI_VPDRES_TYPE_VPD 0x10 /* large */ #define PCI_VPD_KEY0 0x00 #define PCI_VPD_KEY1 0x01 #define PCI_VPD_LEN 0x02 -#define PCI_VPD_DATA 0x03 +#define PCI_VPD_SIZE 0x03 #define GEM_ROM_READ_1(sc, offs) \ - GEM_BANK1_READ_1((sc), GEM_PCI_ROM_OFFSET + (offs)) + GEM_BANK1_READ_1((sc), GEM_PCI_ROM_OFFSET + (offs)) #define GEM_ROM_READ_2(sc, offs) \ - GEM_BANK1_READ_2((sc), GEM_PCI_ROM_OFFSET + (offs)) + GEM_BANK1_READ_2((sc), GEM_PCI_ROM_OFFSET + (offs)) #define GEM_ROM_READ_4(sc, offs) \ - GEM_BANK1_READ_4((sc), GEM_PCI_ROM_OFFSET + (offs)) + GEM_BANK1_READ_4((sc), GEM_PCI_ROM_OFFSET + (offs)) /* Read PCI Expansion ROM header. */ if (GEM_ROM_READ_2(sc, PCI_ROMHDR_SIG) != PCI_ROMHDR_SIG_MAGIC || @@ -273,22 +277,22 @@ gem_pci_attach(device_t dev) j + PCI_VPDRES_BYTE0)) == 0 || PCI_VPDRES_LARGE_NAME(GEM_ROM_READ_1(sc, j + PCI_VPDRES_BYTE0)) != PCI_VPDRES_TYPE_VPD || - (GEM_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_LEN_LSB) << 8 | + ((GEM_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_LEN_LSB) << 8) | GEM_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_LEN_MSB)) != PCI_VPD_SIZE + ETHER_ADDR_LEN || - GEM_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_DATA + PCI_VPD_KEY0) != + GEM_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_SIZE + PCI_VPD_KEY0) != 0x4e /* N */ || - GEM_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_DATA + PCI_VPD_KEY1) != + GEM_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_SIZE + PCI_VPD_KEY1) != 0x41 /* A */ || - GEM_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_DATA + PCI_VPD_LEN) != + GEM_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_SIZE + PCI_VPD_LEN) != ETHER_ADDR_LEN || - GEM_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_DATA + PCI_VPD_DATA + + GEM_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_SIZE + PCI_VPD_SIZE + ETHER_ADDR_LEN) != 0x79) { device_printf(dev, "unexpected PCI VPD\n"); goto fail; } bus_read_region_1(sc->sc_res[GEM_RES_BANK1], - GEM_PCI_ROM_OFFSET + j + PCI_VPDRES_LARGE_DATA + PCI_VPD_DATA, + GEM_PCI_ROM_OFFSET + j + PCI_VPDRES_LARGE_SIZE + PCI_VPD_SIZE, sc->sc_enaddr, ETHER_ADDR_LEN); #endif @@ -330,19 +334,15 @@ gem_pci_detach(device_t dev) static int gem_pci_suspend(device_t dev) { - struct gem_softc *sc; - sc = device_get_softc(dev); - gem_suspend(sc); + gem_suspend(device_get_softc(dev)); return (0); } static int gem_pci_resume(device_t dev) { - struct gem_softc *sc; - sc = device_get_softc(dev); - gem_resume(sc); + gem_resume(device_get_softc(dev)); return (0); } diff --git a/sys/dev/gem/if_gem_sbus.c b/sys/dev/gem/if_gem_sbus.c new file mode 100644 index 000000000000..4402251354e9 --- /dev/null +++ b/sys/dev/gem/if_gem_sbus.c @@ -0,0 +1,210 @@ +/*- + * Copyright (C) 2001 Eduardo Horvath. + * Copyright (c) 2007 Marius Strobl + * 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. + * + * 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. + * + * from: NetBSD: if_gem_pci.c,v 1.7 2001/10/18 15:09:15 thorpej Exp + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * SBus bindings for Sun GEM Ethernet controllers + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +#include "miibus_if.h" + +static device_probe_t gem_sbus_probe; +static device_attach_t gem_sbus_attach; +static device_detach_t gem_sbus_detach; +static device_suspend_t gem_sbus_suspend; +static device_resume_t gem_sbus_resume; + +static device_method_t gem_sbus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, gem_sbus_probe), + DEVMETHOD(device_attach, gem_sbus_attach), + DEVMETHOD(device_detach, gem_sbus_detach), + DEVMETHOD(device_suspend, gem_sbus_suspend), + DEVMETHOD(device_resume, gem_sbus_resume), + /* Use the suspend handler here, it is all that is required. */ + DEVMETHOD(device_shutdown, gem_sbus_suspend), + + /* bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + + /* MII interface */ + DEVMETHOD(miibus_readreg, gem_mii_readreg), + DEVMETHOD(miibus_writereg, gem_mii_writereg), + DEVMETHOD(miibus_statchg, gem_mii_statchg), + + KOBJMETHOD_END +}; + +static driver_t gem_sbus_driver = { + "gem", + gem_sbus_methods, + sizeof(struct gem_softc) +}; + +DRIVER_MODULE(gem, sbus, gem_sbus_driver, gem_devclass, 0, 0); +MODULE_DEPEND(gem, sbus, 1, 1, 1); +MODULE_DEPEND(gem, ether, 1, 1, 1); + +static int +gem_sbus_probe(device_t dev) +{ + + if (strcmp(ofw_bus_get_name(dev), "network") == 0 && + ofw_bus_get_compat(dev) != NULL && + strcmp(ofw_bus_get_compat(dev), "SUNW,sbus-gem") == 0) { + device_set_desc(dev, "Sun GEM Gigabit Ethernet"); + return (0); + } + + return (ENXIO); +} + +static struct resource_spec gem_sbus_res_spec[] = { + { SYS_RES_IRQ, 0, RF_SHAREABLE | RF_ACTIVE }, /* GEM_RES_INTR */ + { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* GEM_RES_BANK1 */ + { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* GEM_RES_BANK2 */ + { -1, 0 } +}; + +static int +gem_sbus_attach(device_t dev) +{ + struct gem_softc *sc; + int burst; + uint32_t val; + + sc = device_get_softc(dev); + sc->sc_variant = GEM_SUN_GEM; + sc->sc_dev = dev; + + if (bus_alloc_resources(dev, gem_sbus_res_spec, sc->sc_res)) { + device_printf(dev, "failed to allocate resources\n"); + bus_release_resources(dev, gem_sbus_res_spec, sc->sc_res); + return (ENXIO); + } + + GEM_LOCK_INIT(sc, device_get_nameunit(dev)); + + OF_getetheraddr(dev, sc->sc_enaddr); + + burst = sbus_get_burstsz(dev); + val = GEM_SBUS_CFG_PARITY; + if ((burst & SBUS_BURST64_MASK) != 0) { + val |= GEM_SBUS_CFG_64BIT; + burst >>= SBUS_BURST64_SHIFT; + } + if ((burst & SBUS_BURST_64) != 0) + val |= GEM_SBUS_CFG_BURST_64; + else if ((burst & SBUS_BURST_32) != 0) + val |= GEM_SBUS_CFG_BURST_32; + else { + device_printf(dev, "unsupported burst size\n"); + goto fail; + } + /* Reset the SBus interface only. */ + (void)GEM_BANK2_READ_4(sc, GEM_SBUS_BIF_RESET); + DELAY(100); + GEM_BANK2_WRITE_4(sc, GEM_SBUS_CONFIG, val); + + if (gem_attach(sc) != 0) { + device_printf(dev, "could not be attached\n"); + goto fail; + } + + if (bus_setup_intr(dev, sc->sc_res[GEM_RES_INTR], INTR_TYPE_NET | + INTR_MPSAFE, NULL, gem_intr, sc, &sc->sc_ih) != 0) { + device_printf(dev, "failed to set up interrupt\n"); + gem_detach(sc); + goto fail; + } + return (0); + + fail: + GEM_LOCK_DESTROY(sc); + bus_release_resources(dev, gem_sbus_res_spec, sc->sc_res); + return (ENXIO); +} + +static int +gem_sbus_detach(device_t dev) +{ + struct gem_softc *sc; + + sc = device_get_softc(dev); + bus_teardown_intr(dev, sc->sc_res[GEM_RES_INTR], sc->sc_ih); + gem_detach(sc); + GEM_LOCK_DESTROY(sc); + bus_release_resources(dev, gem_sbus_res_spec, sc->sc_res); + return (0); +} + +static int +gem_sbus_suspend(device_t dev) +{ + + gem_suspend(device_get_softc(dev)); + return (0); +} + +static int +gem_sbus_resume(device_t dev) +{ + + gem_resume(device_get_softc(dev)); + return (0); +} diff --git a/sys/dev/gem/if_gemreg.h b/sys/dev/gem/if_gemreg.h index f77ddac3a6cd..effcaf5aa427 100644 --- a/sys/dev/gem/if_gemreg.h +++ b/sys/dev/gem/if_gemreg.h @@ -32,7 +32,7 @@ #ifndef _IF_GEMREG_H #define _IF_GEMREG_H -/* Register definitions for Sun GEM gigabit ethernet */ +/* register definitions for Apple GMAC, Sun ERI and Sun GEM */ /* * First bank: this registers live at the start of the PCI @@ -47,6 +47,51 @@ #define GEM_INTACK 0x0014 /* Interrupt acknowledge, W/O */ #define GEM_STATUS_ALIAS 0x001c +/* Bits in GEM_SEB register */ +#define GEM_SEB_ARB 0x00000002 /* Arbitration status */ +#define GEM_SEB_RXWON 0x00000004 + +/* Bits in GEM_CONFIG register */ +#define GEM_CONFIG_BURST_64 0x00000000 /* maximum burst size 64KB */ +#define GEM_CONFIG_BURST_INF 0x00000001 /* infinite for entire packet */ +#define GEM_CONFIG_TXDMA_LIMIT 0x0000003e +#define GEM_CONFIG_RXDMA_LIMIT 0x000007c0 +/* GEM_CONFIG_RONPAULBIT and GEM_CONFIG_BUG2FIX are Apple only. */ +#define GEM_CONFIG_RONPAULBIT 0x00000800 /* after infinite burst use */ + /* memory read multiple for */ + /* PCI commands */ +#define GEM_CONFIG_BUG2FIX 0x00001000 /* fix RX hang after overflow */ + +#define GEM_CONFIG_TXDMA_LIMIT_SHIFT 1 +#define GEM_CONFIG_RXDMA_LIMIT_SHIFT 6 + +/* Top part of GEM_STATUS has TX completion information */ +#define GEM_STATUS_TX_COMPLETION_MASK 0xfff80000 /* TX completion reg. */ +#define GEM_STATUS_TX_COMPLETION_SHFT 19 + +/* + * Interrupt bits, for both the GEM_STATUS and GEM_INTMASK regs + * Bits 0-6 auto-clear when read. + */ +#define GEM_INTR_TX_INTME 0x00000001 /* Frame w/INTME bit set sent */ +#define GEM_INTR_TX_EMPTY 0x00000002 /* TX ring empty */ +#define GEM_INTR_TX_DONE 0x00000004 /* TX complete */ +#define GEM_INTR_RX_DONE 0x00000010 /* Got a packet */ +#define GEM_INTR_RX_NOBUF 0x00000020 +#define GEM_INTR_RX_TAG_ERR 0x00000040 +#define GEM_INTR_PERR 0x00000080 /* Parity error */ +#define GEM_INTR_PCS 0x00002000 /* Physical Code Sub-layer */ +#define GEM_INTR_TX_MAC 0x00004000 +#define GEM_INTR_RX_MAC 0x00008000 +#define GEM_INTR_MAC_CONTROL 0x00010000 /* MAC control interrupt */ +#define GEM_INTR_MIF 0x00020000 +#define GEM_INTR_BERR 0x00040000 /* Bus error interrupt */ +#define GEM_INTR_BITS "\177\020" \ + "b\0INTME\0b\1TXEMPTY\0b\2TXDONE\0" \ + "b\4RXDONE\0b\5RXNOBUF\0b\6RX_TAG_ERR\0" \ + "b\xdPCS\0b\xeTXMAC\0b\xfRXMAC\0" \ + "b\x10MAC_CONTROL\0b\x11MIF\0b\x12IBERR\0\0" + /* * Second bank: this registers live at offset 0x1000 of the PCI * mapping, and at the start of the first bank of the SBus @@ -55,89 +100,57 @@ #define GEM_PCI_BANK2_OFFSET 0x1000 #define GEM_PCI_BANK2_SIZE 0x14 /* This is the same as the GEM_STATUS reg but reading it does not clear bits. */ -#define GEM_ERROR_STATUS 0x0000 /* PCI error status R/C */ -#define GEM_ERROR_MASK 0x0004 -#define GEM_SBUS_CONFIG 0x0004 -#define GEM_BIF_CONFIG 0x0008 /* BIF config reg */ -#define GEM_BIF_DIAG 0x000c -#define GEM_RESET 0x0010 /* Software reset register */ +#define GEM_PCI_ERROR_STATUS 0x0000 /* PCI error status */ +#define GEM_PCI_ERROR_MASK 0x0004 /* PCI error mask */ +#define GEM_PCI_BIF_CONFIG 0x0008 /* PCI BIF configuration */ +#define GEM_PCI_BIF_DIAG 0x000c /* PCI BIF diagnostic */ +#define GEM_SBUS_BIF_RESET 0x0000 /* SBus BIF only software reset */ +#define GEM_SBUS_CONFIG 0x0004 /* SBus IO configuration */ +#define GEM_SBUS_STATUS 0x0008 /* SBus IO status */ +#define GEM_SBUS_REVISION 0x000c /* SBus revision ID */ -/* Bits in GEM_SEB register */ -#define GEM_SEB_ARB 0x000000002 /* Arbitration status */ -#define GEM_SEB_RXWON 0x000000004 +#define GEM_RESET 0x0010 /* software reset */ -/* Bits in GEM_SBUS_CONFIG register */ -#define GEM_SBUS_CFG_BMODE64 0x00000008 -#define GEM_SBUS_CFG_PARITY 0x00000200 +/* GEM_PCI_ERROR_STATUS and GEM_PCI_ERROR_MASK error bits */ +#define GEM_PCI_ERR_STAT_BADACK 0x00000001 /* No ACK64# */ +#define GEM_PCI_ERR_STAT_DTRTO 0x00000002 /* Delayed xaction timeout */ +#define GEM_PCI_ERR_STAT_OTHERS 0x00000004 +#define GEM_PCI_ERR_BITS "\177\020b\0ACKBAD\0b\1DTRTO\0b\2OTHER\0\0" -/* Bits in GEM_CONFIG register */ -#define GEM_CONFIG_BURST_64 0x000000000 /* maximum burst size 64KB */ -#define GEM_CONFIG_BURST_INF 0x000000001 /* infinite for entire packet */ -#define GEM_CONFIG_TXDMA_LIMIT 0x00000003e -#define GEM_CONFIG_RXDMA_LIMIT 0x0000007c0 -/* GEM_CONFIG_RONPAULBIT and GEM_CONFIG_BUG2FIX are Apple only. */ -#define GEM_CONFIG_RONPAULBIT 0x000000800 /* after infinite burst use */ - /* memory read multiple for */ - /* PCI commands */ -#define GEM_CONFIG_BUG2FIX 0x000001000 /* fix RX hang after overflow */ - -#define GEM_CONFIG_TXDMA_LIMIT_SHIFT 1 -#define GEM_CONFIG_RXDMA_LIMIT_SHIFT 6 - - -/* Top part of GEM_STATUS has TX completion information */ -#define GEM_STATUS_TX_COMPL 0xfff800000 /* TX completion reg. */ - - -/* - * Interrupt bits, for both the GEM_STATUS and GEM_INTMASK regs - * Bits 0-6 auto-clear when read. - */ -#define GEM_INTR_TX_INTME 0x000000001 /* Frame w/INTME bit set sent */ -#define GEM_INTR_TX_EMPTY 0x000000002 /* TX ring empty */ -#define GEM_INTR_TX_DONE 0x000000004 /* TX complete */ -#define GEM_INTR_RX_DONE 0x000000010 /* Got a packet */ -#define GEM_INTR_RX_NOBUF 0x000000020 -#define GEM_INTR_RX_TAG_ERR 0x000000040 -#define GEM_INTR_PERR 0x000000080 /* Parity error */ -#define GEM_INTR_PCS 0x000002000 /* Physical Code Sub-layer */ -#define GEM_INTR_TX_MAC 0x000004000 -#define GEM_INTR_RX_MAC 0x000008000 -#define GEM_INTR_MAC_CONTROL 0x000010000 /* MAC control interrupt */ -#define GEM_INTR_MIF 0x000020000 -#define GEM_INTR_BERR 0x000040000 /* Bus error interrupt */ -#define GEM_INTR_BITS "\177\020" \ - "b\0INTME\0b\1TXEMPTY\0b\2TXDONE\0" \ - "b\4RXDONE\0b\5RXNOBUF\0b\6RX_TAG_ERR\0" \ - "b\xdPCS\0b\xeTXMAC\0b\xfRXMAC\0" \ - "b\x10MAC_CONTROL\0b\x11MIF\0b\x12IBERR\0\0" - - -/* GEM_ERROR_STATUS and GEM_ERROR_MASK PCI error bits */ -#define GEM_ERROR_STAT_BADACK 0x000000001 /* No ACK64# */ -#define GEM_ERROR_STAT_DTRTO 0x000000002 /* Delayed xaction timeout */ -#define GEM_ERROR_STAT_OTHERS 0x000000004 -#define GEM_ERROR_BITS "\177\020b\0ACKBAD\0b\1DTRTO\0b\2OTHER\0\0" - - -/* GEM_BIF_CONFIG register bits */ -#define GEM_BIF_CONFIG_SLOWCLK 0x000000001 /* Parity error timing */ -#define GEM_BIF_CONFIG_HOST_64 0x000000002 /* 64-bit host */ -#define GEM_BIF_CONFIG_B64D_DIS 0x000000004 /* no 64-bit data cycle */ -#define GEM_BIF_CONFIG_M66EN 0x000000008 -#define GEM_BIF_CONFIG_BITS "\177\020b\0SLOWCLK\0b\1HOST64\0" \ +/* GEM_PCI_BIF_CONFIG register bits */ +#define GEM_PCI_BIF_CNF_SLOWCLK 0x00000001 /* Parity error timing */ +#define GEM_PCI_BIF_CNF_HOST_64 0x00000002 /* 64-bit host */ +#define GEM_PCI_BIF_CNF_B64D_DS 0x00000004 /* no 64-bit data cycle */ +#define GEM_PCI_BIF_CNF_M66EN 0x00000008 +#define GEM_PCI_BIF_CNF_BITS "\177\020b\0SLOWCLK\0b\1HOST64\0" \ "b\2B64DIS\0b\3M66EN\0\0" +/* GEM_PCI_BIF_DIAG register bits */ +#define GEN_PCI_BIF_DIAG_BC_SM 0x007f0000 /* burst ctrl. state machine */ +#define GEN_PCI_BIF_DIAG_SM 0xff000000 /* BIF state machine */ + +/* Bits in GEM_SBUS_CONFIG register */ +#define GEM_SBUS_CFG_BURST_32 0x00000001 /* 32 byte bursts */ +#define GEM_SBUS_CFG_BURST_64 0x00000002 /* 64 byte bursts */ +#define GEM_SBUS_CFG_BURST_128 0x00000004 /* 128 byte bursts */ +#define GEM_SBUS_CFG_64BIT 0x00000008 /* extended transfer mode */ +#define GEM_SBUS_CFG_PARITY 0x00000200 /* enable parity checking */ + +/* GEM_SBUS_STATUS register bits */ +#define GEM_SBUS_STATUS_LERR 0x00000001 /* LERR from SBus slave */ +#define GEM_SBUS_STATUS_SACK 0x00000002 /* size ack. error */ +#define GEM_SBUS_STATUS_EACK 0x00000004 /* SBus ctrl. or slave error */ +#define GEM_SBUS_STATUS_MPARITY 0x00000008 /* SBus master parity error */ /* GEM_RESET register bits -- TX and RX self clear when complete. */ -#define GEM_RESET_TX 0x000000001 /* Reset TX half */ -#define GEM_RESET_RX 0x000000002 /* Reset RX half */ -#define GEM_RESET_RSTOUT 0x000000004 /* Force PCI RSTOUT# */ - +#define GEM_RESET_TX 0x00000001 /* Reset TX half. */ +#define GEM_RESET_RX 0x00000002 /* Reset RX half. */ +#define GEM_RESET_PCI_RSTOUT 0x00000004 /* Force PCI RSTOUT#. */ /* The rest of the registers live in the first bank again. */ -/* GEM TX DMA registers */ + +/* TX DMA registers */ #define GEM_TX_KICK 0x2000 /* Write last valid desc + 1 */ #define GEM_TX_CONFIG 0x2004 #define GEM_TX_RING_PTR_LO 0x2008 @@ -162,7 +175,6 @@ #define GEM_TX_FIFO_SIZE 0x2118 #define GEM_TX_DEBUG 0x3028 - /* GEM_TX_CONFIG register bits */ #define GEM_TX_CONFIG_TXDMA_EN 0x00000001 /* TX DMA enable */ #define GEM_TX_CONFIG_TXRING_SZ 0x0000001e /* TX ring size */ @@ -179,12 +191,10 @@ #define GEM_RING_SZ_4096 (7<<1) #define GEM_RING_SZ_8192 (8<<1) - /* GEM_TX_COMPLETION register bits */ #define GEM_TX_COMPLETION_MASK 0x00001fff /* # of last descriptor */ - -/* GEM RX DMA registers */ +/* RX DMA registers */ #define GEM_RX_CONFIG 0x4000 #define GEM_RX_RING_PTR_LO 0x4004 /* 64-bits unaligned GAK! */ #define GEM_RX_RING_PTR_HI 0x4008 /* 64-bits unaligned GAK! */ @@ -211,7 +221,6 @@ #define GEM_RX_FIFO_DATA_HI_T0 0x411c #define GEM_RX_FIFO_SIZE 0x4120 - /* GEM_RX_CONFIG register bits */ #define GEM_RX_CONFIG_RXDMA_EN 0x00000001 /* RX DMA enable */ #define GEM_RX_CONFIG_RXRING_SZ 0x0000001e /* RX ring size */ @@ -231,19 +240,16 @@ #define GEM_RX_CONFIG_FBOFF_SHFT 10 #define GEM_RX_CONFIG_CXM_START_SHFT 13 - /* GEM_RX_PAUSE_THRESH register bits -- sizes in multiples of 64 bytes */ #define GEM_RX_PTH_XOFF_THRESH 0x000001ff #define GEM_RX_PTH_XON_THRESH 0x001ff000 - /* GEM_RX_BLANKING register bits */ #define GEM_RX_BLANKING_PACKETS 0x000001ff /* Delay intr for x packets */ #define GEM_RX_BLANKING_TIME 0x000ff000 /* Delay intr for x ticks */ #define GEM_RX_BLANKING_TIME_SHIFT 12 /* One tick is 2048 PCI clocks, or 16us at 66MHz */ - /* GEM_MAC registers */ #define GEM_MAC_TXRESET 0x6000 /* Store 1, cleared when done */ #define GEM_MAC_RXRESET 0x6004 /* ditto */ @@ -316,12 +322,10 @@ #define GEM_MAC_RANDOM_SEED 0x6130 #define GEM_MAC_MAC_STATE 0x6134 /* MAC state machine reg */ - /* GEM_MAC_SEND_PAUSE_CMD register bits */ #define GEM_MAC_PAUSE_CMD_TIME 0x0000ffff #define GEM_MAC_PAUSE_CMD_SEND 0x00010000 - /* GEM_MAC_TX_STATUS and _MASK register bits */ #define GEM_MAC_TX_XMIT_DONE 0x00000001 #define GEM_MAC_TX_UNDERRUN 0x00000002 @@ -333,7 +337,6 @@ #define GEM_MAC_TX_DEFER_EXP 0x00000080 #define GEM_MAC_TX_PEAK_EXP 0x00000100 - /* GEM_MAC_RX_STATUS and _MASK register bits */ #define GEM_MAC_RX_DONE 0x00000001 #define GEM_MAC_RX_OVERFLOW 0x00000002 @@ -343,7 +346,6 @@ #define GEM_MAC_RX_LEN_EXP 0x00000020 #define GEM_MAC_RX_CVI_EXP 0x00000040 /* Code violation */ - /* GEM_MAC_CONTROL_STATUS and GEM_MAC_CONTROL_MASK register bits */ #define GEM_MAC_PAUSED 0x00000001 /* Pause received */ #define GEM_MAC_PAUSE 0x00000002 /* enter pause state */ @@ -386,14 +388,13 @@ #define GEM_MAC_TX_SLOWDOWN 0x00000080 #define GEM_MAC_TX_NO_FCS 0x00000100 /* no FCS will be generated */ #define GEM_MAC_TX_CARR_EXTEND 0x00000200 /* Ena TX Carrier Extension */ -/* Carrier Extension is required for half duplex Gbps operation */ +/* Carrier Extension is required for half duplex Gbps operation. */ #define GEM_MAC_TX_CONFIG_BITS "\177\020" \ "b\0TXENA\0b\1IGNCAR\0b\2IGNCOLLIS\0" \ "b\3IPG0ENA\0b\4TXNGU\0b\5TXNGULIM\0" \ "b\6NOBKOFF\0b\7SLOWDN\0b\x8NOFCS\0" \ "b\x9TXCARREXT\0\0" - /* GEM_MAC_RX_CONFIG register bits */ #define GEM_MAC_RX_ENABLE 0x00000001 /* RX enable */ #define GEM_MAC_RX_STRIP_PAD 0x00000002 /* strip pad bytes */ @@ -413,32 +414,31 @@ "b\3PROMIS\0b\4PROMISCGRP\0b\5HASHFLTR\0" \ "b\6ADDRFLTR\0b\7ERRCHKDIS\0b\x9TXCARREXT\0\0" - /* GEM_MAC_CONTROL_CONFIG bits */ #define GEM_MAC_CC_TX_PAUSE 0x00000001 /* send pause enabled */ #define GEM_MAC_CC_RX_PAUSE 0x00000002 /* receive pause enabled */ #define GEM_MAC_CC_PASS_PAUSE 0x00000004 /* pass pause up */ #define GEM_MAC_CC_BITS "\177\020b\0TXPAUSE\0b\1RXPAUSE\0b\2NOPAUSE\0\0" - -/* GEM MIF registers */ -/* Bit bang registers use low bit only. */ +/* + * MIF registers + * Bit bang registers use low bit only. + */ #define GEM_MIF_BB_CLOCK 0x6200 /* bit bang clock */ #define GEM_MIF_BB_DATA 0x6204 /* bit bang data */ #define GEM_MIF_BB_OUTPUT_ENAB 0x6208 #define GEM_MIF_FRAME 0x620c /* MIF frame - ctl and data */ #define GEM_MIF_CONFIG 0x6210 -#define GEM_MIF_INTERRUPT_MASK 0x6214 -#define GEM_MIF_BASIC_STATUS 0x6218 +#define GEM_MIF_MASK 0x6214 +#define GEM_MIF_STATUS 0x6218 #define GEM_MIF_STATE_MACHINE 0x621c - /* GEM_MIF_FRAME bits */ #define GEM_MIF_FRAME_DATA 0x0000ffff -#define GEM_MIF_FRAME_TA0 0x00010000 /* TA bit, 1 for completion */ -#define GEM_MIF_FRAME_TA1 0x00020000 /* TA bits */ +#define GEM_MIF_FRAME_TA0 0x00010000 /* TA LSB, 1 for completion */ +#define GEM_MIF_FRAME_TA1 0x00020000 /* TA MSB, 1 for instruction */ #define GEM_MIF_FRAME_REG_ADDR 0x007c0000 -#define GEM_MIF_FRAME_PHY_ADDR 0x0f800000 /* phy address, should be 0 */ +#define GEM_MIF_FRAME_PHY_ADDR 0x0f800000 /* PHY address */ #define GEM_MIF_FRAME_OP 0x30000000 /* operation - write/read */ #define GEM_MIF_FRAME_START 0xc0000000 /* START bits */ @@ -448,31 +448,29 @@ #define GEM_MIF_REG_SHIFT 18 #define GEM_MIF_PHY_SHIFT 23 - /* GEM_MIF_CONFIG register bits */ -#define GEM_MIF_CONFIG_PHY_SEL 0x00000001 /* PHY select, 0=MDIO0 */ +#define GEM_MIF_CONFIG_PHY_SEL 0x00000001 /* PHY select, 0: MDIO_0 */ #define GEM_MIF_CONFIG_POLL_ENA 0x00000002 /* poll enable */ #define GEM_MIF_CONFIG_BB_ENA 0x00000004 /* bit bang enable */ #define GEM_MIF_CONFIG_REG_ADR 0x000000f8 /* poll register address */ -#define GEM_MIF_CONFIG_MDI0 0x00000100 /* MDIO_0 Data/MDIO_0 atached */ -#define GEM_MIF_CONFIG_MDI1 0x00000200 /* MDIO_1 Data/MDIO_1 atached */ +#define GEM_MIF_CONFIG_MDI0 0x00000100 /* MDIO_0 attached/data */ +#define GEM_MIF_CONFIG_MDI1 0x00000200 /* MDIO_1 attached/data */ #define GEM_MIF_CONFIG_PHY_ADR 0x00007c00 /* poll PHY address */ /* MDI0 is the onboard transceiver, MDI1 is external, PHYAD for both is 0. */ #define GEM_MIF_CONFIG_BITS "\177\020b\0PHYSEL\0b\1POLL\0b\2BBENA\0" \ "b\x8MDIO0\0b\x9MDIO1\0\0" - -/* GEM_MIF_BASIC_STATUS and GEM_MIF_INTERRUPT_MASK bits */ -#define GEM_MIF_STATUS 0x0000ffff -#define GEM_MIF_BASIC 0xffff0000 +/* GEM_MIF_STATUS and GEM_MIF_MASK bits */ +#define GEM_MIF_POLL_STATUS_MASK 0x0000ffff /* polling status */ +#define GEM_MIF_POLL_STATUS_SHFT 0 +#define GEM_MIF_POLL_DATA_MASK 0xffff0000 /* polling data */ +#define GEM_MIF_POLL_DATA_SHFT 8 /* * The Basic part is the last value read in the POLL field of the config * register. - * * The status part indicates the bits that have changed. */ - /* GEM PCS/Serial link registers */ /* DO NOT TOUCH THESE REGISTERS ON ERI -- IT HARD HANGS. */ #define GEM_MII_CONTROL 0x9000 @@ -485,106 +483,94 @@ #define GEM_MII_DATAPATH_MODE 0x9050 #define GEM_MII_SLINK_CONTROL 0x9054 /* Serial link control */ #define GEM_MII_OUTPUT_SELECT 0x9058 -#define GEM_MII_SLINK_STATUS 0x905c /* serial link status */ - +#define GEM_MII_SLINK_STATUS 0x905c /* Serialink status */ /* GEM_MII_CONTROL bits - PCS "BMCR" (Basic Mode Control Reg) */ -#define GEM_MII_CONTROL_RESET 0x00008000 -#define GEM_MII_CONTROL_LOOPBK 0x00004000 /* 10-bit i/f loopback */ -#define GEM_MII_CONTROL_1000M 0x00002000 /* speed select, always 0 */ -#define GEM_MII_CONTROL_AUTONEG 0x00001000 /* auto negotiation enabled */ -#define GEM_MII_CONTROL_POWERDN 0x00000800 -#define GEM_MII_CONTROL_ISOLATE 0x00000400 /* isolate phy from mii */ -#define GEM_MII_CONTROL_RAN 0x00000200 /* restart auto negotiation */ -#define GEM_MII_CONTROL_FDUPLEX 0x00000100 /* full duplex, always 0 */ +#define GEM_MII_CONTROL_1000M 0x00000040 /* 1000Mbps speed select */ #define GEM_MII_CONTROL_COL_TST 0x00000080 /* collision test */ +#define GEM_MII_CONTROL_FDUPLEX 0x00000100 /* full-duplex, always 0 */ +#define GEM_MII_CONTROL_RAN 0x00000200 /* restart auto-negotiation */ +#define GEM_MII_CONTROL_ISOLATE 0x00000400 /* isolate PHY from MII */ +#define GEM_MII_CONTROL_POWERDN 0x00000800 /* power down */ +#define GEM_MII_CONTROL_AUTONEG 0x00001000 /* auto-negotiation enable */ +#define GEM_MII_CONTROL_10_100M 0x00002000 /* 10/100Mbps speed select */ +#define GEM_MII_CONTROL_LOOPBK 0x00004000 /* 10-bit i/f loopback */ +#define GEM_MII_CONTROL_RESET 0x00008000 /* Reset PCS. */ #define GEM_MII_CONTROL_BITS "\177\020b\7COLTST\0b\x8_FD\0b\x9RAN\0" \ "b\xaISOLATE\0b\xbPWRDWN\0b\xc_ANEG\0" \ "b\xdGIGE\0b\xeLOOP\0b\xfRESET\0\0" - /* GEM_MII_STATUS reg - PCS "BMSR" (Basic Mode Status Reg) */ -#define GEM_MII_STATUS_GB_FDX 0x00000400 /* can perform GBit FDX */ -#define GEM_MII_STATUS_GB_HDX 0x00000200 /* can perform GBit HDX */ -#define GEM_MII_STATUS_UNK 0x00000100 -#define GEM_MII_STATUS_ANEG_CPT 0x00000020 /* auto negotiate compete */ -#define GEM_MII_STATUS_REM_FLT 0x00000010 /* remote fault detected */ -#define GEM_MII_STATUS_ACFG 0x00000008 /* can auto negotiate */ -#define GEM_MII_STATUS_LINK_STS 0x00000004 /* link status */ +#define GEM_MII_STATUS_EXTCAP 0x00000001 /* extended capability */ #define GEM_MII_STATUS_JABBER 0x00000002 /* jabber condition detected */ -#define GEM_MII_STATUS_EXTCAP 0x00000001 /* extended register capability */ +#define GEM_MII_STATUS_LINK_STS 0x00000004 /* link status */ +#define GEM_MII_STATUS_ACFG 0x00000008 /* can auto-negotiate */ +#define GEM_MII_STATUS_REM_FLT 0x00000010 /* remote fault detected */ +#define GEM_MII_STATUS_ANEG_CPT 0x00000020 /* auto-negotiate complete */ +#define GEM_MII_STATUS_EXTENDED 0x00000100 /* extended status */ #define GEM_MII_STATUS_BITS "\177\020b\0EXTCAP\0b\1JABBER\0b\2LINKSTS\0" \ - "b\3ACFG\0b\4REMFLT\0b\5ANEGCPT\0b\x9GBHDX\0" \ - "b\xaGBFDX\0\0" - + "b\3ACFG\0b\4REMFLT\0b\5ANEGCPT\0\0" /* GEM_MII_ANAR and GEM_MII_ANLPAR reg bits */ -#define GEM_MII_ANEG_NP 0x00008000 /* next page bit */ -#define GEM_MII_ANEG_ACK 0x00004000 /* ack reception of */ - /* Link Partner Capability */ -#define GEM_MII_ANEG_RF 0x00003000 /* advertise remote fault cap */ -#define GEM_MII_ANEG_ASYM_PAUSE 0x00000100 /* asymmetric pause */ -#define GEM_MII_ANEG_SYM_PAUSE 0x00000080 /* symmetric pause */ -#define GEM_MII_ANEG_HLF_DUPLX 0x00000040 -#define GEM_MII_ANEG_FUL_DUPLX 0x00000020 +#define GEM_MII_ANEG_FDUPLX 0x00000020 /* full-duplex */ +#define GEM_MII_ANEG_HDUPLX 0x00000040 /* half-duplex */ +#define GEM_MII_ANEG_PAUSE 0x00000080 /* symmetric PAUSE */ +#define GEM_MII_ANEG_ASM_DIR 0x00000100 /* asymmetric PAUSE */ +#define GEM_MII_ANEG_RFLT_FAIL 0x00001000 /* remote fault - fail */ +#define GEM_MII_ANEG_RFLT_OFF 0x00002000 /* remote fault - off-line */ +#define GEM_MII_ANEG_RFLT_MASK \ +(CAS_PCS_ANEG_RFLT_FAIL | CAS_PCS_ANEG_RFLT_OFF) +#define GEM_MII_ANEG_ACK 0x00004000 /* acknowledge */ +#define GEM_MII_ANEG_NP 0x00008000 /* next page */ #define GEM_MII_ANEG_BITS "\177\020b\5FDX\0b\6HDX\0b\7SYMPAUSE\0" \ "\b\x8_ASYMPAUSE\0\b\xdREMFLT\0\b\xeLPACK\0" \ "\b\xfNPBIT\0\0" - /* GEM_MII_CONFIG reg */ -#define GEM_MII_CONFIG_TIMER 0x0000000e /* link monitor timer values */ -#define GEM_MII_CONFIG_ANTO 0x00000020 /* 10ms ANEG timer override */ -#define GEM_MII_CONFIG_JS 0x00000018 /* Jitter Study, 0 normal - * 1 high freq, 2 low freq */ -#define GEM_MII_CONFIG_SDL 0x00000004 /* Signal Detect active low */ -#define GEM_MII_CONFIG_SDO 0x00000002 /* Signal Detect Override */ -#define GEM_MII_CONFIG_ENABLE 0x00000001 /* Enable PCS */ +#define GEM_MII_CONFIG_ENABLE 0x00000001 /* Enable PCS. */ +#define GEM_MII_CONFIG_SDO 0x00000002 /* signal detect override */ +#define GEM_MII_CONFIG_SDL 0x00000004 /* signal detect active-low */ +#define GEM_MII_CONFIG_JS_NORM 0x00000000 /* jitter study - normal op. */ +#define GEM_MII_CONFIG_JS_HF 0x00000008 /* jitter study - HF test */ +#define GEM_MII_CONFIG_JS_LF 0x00000010 /* jitter study - LF test */ +#define GEM_MII_CONFIG_JS_MASK \ + (GEM_MII_CONFIG_JS_HF | GEM_MII_CONFIG_JS_LF) +#define GEM_MII_CONFIG_ANTO 0x00000020 /* auto-neg. timer override */ #define GEM_MII_CONFIG_BITS "\177\020b\0PCSENA\0\0" - -/* - * GEM_MII_STATE_MACHINE - * XXX These are best guesses from observed behavior. - */ -#define GEM_MII_FSM_STOP 0x00000000 /* stopped */ -#define GEM_MII_FSM_RUN 0x00000001 /* running */ -#define GEM_MII_FSM_UNKWN 0x00000100 /* unknown */ -#define GEM_MII_FSM_DONE 0x00000101 /* complete */ - - /* * GEM_MII_INTERRUP_STATUS reg * No mask register; mask with the global interrupt mask register. */ #define GEM_MII_INTERRUP_LINK 0x00000004 /* PCS link status change */ - /* GEM_MII_DATAPATH_MODE reg */ -#define GEM_MII_DATAPATH_SERIAL 0x00000001 /* Serial link */ -#define GEM_MII_DATAPATH_SERDES 0x00000002 /* Use PCS via 10bit interfac */ -#define GEM_MII_DATAPATH_MII 0x00000004 /* Use {G}MII, not PCS */ -#define GEM_MII_DATAPATH_MIIOUT 0x00000008 /* enable serial output on GMII */ +#define GEM_MII_DATAPATH_SERIAL 0x00000001 /* Serialink */ +#define GEM_MII_DATAPATH_SERDES 0x00000002 /* SERDES via 10-bit */ +#define GEM_MII_DATAPATH_MII 0x00000004 /* GMII/MII */ +#define GEM_MII_DATAPATH_GMIIOE 0x00000008 /* serial output on GMII en. */ #define GEM_MII_DATAPATH_BITS "\177\020" \ - "b\0SERIAL\0b\1SERDES\0b\2MII\0b\3MIIOUT\0\0" - + "b\0SERIAL\0b\1SERDES\0b\2MII\0b\3GMIIOE\0\0" /* GEM_MII_SLINK_CONTROL reg */ -#define GEM_MII_SLINK_LOOPBACK 0x00000001 /* enable loopback at sl, logic +#define GEM_MII_SLINK_LOOPBACK 0x00000001 /* enable loopback at SL, logic * reversed for SERDES */ #define GEM_MII_SLINK_EN_SYNC_D 0x00000002 /* enable sync detection */ -#define GEM_MII_SLINK_LOCK_REF 0x00000004 /* lock reference clock */ -#define GEM_MII_SLINK_EMPHASIS 0x00000008 /* enable emphasis */ -#define GEM_MII_SLINK_SELFTEST 0x000001c0 -#define GEM_MII_SLINK_POWER_OFF 0x00000200 /* Power down serial link */ +#define GEM_MII_SLINK_LOCK_REF 0x00000004 /* lock to reference clock */ +#define GEM_MII_SLINK_EMPHASIS 0x00000018 /* enable emphasis */ +#define GEM_MII_SLINK_SELFTEST 0x000001c0 /* self-test */ +#define GEM_MII_SLINK_POWER_OFF 0x00000200 /* Power down Serialink. */ +#define GEM_MII_SLINK_RX_ZERO 0x00000c00 /* PLL input to Serialink. */ +#define GEM_MII_SLINK_RX_POLE 0x00003000 /* PLL input to Serialink. */ +#define GEM_MII_SLINK_TX_ZERO 0x0000c000 /* PLL input to Serialink. */ +#define GEM_MII_SLINK_TX_POLE 0x00030000 /* PLL input to Serialink. */ #define GEM_MII_SLINK_CONTROL_BITS \ "\177\020b\0LOOP\0b\1ENASYNC\0b\2LOCKREF" \ "\0b\3EMPHASIS\0b\x9PWRDWN\0\0" - /* GEM_MII_SLINK_STATUS reg */ #define GEM_MII_SLINK_TEST 0x00000000 /* undergoing test */ -#define GEM_MII_SLINK_LOCKED 0x00000001 /* waiting 500us lockrefn */ +#define GEM_MII_SLINK_LOCKED 0x00000001 /* waiting 500us w/ lockrefn */ #define GEM_MII_SLINK_COMMA 0x00000002 /* waiting for comma detect */ #define GEM_MII_SLINK_SYNC 0x00000003 /* recv data synchronized */ @@ -596,12 +582,12 @@ #define GEM_PCI_ROM_OFFSET 0x100000 #define GEM_PCI_ROM_SIZE 0x10000 -/* Wired GEM PHY addresses */ +/* Wired PHY addresses */ #define GEM_PHYAD_INTERNAL 1 #define GEM_PHYAD_EXTERNAL 0 /* - * GEM descriptor table structures + * descriptor table structures */ struct gem_desc { uint64_t gd_flags; @@ -609,29 +595,29 @@ struct gem_desc { }; /* Transmit flags */ -#define GEM_TD_BUFSIZE 0x0000000000007fffLL -#define GEM_TD_CXSUM_START 0x00000000001f8000LL /* Cxsum start offset */ +#define GEM_TD_BUFSIZE 0x0000000000007fffULL +#define GEM_TD_CXSUM_START 0x00000000001f8000ULL /* Cxsum start offset */ #define GEM_TD_CXSUM_STARTSHFT 15 -#define GEM_TD_CXSUM_STUFF 0x000000001fe00000LL /* Cxsum stuff offset */ +#define GEM_TD_CXSUM_STUFF 0x000000001fe00000ULL /* Cxsum stuff offset */ #define GEM_TD_CXSUM_STUFFSHFT 21 -#define GEM_TD_CXSUM_ENABLE 0x0000000020000000LL /* Cxsum generation enable */ -#define GEM_TD_END_OF_PACKET 0x0000000040000000LL -#define GEM_TD_START_OF_PACKET 0x0000000080000000LL -#define GEM_TD_INTERRUPT_ME 0x0000000100000000LL /* Interrupt me now */ -#define GEM_TD_NO_CRC 0x0000000200000000LL /* do not insert crc */ +#define GEM_TD_CXSUM_ENABLE 0x0000000020000000ULL /* Cxsum generation enable */ +#define GEM_TD_END_OF_PACKET 0x0000000040000000ULL +#define GEM_TD_START_OF_PACKET 0x0000000080000000ULL +#define GEM_TD_INTERRUPT_ME 0x0000000100000000ULL /* Interrupt me now */ +#define GEM_TD_NO_CRC 0x0000000200000000ULL /* do not insert crc */ /* * Only need to set GEM_TD_CXSUM_ENABLE, GEM_TD_CXSUM_STUFF, * GEM_TD_CXSUM_START, and GEM_TD_INTERRUPT_ME in 1st descriptor of a group. */ /* Receive flags */ -#define GEM_RD_CHECKSUM 0x000000000000ffffLL /* is the complement */ -#define GEM_RD_BUFSIZE 0x000000007fff0000LL -#define GEM_RD_OWN 0x0000000080000000LL /* 1 - owned by h/w */ -#define GEM_RD_HASHVAL 0x0ffff00000000000LL -#define GEM_RD_HASH_PASS 0x1000000000000000LL /* passed hash filter */ -#define GEM_RD_ALTERNATE_MAC 0x2000000000000000LL /* Alternate MAC adrs */ -#define GEM_RD_BAD_CRC 0x4000000000000000LL +#define GEM_RD_CHECKSUM 0x000000000000ffffULL /* is the complement */ +#define GEM_RD_BUFSIZE 0x000000007fff0000ULL +#define GEM_RD_OWN 0x0000000080000000ULL /* 1 - owned by h/w */ +#define GEM_RD_HASHVAL 0x0ffff00000000000ULL +#define GEM_RD_HASH_PASS 0x1000000000000000ULL /* passed hash filter */ +#define GEM_RD_ALTERNATE_MAC 0x2000000000000000ULL /* Alternate MAC adrs */ +#define GEM_RD_BAD_CRC 0x4000000000000000ULL #define GEM_RD_BUFSHIFT 16 #define GEM_RD_BUFLEN(x) (((x) & GEM_RD_BUFSIZE) >> GEM_RD_BUFSHIFT) diff --git a/sys/dev/gem/if_gemvar.h b/sys/dev/gem/if_gemvar.h index 76e2b20f15a6..48e3299ca41e 100644 --- a/sys/dev/gem/if_gemvar.h +++ b/sys/dev/gem/if_gemvar.h @@ -35,7 +35,7 @@ #include /* - * Transmit descriptor list size. This is arbitrary, but allocate + * Transmit descriptor ring size - this is arbitrary, but allocate * enough descriptors for 64 pending transmissions and 16 segments * per packet. This limit is not actually enforced (packets with * more segments can be sent, depending on the busdma backend); it @@ -50,7 +50,7 @@ #define GEM_NEXTTX(x) ((x + 1) & GEM_NTXDESC_MASK) /* - * Receive descriptor list size. We have one RX buffer per incoming + * Receive descriptor ring size - we have one RX buffer per incoming * packet, so this logic is a little simpler. */ #define GEM_NRXDESC 256 @@ -64,7 +64,7 @@ #define GEM_RXOWN_TICKS (hz / 50) /* - * Control structures are DMA'd to the GEM chip. We allocate them + * Control structures are DMA'd to the chip. We allocate them * in a single clump that maps to a single DMA segment to make * several things easier. */ @@ -83,9 +83,9 @@ struct gem_control_data { struct gem_txsoft { struct mbuf *txs_mbuf; /* head of our mbuf chain */ bus_dmamap_t txs_dmamap; /* our DMA map */ - int txs_firstdesc; /* first descriptor in packet */ - int txs_lastdesc; /* last descriptor in packet */ - int txs_ndescs; /* number of descriptors */ + u_int txs_firstdesc; /* first descriptor in packet */ + u_int txs_lastdesc; /* last descriptor in packet */ + u_int txs_ndescs; /* number of descriptors */ STAILQ_ENTRY(gem_txsoft) txs_q; }; @@ -112,7 +112,7 @@ struct gem_softc { u_char sc_enaddr[ETHER_ADDR_LEN]; struct callout sc_tick_ch; /* tick callout */ struct callout sc_rx_ch; /* delayed RX callout */ - int sc_wdog_timer; /* watchdog timer */ + u_int sc_wdog_timer; /* watchdog timer */ void *sc_ih; struct resource *sc_res[3]; @@ -141,15 +141,15 @@ struct gem_softc { u_int sc_flags; #define GEM_INITED (1 << 0) /* reset persistent regs init'ed */ -#define GEM_LINK (1 << 1) /* link is up */ -#define GEM_PCI (1 << 2) /* PCI busses are little-endian */ -#define GEM_SERDES (1 << 3) /* use the SERDES */ +#define GEM_DYING (1 << 1) /* detach initiated */ +#define GEM_LINK (1 << 2) /* link is up */ +#define GEM_PCI (1 << 3) /* PCI busses are little-endian */ +#define GEM_PCI66 (1 << 4) /* PCI bus runs at 66MHz */ +#define GEM_SERDES (1 << 5) /* use the SERDES */ /* * ring buffer DMA stuff */ - bus_dma_segment_t sc_cdseg; /* control data memory */ - int sc_cdnseg; /* number of segments */ bus_dmamap_t sc_cddmamap; /* control data DMA map */ bus_addr_t sc_cddma; @@ -166,18 +166,18 @@ struct gem_softc { #define sc_txdescs sc_control_data->gcd_txdescs #define sc_rxdescs sc_control_data->gcd_rxdescs - int sc_txfree; /* number of free TX descriptors */ - int sc_txnext; /* next ready TX descriptor */ - int sc_txwin; /* TX desc. since last TX intr. */ + u_int sc_txfree; /* number of free TX descriptors */ + u_int sc_txnext; /* next ready TX descriptor */ + u_int sc_txwin; /* TX desc. since last TX intr. */ struct gem_txsq sc_txfreeq; /* free TX descsofts */ struct gem_txsq sc_txdirtyq; /* dirty TX descsofts */ - int sc_rxptr; /* next ready RX desc./descsoft */ - int sc_rxfifosize; /* RX FIFO size (bytes) */ + u_int sc_rxptr; /* next ready RX descriptor/state */ + u_int sc_rxfifosize; /* RX FIFO size (bytes) */ int sc_ifflags; - int sc_csum_features; + u_long sc_csum_features; }; #define GEM_BANKN_BARRIER(n, sc, offs, len, flags) \ @@ -238,10 +238,9 @@ do { \ __m->m_data = __m->m_ext.ext_buf; \ __rxd->gd_addr = \ GEM_DMA_WRITE((sc), __rxs->rxs_paddr); \ - __rxd->gd_flags = \ - GEM_DMA_WRITE((sc), \ - (((__m->m_ext.ext_size) << GEM_RD_BUFSHIFT) \ - & GEM_RD_BUFSIZE) | GEM_RD_OWN); \ + __rxd->gd_flags = GEM_DMA_WRITE((sc), \ + (((__m->m_ext.ext_size) << GEM_RD_BUFSHIFT) & \ + GEM_RD_BUFSIZE) | GEM_RD_OWN); \ } while (0) #define GEM_UPDATE_RXDESC(sc, x) \ @@ -250,10 +249,9 @@ do { \ struct gem_desc *__rxd = &sc->sc_rxdescs[(x)]; \ struct mbuf *__m = __rxs->rxs_mbuf; \ \ - __rxd->gd_flags = \ - GEM_DMA_WRITE((sc), \ - (((__m->m_ext.ext_size) << GEM_RD_BUFSHIFT) \ - & GEM_RD_BUFSIZE) | GEM_RD_OWN); \ + __rxd->gd_flags = GEM_DMA_WRITE((sc), \ + (((__m->m_ext.ext_size) << GEM_RD_BUFSHIFT) & \ + GEM_RD_BUFSIZE) | GEM_RD_OWN); \ } while (0) #define GEM_LOCK_INIT(_sc, _name) \ diff --git a/sys/modules/gem/Makefile b/sys/modules/gem/Makefile index 4352bd636f86..94db46251a7f 100644 --- a/sys/modules/gem/Makefile +++ b/sys/modules/gem/Makefile @@ -3,6 +3,10 @@ .PATH: ${.CURDIR}/../../dev/gem KMOD= if_gem -SRCS= if_gem.c if_gem_pci.c device_if.h bus_if.h pci_if.h miibus_if.h +SRCS= bus_if.h device_if.h if_gem.c if_gem_pci.c miibus_if.h pci_if.h + +.if ${MACHINE} == "sparc64" +SRCS+= if_gem_sbus.c ofw_bus_if.h +.endif .include