PERFORCE change 163091 for review
Arnar Mar Sig
antab at FreeBSD.org
Sat May 30 16:01:07 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=163091
Change 163091 by antab at 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) <<<
More information about the p4-projects
mailing list