Date: Sat, 30 May 2009 16:01:05 GMT From: Arnar Mar Sig <antab@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 163091 for review Message-ID: <200905301601.n4UG15lX065795@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=163091 Change 163091 by antab@antab_farm on 2009/05/30 16:00:08 * Update in_cksum with copy from mips. * Update if_ate and hack it to work on at32ap700x, need to clean it up later. rootfs over NFS is now working Affected files ... .. //depot/projects/avr32/src/sys/avr32/avr32/in_cksum.c#2 edit .. //depot/projects/avr32/src/sys/avr32/avr32/trap.c#10 edit .. //depot/projects/avr32/src/sys/dev/ate/if_ate.c#2 edit .. //depot/projects/avr32/src/sys/dev/ate/if_atereg.h#1 add .. //depot/projects/avr32/src/sys/netinet/udp_usrreq.c#7 edit Differences ... ==== //depot/projects/avr32/src/sys/avr32/avr32/in_cksum.c#2 (text+ko) ==== @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: src/sys/mips/mips/in_cksum.c,v 1.1 2008/04/13 07:27:37 imp Exp $"); +__FBSDID("$FreeBSD: src/sys/mips/mips/in_cksum.c,v 1.3 2009/02/08 23:43:36 gonzo Exp $"); #include <sys/param.h> #include <sys/mbuf.h> @@ -69,7 +69,7 @@ } static const u_int32_t in_masks[] = { -#ifndef _MISEB +#if _BYTE_ORDER == _LITTLE_ENDIAN /*0 bytes*/ /*1 byte*/ /*2 bytes*/ /*3 bytes*/ 0x00000000, 0x000000FF, 0x0000FFFF, 0x00FFFFFF, /* offset 0 */ 0x00000000, 0x0000FF00, 0x00FFFF00, 0xFFFFFF00, /* offset 1 */ @@ -104,9 +104,9 @@ union q_util q_util; if ((3 & (long) lw) == 0 && len == 20) { - sum = (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3] + lw[4]; - REDUCE32; - return sum; + sum = (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3] + lw[4]; + REDUCE32; + return sum; } if ((offset = 3 & (long) lw) != 0) { @@ -190,7 +190,7 @@ u_int64_t sum; union q_util q_util; union l_util l_util; - + sum = (u_int64_t) a + b + c; REDUCE16; return (sum); @@ -206,16 +206,16 @@ union q_util q_util; union l_util l_util; - len -= skip; - for (; skip && m; m = m->m_next) { - if (m->m_len > skip) { - mlen = m->m_len - skip; + len -= skip; + for (; skip && m; m = m->m_next) { + if (m->m_len > skip) { + mlen = m->m_len - skip; addr = mtod(m, caddr_t) + skip; - goto skip_start; - } else { - skip -= m->m_len; - } - } + goto skip_start; + } else { + skip -= m->m_len; + } + } for (; m && len; m = m->m_next) { if (m->m_len == 0) @@ -227,9 +227,9 @@ mlen = len; if ((clen ^ (int) addr) & 1) - sum += in_cksumdata(addr, mlen) << 8; + sum += in_cksumdata(addr, mlen) << 8; else - sum += in_cksumdata(addr, mlen); + sum += in_cksumdata(addr, mlen); clen += mlen; len -= mlen; @@ -240,9 +240,9 @@ u_int in_cksum_hdr(const struct ip *ip) { - u_int64_t sum = in_cksumdata(ip, sizeof(struct ip)); - union q_util q_util; - union l_util l_util; - REDUCE16; - return (~sum & 0xffff); + u_int64_t sum = in_cksumdata(ip, sizeof(struct ip)); + union q_util q_util; + union l_util l_util; + REDUCE16; + return (~sum & 0xffff); } ==== //depot/projects/avr32/src/sys/avr32/avr32/trap.c#10 (text+ko) ==== @@ -545,6 +545,8 @@ , frame->regs.sr); switch (type) { + case T_DATA_READ_ALIGNMENT: + case T_DATA_WRITE_ALIGNMENT: case T_TLB_MISS_EXECUTE: case T_TLB_MISS_READ: case T_TLB_MISS_WRITE: ==== //depot/projects/avr32/src/sys/dev/ate/if_ate.c#2 (text) ==== @@ -23,18 +23,14 @@ * SUCH DAMAGE. */ -/* TODO: (in no order) +/* TODO * - * 8) Need to sync busdma goo in atestop - * 9) atestop should maybe free the mbufs? - * - * 1) detach - * 2) Free dma setup - * 3) Turn on the clock in pmc? Turn off? + * 1) Turn on the clock in pmc? Turn off? + * 2) GPIO initializtion in board setup code. */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: src/sys/arm/at91/if_ate.c,v 1.30 2008/11/25 00:14:49 imp Exp $"); +__FBSDID("$FreeBSD: src/sys/arm/at91/if_ate.c,v 1.37 2009/05/13 21:01:10 stas Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -69,86 +65,116 @@ #include <dev/mii/mii.h> #include <dev/mii/miivar.h> -#include <arm/at91/if_atereg.h> +#include "if_atereg.h" #include "miibus_if.h" -#define ATE_MAX_TX_BUFFERS 2 /* We have ping-pong tx buffers */ -#define ATE_MAX_RX_BUFFERS 64 + +/* + * Driver-specific flags. + */ +#define ATE_FLAG_DETACHING 0x01 +#define ATE_FLAG_MULTICAST 0x02 struct ate_softc { - struct ifnet *ifp; /* ifnet pointer */ - struct mtx sc_mtx; /* basically a perimeter lock */ - device_t dev; /* Myself */ - device_t miibus; /* My child miibus */ - void *intrhand; /* Interrupt handle */ - struct resource *irq_res; /* IRQ resource */ + struct ifnet *ifp; /* ifnet pointer */ + struct mtx sc_mtx; /* Basically a perimeter lock */ + device_t dev; /* Myself */ + device_t miibus; /* My child miibus */ + struct resource *irq_res; /* IRQ resource */ struct resource *mem_res; /* Memory resource */ - struct callout tick_ch; /* Tick callout */ - bus_dma_tag_t mtag; /* bus dma tag for mbufs */ - bus_dmamap_t tx_map[ATE_MAX_TX_BUFFERS]; - struct mbuf *sent_mbuf[ATE_MAX_TX_BUFFERS]; /* Sent mbufs */ - bus_dma_tag_t rxtag; - bus_dmamap_t rx_map[ATE_MAX_RX_BUFFERS]; - void *rx_buf[ATE_MAX_RX_BUFFERS]; /* RX buffer space */ - int rx_buf_ptr; - bus_dma_tag_t rx_desc_tag; - bus_dmamap_t rx_desc_map; - int txcur; /* current tx map pointer */ - bus_addr_t rx_desc_phys; - eth_rx_desc_t *rx_descs; - int use_rmii; - struct ifmib_iso_8802_3 mibdata; /* stuff for network mgmt */ + struct callout tick_ch; /* Tick callout */ + struct ifmib_iso_8802_3 mibdata; /* Stuff for network mgmt */ + +#ifdef ATE_EMACB + bus_dma_tag_t tx_desc_tag; + bus_dmamap_t tx_desc_map; + eth_tx_desc_t *tx_descs; + bus_addr_t tx_desc_phys; +#endif + struct mbuf *sent_mbuf[ATE_MAX_TX_BUFFERS]; /* Sent mbufs */ + bus_dma_tag_t mtag; /* bus dma tag for mbufs */ + bus_dmamap_t tx_map[ATE_MAX_TX_BUFFERS]; + int txcur; /* Current TX map pointer */ + int tx_clean_ptr; /* Last TX map entry we cleaned */ + + bus_dma_tag_t rxtag; + bus_dma_tag_t rx_desc_tag; + bus_dmamap_t rx_desc_map; + bus_dmamap_t rx_map[ATE_MAX_RX_BUFFERS]; + bus_addr_t rx_desc_phys; + eth_rx_desc_t *rx_descs; + void *rx_buf[ATE_MAX_RX_BUFFERS]; /* RX buffer space */ + int rx_buf_ptr; + + void *intrhand; /* Interrupt handle */ + int flags; + int if_flags; + int use_rmii; }; static inline uint32_t RD4(struct ate_softc *sc, bus_size_t off) { - return bus_read_4(sc->mem_res, off); + + return (bus_read_4(sc->mem_res, off)); } static inline void WR4(struct ate_softc *sc, bus_size_t off, uint32_t val) { + bus_write_4(sc->mem_res, off, val); } -#define ATE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) +static inline void +BARRIER(struct ate_softc *sc, bus_size_t off, bus_size_t len, int flags) +{ + + bus_barrier(sc->mem_res, off, len, flags); +} + +#define ATE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) #define ATE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) -#define ATE_LOCK_INIT(_sc) \ - mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \ +#define ATE_LOCK_INIT(_sc) \ + mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \ MTX_NETWORK_LOCK, MTX_DEF) -#define ATE_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); -#define ATE_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); -#define ATE_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); +#define ATE_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); +#define ATE_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); +#define ATE_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); static devclass_t ate_devclass; -/* ifnet entry points */ +/* + * ifnet entry points. + */ +static void ateinit_locked(void *); +static void atestart_locked(struct ifnet *); -static void ateinit_locked(void *); -static void atestart_locked(struct ifnet *); +static void ateinit(void *); +static void atestart(struct ifnet *); +static void atestop(struct ate_softc *); +static int ateioctl(struct ifnet * ifp, u_long, caddr_t); -static void ateinit(void *); -static void atestart(struct ifnet *); -static void atestop(struct ate_softc *); -static int ateioctl(struct ifnet * ifp, u_long, caddr_t); +/* + * Bus entry points. + */ +static int ate_probe(device_t dev); +static int ate_attach(device_t dev); +static int ate_detach(device_t dev); +static void ate_intr(void *); -/* bus entry points */ - -static int ate_probe(device_t dev); -static int ate_attach(device_t dev); -static int ate_detach(device_t dev); -static void ate_intr(void *); - -/* helper routines */ -static int ate_activate(device_t dev); -static void ate_deactivate(device_t dev); -static int ate_ifmedia_upd(struct ifnet *ifp); -static void ate_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr); -static int ate_get_mac(struct ate_softc *sc, u_char *eaddr); -static void ate_set_mac(struct ate_softc *sc, u_char *eaddr); +/* + * Helper routines. + */ +static int ate_activate(device_t dev); +static void ate_deactivate(struct ate_softc *sc); +static int ate_ifmedia_upd(struct ifnet *ifp); +static void ate_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr); +static int ate_get_mac(struct ate_softc *sc, u_char *eaddr); +static void ate_set_mac(struct ate_softc *sc, u_char *eaddr); +static void ate_rxfilter(struct ate_softc *sc); /* * The AT91 family of products has the ethernet called EMAC. However, @@ -159,6 +185,7 @@ static int ate_probe(device_t dev) { + device_set_desc(dev, "EMAC"); return (0); } @@ -166,20 +193,50 @@ static int ate_attach(device_t dev) { - struct ate_softc *sc = device_get_softc(dev); + struct ate_softc *sc; struct ifnet *ifp = NULL; struct sysctl_ctx_list *sctx; struct sysctl_oid *soid; - int err; u_char eaddr[ETHER_ADDR_LEN]; uint32_t rnd; + int rid, err; + sc = device_get_softc(dev); sc->dev = dev; + ATE_LOCK_INIT(sc); + + /* + * Allocate resources. + */ + rid = 0; + sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + if (sc->mem_res == NULL) { + device_printf(dev, "could not allocate memory resources.\n"); + err = ENOMEM; + goto out; + } + rid = 0; + sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_ACTIVE); + if (sc->irq_res == NULL) { + device_printf(dev, "could not allocate interrupt resources.\n"); + err = ENOMEM; + goto out; + } + err = ate_activate(dev); if (err) goto out; + /* + * RMII bit is stored in USRIO and inverted in EMACB + */ +#ifdef ATE_EMACB + sc->use_rmii = (RD4(sc, ETH_CFG) & ETH_USRIO_RMII) != ETH_USRIO_RMII; +#else sc->use_rmii = (RD4(sc, ETH_CFG) & ETH_CFG_RMII) == ETH_CFG_RMII; +#endif /* Sysctls */ sctx = device_get_sysctl_ctx(dev); @@ -187,9 +244,10 @@ SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "rmii", CTLFLAG_RD, &sc->use_rmii, 0, "rmii in use"); - /* calling atestop before ifp is set is OK */ + /* Calling atestop before ifp is set is OK. */ + ATE_LOCK(sc); atestop(sc); - ATE_LOCK_INIT(sc); + ATE_UNLOCK(sc); callout_init_mtx(&sc->tick_ch, &sc->sc_mtx, 0); if ((err = ate_get_mac(sc, eaddr)) != 0) { @@ -213,7 +271,6 @@ eaddr[4] = (rnd >> 8) & 0xff; eaddr[5] = rnd & 0xff; } - ate_set_mac(sc, eaddr); sc->ifp = ifp = if_alloc(IFT_ETHER); if (mii_phy_probe(dev, &sc->miibus, ate_ifmedia_upd, ate_ifmedia_sts)) { @@ -226,7 +283,7 @@ if_initname(ifp, device_get_name(dev), device_get_unit(dev)); ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_capabilities |= IFCAP_VLAN_MTU; - ifp->if_capenable |= IFCAP_VLAN_MTU; /* the hw bits already set */ + ifp->if_capenable |= IFCAP_VLAN_MTU; /* The hw bits already set. */ ifp->if_start = atestart; ifp->if_ioctl = ateioctl; ifp->if_init = ateinit; @@ -238,34 +295,74 @@ ifp->if_linkmib = &sc->mibdata; ifp->if_linkmiblen = sizeof(sc->mibdata); sc->mibdata.dot3Compliance = DOT3COMPLIANCE_COLLS; + sc->if_flags = ifp->if_flags; ether_ifattach(ifp, eaddr); /* - * Activate the interrupt + * Activate the interrupt. */ err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE, NULL, ate_intr, sc, &sc->intrhand); if (err) { + device_printf(dev, "could not establish interrupt handler.\n"); ether_ifdetach(ifp); - ATE_LOCK_DESTROY(sc); + goto out; } -out:; + +out: if (err) - ate_deactivate(dev); - if (err && ifp) - if_free(ifp); + ate_detach(dev); return (err); } static int ate_detach(device_t dev) { - return EBUSY; /* XXX TODO(1) */ + struct ate_softc *sc; + struct ifnet *ifp; + + sc = device_get_softc(dev); + KASSERT(sc != NULL, ("[ate: %d]: sc is NULL", __LINE__)); + ifp = sc->ifp; + if (device_is_attached(dev)) { + ATE_LOCK(sc); + sc->flags |= ATE_FLAG_DETACHING; + atestop(sc); + ATE_UNLOCK(sc); + callout_drain(&sc->tick_ch); + ether_ifdetach(ifp); + } + if (sc->miibus != NULL) { + device_delete_child(dev, sc->miibus); + sc->miibus = NULL; + } + bus_generic_detach(sc->dev); + ate_deactivate(sc); + if (sc->intrhand != NULL) { + bus_teardown_intr(dev, sc->irq_res, sc->intrhand); + sc->intrhand = NULL; + } + if (ifp != NULL) { + if_free(ifp); + sc->ifp = NULL; + } + if (sc->mem_res != NULL) { + bus_release_resource(dev, SYS_RES_IOPORT, + rman_get_rid(sc->mem_res), sc->mem_res); + sc->mem_res = NULL; + } + if (sc->irq_res != NULL) { + bus_release_resource(dev, SYS_RES_IRQ, + rman_get_rid(sc->irq_res), sc->irq_res); + sc->irq_res = NULL; + } + ATE_LOCK_DESTROY(sc); + return (0); } static void -ate_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) +ate_rx_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) { struct ate_softc *sc; @@ -275,7 +372,38 @@ sc->rx_desc_phys = segs[0].ds_addr; } +#ifdef ATE_EMACB +static void +ate_tx_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) +{ + struct ate_softc *sc; + + if (error != 0) + return; + sc = (struct ate_softc *)arg; + sc->tx_desc_phys = segs[0].ds_addr; +} + static void +ate_load_tx_buf(void *arg, bus_dma_segment_t *segs, int nsegs, bus_size_t mapsize, int error) +{ + struct ate_softc *sc; + + if (error != 0) + return; + sc = (struct ate_softc *)arg; + + KASSERT(nsegs == 1, ("too many segments: %d\n", nsegs)); + KASSERT(mapsize < ATE_MAX_TX_BUFFER_LENGTH, ("Transmit buffer to long")); + + bus_dmamap_sync(sc->tx_desc_tag, sc->tx_desc_map, BUS_DMASYNC_PREWRITE); + sc->tx_descs[sc->txcur].addr = segs[0].ds_addr; + sc->tx_descs[sc->txcur].status = mapsize | ETH_TX_DESC_LAST; + bus_dmamap_sync(sc->tx_desc_tag, sc->tx_desc_map, BUS_DMASYNC_POSTWRITE); +} +#endif /* ATE_EMACB */ + +static void ate_load_rx_buf(void *arg, bus_dma_segment_t *segs, int nsegs, int error) { struct ate_softc *sc; @@ -307,26 +435,39 @@ * of different MAC chips use this method (or the reverse the bits) * method. */ -static void +static int ate_setmcast(struct ate_softc *sc) { uint32_t index; uint32_t mcaf[2]; u_char *af = (u_char *) mcaf; struct ifmultiaddr *ifma; + struct ifnet *ifp; + + ifp = sc->ifp; + + if ((ifp->if_flags & IFF_PROMISC) != 0) + return (0); + if ((ifp->if_flags & IFF_ALLMULTI) != 0) { + WR4(sc, ETH_HSL, 0xffffffff); + WR4(sc, ETH_HSH, 0xffffffff); + return (1); + } + /* + * Compute the multicast hash. + */ mcaf[0] = 0; mcaf[1] = 0; - - IF_ADDR_LOCK(sc->ifp); - TAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) { + IF_ADDR_LOCK(ifp); + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; index = ether_crc32_be(LLADDR((struct sockaddr_dl *) ifma->ifma_addr), ETHER_ADDR_LEN) >> 26; af[index >> 3] |= 1 << (index & 7); } - IF_ADDR_UNLOCK(sc->ifp); + IF_ADDR_UNLOCK(ifp); /* * Write the hash to the hash register. This card can also @@ -337,44 +478,68 @@ */ WR4(sc, ETH_HSL, mcaf[0]); WR4(sc, ETH_HSH, mcaf[1]); + return (mcaf[0] || mcaf[1]); } static int ate_activate(device_t dev) { struct ate_softc *sc; - int rid, err, i; + int err, i; sc = device_get_softc(dev); - rid = 0; - sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, - RF_ACTIVE); - if (sc->mem_res == NULL) - goto errout; - rid = 0; - sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, - RF_ACTIVE); - if (sc->irq_res == NULL) - goto errout; /* - * Allocate DMA tags and maps + * Allocate DMA tags and maps. */ err = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 1, MCLBYTES, 0, busdma_lock_mutex, &sc->sc_mtx, &sc->mtag); if (err != 0) goto errout; + for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) { err = bus_dmamap_create(sc->mtag, 0, &sc->tx_map[i]); if (err != 0) goto errout; } - /* - * Allocate our Rx buffers. This chip has a rx structure that's filled - * in - */ - + +#ifdef ATE_EMACB + /* + * DMA tag and map for the TX descriptors. + */ + err = bus_dma_tag_create(bus_get_dma_tag(dev), sizeof(eth_tx_desc_t), + 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + ATE_MAX_TX_BUFFERS * sizeof(eth_tx_desc_t), 1, + ATE_MAX_TX_BUFFERS * sizeof(eth_tx_desc_t), 0, busdma_lock_mutex, + &sc->sc_mtx, &sc->tx_desc_tag); + if (err != 0) + goto errout; + if (bus_dmamem_alloc(sc->tx_desc_tag, (void **)&sc->tx_descs, + BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->tx_desc_map) != 0) + goto errout; + if (bus_dmamap_load(sc->tx_desc_tag, sc->tx_desc_map, + sc->tx_descs, ATE_MAX_TX_BUFFERS * sizeof(eth_tx_desc_t), + ate_tx_getaddr, sc, 0) != 0) + goto errout; + + /* + * Init transmit buffer queue descriptors + */ + for (i = 0; i < ATE_MAX_TX_BUFFERS - 1; i++) { + sc->tx_descs[i].addr = 0; + sc->tx_descs[i].status = ETH_TX_DESC_CPU_OWNER; + } + sc->tx_descs[ATE_MAX_TX_BUFFERS - 1].addr = 0; + sc->tx_descs[ATE_MAX_TX_BUFFERS - 1].status = ETH_TX_DESC_CPU_OWNER | + ETH_TX_DESC_WRAP; + + /* Flush the memory for the EMAC tx descriptor. */ + bus_dmamap_sync(sc->tx_desc_tag, sc->tx_desc_map, BUS_DMASYNC_PREWRITE); + /* Write the descriptor queue address. */ + WR4(sc, ETH_TBQP, sc->tx_desc_phys); +#endif + /* * Allocate DMA tags and maps for RX. */ @@ -384,7 +549,9 @@ if (err != 0) goto errout; - /* Dma TAG and MAP for the rx descriptors. */ + /* + * DMA tag and map for the RX descriptors. + */ err = bus_dma_tag_create(bus_get_dma_tag(dev), sizeof(eth_rx_desc_t), 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, ATE_MAX_RX_BUFFERS * sizeof(eth_rx_desc_t), 1, @@ -397,83 +564,114 @@ goto errout; if (bus_dmamap_load(sc->rx_desc_tag, sc->rx_desc_map, sc->rx_descs, ATE_MAX_RX_BUFFERS * sizeof(eth_rx_desc_t), - ate_getaddr, sc, 0) != 0) + ate_rx_getaddr, sc, 0) != 0) goto errout; - /* XXX TODO(5) Put this in ateinit_locked? */ + + /* + * Allocate our RX buffers. This chip has a RX structure that's filled + * in. + */ for (i = 0; i < ATE_MAX_RX_BUFFERS; i++) { sc->rx_buf_ptr = i; if (bus_dmamem_alloc(sc->rxtag, (void **)&sc->rx_buf[i], BUS_DMA_NOWAIT, &sc->rx_map[i]) != 0) goto errout; if (bus_dmamap_load(sc->rxtag, sc->rx_map[i], sc->rx_buf[i], - MCLBYTES, ate_load_rx_buf, sc, 0) != 0) + ATE_MAX_RX_BUFFER_LENGTH, ate_load_rx_buf, sc, 0) != 0) goto errout; } sc->rx_buf_ptr = 0; - /* Flush the memory for the EMAC rx descriptor */ + /* Flush the memory for the EMAC rx descriptor. */ bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_PREWRITE); /* Write the descriptor queue address. */ WR4(sc, ETH_RBQP, sc->rx_desc_phys); return (0); + errout: - ate_deactivate(dev); return (ENOMEM); } static void -ate_deactivate(device_t dev) +ate_deactivate(struct ate_softc *sc) { - struct ate_softc *sc; + int i; - sc = device_get_softc(dev); - /* XXX TODO(2) teardown busdma junk, below from fxp -- customize */ -#if 0 - if (sc->fxp_mtag) { - for (i = 0; i < FXP_NRFABUFS; i++) { - rxp = &sc->fxp_desc.rx_list[i]; - if (rxp->rx_mbuf != NULL) { - bus_dmamap_sync(sc->fxp_mtag, rxp->rx_map, - BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->fxp_mtag, rxp->rx_map); - m_freem(rxp->rx_mbuf); + KASSERT(sc != NULL, ("[ate, %d]: sc is NULL!", __LINE__)); +#ifdef ATE_EMACB + if (sc->tx_desc_tag != NULL) { + if (sc->tx_descs != NULL) { + if (sc->tx_desc_phys != 0) { + bus_dmamap_sync(sc->tx_desc_tag, + sc->tx_desc_map, BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc->tx_desc_tag, + sc->tx_desc_map); + sc->tx_desc_phys = 0; } - bus_dmamap_destroy(sc->fxp_mtag, rxp->rx_map); } - bus_dmamap_destroy(sc->fxp_mtag, sc->spare_map); - for (i = 0; i < FXP_NTXCB; i++) { - txp = &sc->fxp_desc.tx_list[i]; - if (txp->tx_mbuf != NULL) { - bus_dmamap_sync(sc->fxp_mtag, txp->tx_map, + } +#endif + if (sc->mtag != NULL) { + for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) { + if (sc->sent_mbuf[i] != NULL) { + bus_dmamap_sync(sc->mtag, sc->tx_map[i], BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->fxp_mtag, txp->tx_map); - m_freem(txp->tx_mbuf); + bus_dmamap_unload(sc->mtag, sc->tx_map[i]); + m_freem(sc->sent_mbuf[i]); } - bus_dmamap_destroy(sc->fxp_mtag, txp->tx_map); + bus_dmamap_destroy(sc->mtag, sc->tx_map[i]); + sc->sent_mbuf[i] = NULL; + sc->tx_map[i] = NULL; } - bus_dma_tag_destroy(sc->fxp_mtag); + bus_dma_tag_destroy(sc->mtag); + } +#ifdef ATE_EMACB + if (sc->tx_desc_tag != NULL) { + if (sc->tx_descs != NULL) + bus_dmamem_free(sc->tx_desc_tag, sc->tx_descs, + sc->tx_desc_map); + bus_dma_tag_destroy(sc->tx_desc_tag); + sc->tx_descs = NULL; + sc->tx_desc_tag = NULL; } - if (sc->fxp_stag) - bus_dma_tag_destroy(sc->fxp_stag); - if (sc->cbl_tag) - bus_dma_tag_destroy(sc->cbl_tag); - if (sc->mcs_tag) - bus_dma_tag_destroy(sc->mcs_tag); #endif - if (sc->intrhand) - bus_teardown_intr(dev, sc->irq_res, sc->intrhand); - sc->intrhand = 0; - bus_generic_detach(sc->dev); - if (sc->miibus) - device_delete_child(sc->dev, sc->miibus); - if (sc->mem_res) - bus_release_resource(dev, SYS_RES_IOPORT, - rman_get_rid(sc->mem_res), sc->mem_res); - sc->mem_res = 0; - if (sc->irq_res) - bus_release_resource(dev, SYS_RES_IRQ, - rman_get_rid(sc->irq_res), sc->irq_res); - sc->irq_res = 0; - return; + if (sc->rx_desc_tag != NULL) { + if (sc->rx_descs != NULL) { + if (sc->rx_desc_phys != 0) { + bus_dmamap_sync(sc->rx_desc_tag, + sc->rx_desc_map, BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc->rx_desc_tag, + sc->rx_desc_map); + sc->rx_desc_phys = 0; + } + } + } + if (sc->rxtag != NULL) { + for (i = 0; i < ATE_MAX_RX_BUFFERS; i++) { + if (sc->rx_buf[i] != NULL) { + if (sc->rx_descs[i].addr != 0) { + bus_dmamap_sync(sc->rxtag, + sc->rx_map[i], + BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc->rxtag, + sc->rx_map[i]); + sc->rx_descs[i].addr = 0; + } + bus_dmamem_free(sc->rxtag, sc->rx_buf[i], + sc->rx_map[i]); + sc->rx_buf[i] = NULL; + sc->rx_map[i] = NULL; + } + } + bus_dma_tag_destroy(sc->rxtag); + } + if (sc->rx_desc_tag != NULL) { + if (sc->rx_descs != NULL) + bus_dmamem_free(sc->rx_desc_tag, sc->rx_descs, + sc->rx_desc_map); + bus_dma_tag_destroy(sc->rx_desc_tag); + sc->rx_descs = NULL; + sc->rx_desc_tag = NULL; + } } /* @@ -512,18 +710,19 @@ static void ate_stat_update(struct ate_softc *sc, int active) { + uint32_t reg; + /* * The speed and full/half-duplex state needs to be reflected * in the ETH_CFG register. */ - if (IFM_SUBTYPE(active) == IFM_10_T) - WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) & ~ETH_CFG_SPD); - else - WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_SPD); + reg = RD4(sc, ETH_CFG); + reg &= ~(ETH_CFG_SPD | ETH_CFG_FD); + if (IFM_SUBTYPE(active) != IFM_10_T) + reg |= ETH_CFG_SPD; if (active & IFM_FDX) - WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_FD); - else - WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) & ~ETH_CFG_FD); + reg |= ETH_CFG_FD; + WR4(sc, ETH_CFG, reg); } static void @@ -580,8 +779,9 @@ sc->mibdata.dot3StatsCarrierSenseErrors += RD4(sc, ETH_CSE); sc->mibdata.dot3StatsFrameTooLongs += RD4(sc, ETH_ELR); sc->mibdata.dot3StatsInternalMacReceiveErrors += RD4(sc, ETH_DRFC); + /* - * not sure where to lump these, so count them against the errors + * Not sure where to lump these, so count them against the errors * for the interface. */ sc->ifp->if_oerrors += RD4(sc, ETH_TUE); @@ -597,6 +797,7 @@ static void ate_set_mac(struct ate_softc *sc, u_char *eaddr) { + WR4(sc, ETH_SA1L, (eaddr[3] << 24) | (eaddr[2] << 16) | (eaddr[1] << 8) | eaddr[0]); WR4(sc, ETH_SA1H, (eaddr[5] << 8) | (eaddr[4])); @@ -629,31 +830,99 @@ } return (ENXIO); } +#ifdef ATE_EMACB +/* + * Not sure if this is the best way to create the rx mbuf, but it seems to work + */ +static struct mbuf * +ate_rx_frame(struct ate_softc *sc, int start, int end, int len) +{ + int at, i, clen; + struct mbuf *m; + m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + if (m == NULL) { + device_printf(sc->dev, "Unable to alloc mbuf\n"); + return (NULL); + } + m->m_pkthdr.rcvif = sc->ifp; + + at = 0; + for (i = start; len > 0; i = (i + 1) % ATE_MAX_RX_BUFFERS) { + clen = (len > ATE_MAX_RX_BUFFER_LENGTH) ? ATE_MAX_RX_BUFFER_LENGTH : len; + len -= ATE_MAX_RX_BUFFER_LENGTH; + + bus_dmamap_sync(sc->rxtag, sc->rx_map[i], + BUS_DMASYNC_POSTREAD); + m_copyback(m, at, clen, sc->rx_buf[i]); + + bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, + BUS_DMASYNC_PREWRITE); + sc->rx_descs[i].addr &= ~ETH_CPU_OWNER; + bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_sync(sc->rxtag, sc->rx_map[i], + BUS_DMASYNC_PREREAD); + + at += clen; + } + sc->rx_buf_ptr = i; + return (m); +} +#endif + static void ate_intr(void *xsc) { struct ate_softc *sc = xsc; struct ifnet *ifp = sc->ifp; - int status; + struct mbuf *mb; + void *bp; + uint32_t status, reg, rx_stat, frame_len; + int frame_start; int i; - void *bp; - struct mbuf *mb; - uint32_t rx_stat; + status = RD4(sc, ETH_ISR); if (status == 0) return; + if (status & ETH_ISR_RCOM) { bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_POSTREAD); +#ifdef ATE_EMACB + i = sc->rx_buf_ptr; + frame_start = -1; + while (sc->rx_descs[i].addr & ETH_CPU_OWNER && i != (sc->rx_buf_ptr - 1)) { + rx_stat = sc->rx_descs[i].status; + if ((rx_stat & ETH_FRAME_START)) { + KASSERT(frame_start == -1, ("New frame with out finishing last")); + frame_start = i; + } + if ((rx_stat & ETH_FRAME_END)) { + frame_len = rx_stat & ETH_LEN_MASK; + KASSERT(frame_start != -1, ("End of frame without begining")); + KASSERT(frame_len != 0, ("Zero length frame")); + + WR4(sc, ETH_RSR, RD4(sc, ETH_RSR)); + mb = ate_rx_frame(sc, frame_start, i, frame_len); + if (mb != NULL) { + frame_start = -1; + ifp->if_ipackets++; + (*ifp->if_input)(ifp, mb); + } + } + i = (i + 1) % ATE_MAX_RX_BUFFERS; + } +#else /* ATE_EMACB */ while (sc->rx_descs[sc->rx_buf_ptr].addr & ETH_CPU_OWNER) { i = sc->rx_buf_ptr; sc->rx_buf_ptr = (i + 1) % ATE_MAX_RX_BUFFERS; bp = sc->rx_buf[i]; rx_stat = sc->rx_descs[i].status; if ((rx_stat & ETH_LEN_MASK) == 0) { - printf("ignoring bogus 0 len packet\n"); + if (bootverbose) + device_printf(sc->dev, "ignoring bogus zero-length packet\n"); bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_PREWRITE); sc->rx_descs[i].addr &= ~ETH_CPU_OWNER; @@ -681,19 +950,47 @@ BUS_DMASYNC_POSTWRITE); bus_dmamap_sync(sc->rxtag, sc->rx_map[i], BUS_DMASYNC_PREREAD); + if (mb != NULL) { ifp->if_ipackets++; (*ifp->if_input)(ifp, mb); } - } +#endif /* !ATE_EMACB */ >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905301601.n4UG15lX065795>