summaryrefslogtreecommitdiff
path: root/sys/arm
diff options
context:
space:
mode:
authorEmmanuel Vadot <manu@FreeBSD.org>2020-11-20 11:29:37 +0000
committerEmmanuel Vadot <manu@FreeBSD.org>2020-11-20 11:29:37 +0000
commit5fba90649ad564a5820877c7448383847f7f20e8 (patch)
tree8b3de50ef182eefed8a85719c6a1324975929db2 /sys/arm
parentf88e0af64abb8317c67fa075125b1943a7f42997 (diff)
downloadsrc-test2-5fba90649ad564a5820877c7448383847f7f20e8.tar.gz
src-test2-5fba90649ad564a5820877c7448383847f7f20e8.zip
if_awg: Reorder functions and sort them by usage
No functional changes intended
Notes
Notes: svn path=/head/; revision=367883
Diffstat (limited to 'sys/arm')
-rw-r--r--sys/arm/allwinner/if_awg.c963
1 files changed, 502 insertions, 461 deletions
diff --git a/sys/arm/allwinner/if_awg.c b/sys/arm/allwinner/if_awg.c
index 5dc518fa8b2f..1d713a8ed50a 100644
--- a/sys/arm/allwinner/if_awg.c
+++ b/sys/arm/allwinner/if_awg.c
@@ -217,6 +217,9 @@ static struct resource_spec awg_spec[] = {
};
static void awg_txeof(struct awg_softc *sc);
+static void awg_start_locked(struct awg_softc *sc);
+
+static void awg_tick(void *softc);
static int awg_parse_delay(device_t dev, uint32_t *tx_delay,
uint32_t *rx_delay);
@@ -225,6 +228,10 @@ static void syscon_write_emac_clk_reg(device_t dev, uint32_t val);
static phandle_t awg_get_phy_node(device_t dev);
static bool awg_has_internal_phy(device_t dev);
+/*
+ * MII functions
+ */
+
static int
awg_miibus_readreg(device_t dev, int phy, int reg)
{
@@ -346,6 +353,10 @@ awg_miibus_statchg(device_t dev)
WR4(sc, EMAC_TX_FLOW_CTL, val);
}
+/*
+ * Media functions
+ */
+
static void
awg_media_status(if_t ifp, struct ifmediareq *ifmr)
{
@@ -379,6 +390,217 @@ awg_media_change(if_t ifp)
return (error);
}
+/*
+ * Core functions
+ */
+
+/* Bit Reversal - http://aggregate.org/MAGIC/#Bit%20Reversal */
+static uint32_t
+bitrev32(uint32_t x)
+{
+ x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
+ x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
+ x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
+ x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
+
+ return (x >> 16) | (x << 16);
+}
+
+static u_int
+awg_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t crc, hashreg, hashbit, *hash = arg;
+
+ crc = ether_crc32_le(LLADDR(sdl), ETHER_ADDR_LEN) & 0x7f;
+ crc = bitrev32(~crc) >> 26;
+ hashreg = (crc >> 5);
+ hashbit = (crc & 0x1f);
+ hash[hashreg] |= (1 << hashbit);
+
+ return (1);
+}
+
+static void
+awg_setup_rxfilter(struct awg_softc *sc)
+{
+ uint32_t val, hash[2], machi, maclo;
+ uint8_t *eaddr;
+ if_t ifp;
+
+ AWG_ASSERT_LOCKED(sc);
+
+ ifp = sc->ifp;
+ val = 0;
+ hash[0] = hash[1] = 0;
+
+ if (if_getflags(ifp) & IFF_PROMISC)
+ val |= DIS_ADDR_FILTER;
+ else if (if_getflags(ifp) & IFF_ALLMULTI) {
+ val |= RX_ALL_MULTICAST;
+ hash[0] = hash[1] = ~0;
+ } else if (if_foreach_llmaddr(ifp, awg_hash_maddr, hash) > 0)
+ val |= HASH_MULTICAST;
+
+ /* Write our unicast address */
+ eaddr = IF_LLADDR(ifp);
+ machi = (eaddr[5] << 8) | eaddr[4];
+ maclo = (eaddr[3] << 24) | (eaddr[2] << 16) | (eaddr[1] << 8) |
+ (eaddr[0] << 0);
+ WR4(sc, EMAC_ADDR_HIGH(0), machi);
+ WR4(sc, EMAC_ADDR_LOW(0), maclo);
+
+ /* Multicast hash filters */
+ WR4(sc, EMAC_RX_HASH_0, hash[1]);
+ WR4(sc, EMAC_RX_HASH_1, hash[0]);
+
+ /* RX frame filter config */
+ WR4(sc, EMAC_RX_FRM_FLT, val);
+}
+
+static void
+awg_setup_core(struct awg_softc *sc)
+{
+ uint32_t val;
+
+ AWG_ASSERT_LOCKED(sc);
+ /* Configure DMA burst length and priorities */
+ val = awg_burst_len << BASIC_CTL_BURST_LEN_SHIFT;
+ if (awg_rx_tx_pri)
+ val |= BASIC_CTL_RX_TX_PRI;
+ WR4(sc, EMAC_BASIC_CTL_1, val);
+
+}
+
+static void
+awg_enable_mac(struct awg_softc *sc, bool enable)
+{
+ uint32_t tx, rx;
+
+ AWG_ASSERT_LOCKED(sc);
+
+ tx = RD4(sc, EMAC_TX_CTL_0);
+ rx = RD4(sc, EMAC_RX_CTL_0);
+ if (enable) {
+ tx |= TX_EN;
+ rx |= RX_EN | CHECK_CRC;
+ } else {
+ tx &= ~TX_EN;
+ rx &= ~(RX_EN | CHECK_CRC);
+ }
+
+ WR4(sc, EMAC_TX_CTL_0, tx);
+ WR4(sc, EMAC_RX_CTL_0, rx);
+}
+
+static void
+awg_get_eaddr(device_t dev, uint8_t *eaddr)
+{
+ struct awg_softc *sc;
+ uint32_t maclo, machi, rnd;
+ u_char rootkey[16];
+ uint32_t rootkey_size;
+
+ sc = device_get_softc(dev);
+
+ machi = RD4(sc, EMAC_ADDR_HIGH(0)) & 0xffff;
+ maclo = RD4(sc, EMAC_ADDR_LOW(0));
+
+ rootkey_size = sizeof(rootkey);
+ if (maclo == 0xffffffff && machi == 0xffff) {
+ /* MAC address in hardware is invalid, create one */
+ if (aw_sid_get_fuse(AW_SID_FUSE_ROOTKEY, rootkey,
+ &rootkey_size) == 0 &&
+ (rootkey[3] | rootkey[12] | rootkey[13] | rootkey[14] |
+ rootkey[15]) != 0) {
+ /* MAC address is derived from the root key in SID */
+ maclo = (rootkey[13] << 24) | (rootkey[12] << 16) |
+ (rootkey[3] << 8) | 0x02;
+ machi = (rootkey[15] << 8) | rootkey[14];
+ } else {
+ /* Create one */
+ rnd = arc4random();
+ maclo = 0x00f2 | (rnd & 0xffff0000);
+ machi = rnd & 0xffff;
+ }
+ }
+
+ eaddr[0] = maclo & 0xff;
+ eaddr[1] = (maclo >> 8) & 0xff;
+ eaddr[2] = (maclo >> 16) & 0xff;
+ eaddr[3] = (maclo >> 24) & 0xff;
+ eaddr[4] = machi & 0xff;
+ eaddr[5] = (machi >> 8) & 0xff;
+}
+
+/*
+ * DMA functions
+ */
+
+static void
+awg_enable_dma_intr(struct awg_softc *sc)
+{
+ /* Enable interrupts */
+ WR4(sc, EMAC_INT_EN, RX_INT_EN | TX_INT_EN | TX_BUF_UA_INT_EN);
+}
+
+static void
+awg_disable_dma_intr(struct awg_softc *sc)
+{
+ /* Disable interrupts */
+ WR4(sc, EMAC_INT_EN, 0);
+}
+
+static void
+awg_init_dma(struct awg_softc *sc)
+{
+ uint32_t val;
+
+ AWG_ASSERT_LOCKED(sc);
+
+ /* Enable interrupts */
+#ifdef DEVICE_POLLING
+ if ((if_getcapenable(sc->ifp) & IFCAP_POLLING) == 0)
+ awg_enable_dma_intr(sc);
+ else
+ awg_disable_dma_intr(sc);
+#else
+ awg_enable_dma_intr(sc);
+#endif
+
+ /* Enable transmit DMA */
+ val = RD4(sc, EMAC_TX_CTL_1);
+ WR4(sc, EMAC_TX_CTL_1, val | TX_DMA_EN | TX_MD | TX_NEXT_FRAME);
+
+ /* Enable receive DMA */
+ val = RD4(sc, EMAC_RX_CTL_1);
+ WR4(sc, EMAC_RX_CTL_1, val | RX_DMA_EN | RX_MD);
+}
+
+static void
+awg_stop_dma(struct awg_softc *sc)
+{
+ uint32_t val;
+
+ AWG_ASSERT_LOCKED(sc);
+
+ /* Stop transmit DMA and flush data in the TX FIFO */
+ val = RD4(sc, EMAC_TX_CTL_1);
+ val &= ~TX_DMA_EN;
+ val |= FLUSH_TX_FIFO;
+ WR4(sc, EMAC_TX_CTL_1, val);
+
+ /* Disable interrupts */
+ awg_disable_dma_intr(sc);
+
+ /* Disable transmit DMA */
+ val = RD4(sc, EMAC_TX_CTL_1);
+ WR4(sc, EMAC_TX_CTL_1, val & ~TX_DMA_EN);
+
+ /* Disable receive DMA */
+ val = RD4(sc, EMAC_RX_CTL_1);
+ WR4(sc, EMAC_RX_CTL_1, val & ~RX_DMA_EN);
+}
+
static int
awg_encap(struct awg_softc *sc, struct mbuf **mp)
{
@@ -560,6 +782,170 @@ awg_newbuf_rx(struct awg_softc *sc, int index)
}
static void
+awg_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+ if (error != 0)
+ return;
+ *(bus_addr_t *)arg = segs[0].ds_addr;
+}
+
+static int
+awg_setup_dma(device_t dev)
+{
+ struct awg_softc *sc;
+ int error, i;
+
+ sc = device_get_softc(dev);
+
+ /* Setup TX ring */
+ error = bus_dma_tag_create(
+ bus_get_dma_tag(dev), /* Parent tag */
+ DESC_ALIGN, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ TX_DESC_SIZE, 1, /* maxsize, nsegs */
+ TX_DESC_SIZE, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->tx.desc_tag);
+ if (error != 0) {
+ device_printf(dev, "cannot create TX descriptor ring tag\n");
+ return (error);
+ }
+
+ error = bus_dmamem_alloc(sc->tx.desc_tag, (void **)&sc->tx.desc_ring,
+ BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->tx.desc_map);
+ if (error != 0) {
+ device_printf(dev, "cannot allocate TX descriptor ring\n");
+ return (error);
+ }
+
+ error = bus_dmamap_load(sc->tx.desc_tag, sc->tx.desc_map,
+ sc->tx.desc_ring, TX_DESC_SIZE, awg_dmamap_cb,
+ &sc->tx.desc_ring_paddr, 0);
+ if (error != 0) {
+ device_printf(dev, "cannot load TX descriptor ring\n");
+ return (error);
+ }
+
+ for (i = 0; i < TX_DESC_COUNT; i++)
+ sc->tx.desc_ring[i].next =
+ htole32(sc->tx.desc_ring_paddr + DESC_OFF(TX_NEXT(i)));
+
+ error = bus_dma_tag_create(
+ bus_get_dma_tag(dev), /* Parent tag */
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ MCLBYTES, TX_MAX_SEGS, /* maxsize, nsegs */
+ MCLBYTES, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->tx.buf_tag);
+ if (error != 0) {
+ device_printf(dev, "cannot create TX buffer tag\n");
+ return (error);
+ }
+
+ sc->tx.queued = 0;
+ for (i = 0; i < TX_DESC_COUNT; i++) {
+ error = bus_dmamap_create(sc->tx.buf_tag, 0,
+ &sc->tx.buf_map[i].map);
+ if (error != 0) {
+ device_printf(dev, "cannot create TX buffer map\n");
+ return (error);
+ }
+ }
+
+ /* Setup RX ring */
+ error = bus_dma_tag_create(
+ bus_get_dma_tag(dev), /* Parent tag */
+ DESC_ALIGN, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ RX_DESC_SIZE, 1, /* maxsize, nsegs */
+ RX_DESC_SIZE, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->rx.desc_tag);
+ if (error != 0) {
+ device_printf(dev, "cannot create RX descriptor ring tag\n");
+ return (error);
+ }
+
+ error = bus_dmamem_alloc(sc->rx.desc_tag, (void **)&sc->rx.desc_ring,
+ BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->rx.desc_map);
+ if (error != 0) {
+ device_printf(dev, "cannot allocate RX descriptor ring\n");
+ return (error);
+ }
+
+ error = bus_dmamap_load(sc->rx.desc_tag, sc->rx.desc_map,
+ sc->rx.desc_ring, RX_DESC_SIZE, awg_dmamap_cb,
+ &sc->rx.desc_ring_paddr, 0);
+ if (error != 0) {
+ device_printf(dev, "cannot load RX descriptor ring\n");
+ return (error);
+ }
+
+ error = bus_dma_tag_create(
+ bus_get_dma_tag(dev), /* Parent tag */
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ MCLBYTES, 1, /* maxsize, nsegs */
+ MCLBYTES, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->rx.buf_tag);
+ if (error != 0) {
+ device_printf(dev, "cannot create RX buffer tag\n");
+ return (error);
+ }
+
+ error = bus_dmamap_create(sc->rx.buf_tag, 0, &sc->rx.buf_spare_map);
+ if (error != 0) {
+ device_printf(dev,
+ "cannot create RX buffer spare map\n");
+ return (error);
+ }
+
+ for (i = 0; i < RX_DESC_COUNT; i++) {
+ sc->rx.desc_ring[i].next =
+ htole32(sc->rx.desc_ring_paddr + DESC_OFF(RX_NEXT(i)));
+
+ error = bus_dmamap_create(sc->rx.buf_tag, 0,
+ &sc->rx.buf_map[i].map);
+ if (error != 0) {
+ device_printf(dev, "cannot create RX buffer map\n");
+ return (error);
+ }
+ sc->rx.buf_map[i].mbuf = NULL;
+ error = awg_newbuf_rx(sc, i);
+ if (error != 0) {
+ device_printf(dev, "cannot create RX buffer\n");
+ return (error);
+ }
+ }
+ bus_dmamap_sync(sc->rx.desc_tag, sc->rx.desc_map,
+ BUS_DMASYNC_PREWRITE);
+
+ /* Write transmit and receive descriptor base address registers */
+ WR4(sc, EMAC_TX_DMA_LIST, sc->tx.desc_ring_paddr);
+ WR4(sc, EMAC_RX_DMA_LIST, sc->rx.desc_ring_paddr);
+
+ return (0);
+}
+
+/*
+ * if_ functions
+ */
+
+static void
awg_start_locked(struct awg_softc *sc)
{
struct mbuf *m;
@@ -617,195 +1003,6 @@ awg_start(if_t ifp)
}
static void
-awg_tick(void *softc)
-{
- struct awg_softc *sc;
- struct mii_data *mii;
- if_t ifp;
- int link;
-
- sc = softc;
- ifp = sc->ifp;
- mii = device_get_softc(sc->miibus);
-
- AWG_ASSERT_LOCKED(sc);
-
- if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0)
- return;
-
- link = sc->link;
- mii_tick(mii);
- if (sc->link && !link)
- awg_start_locked(sc);
-
- callout_reset(&sc->stat_ch, hz, awg_tick, sc);
-}
-
-/* Bit Reversal - http://aggregate.org/MAGIC/#Bit%20Reversal */
-static uint32_t
-bitrev32(uint32_t x)
-{
- x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
- x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
- x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
- x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
-
- return (x >> 16) | (x << 16);
-}
-
-static u_int
-awg_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
-{
- uint32_t crc, hashreg, hashbit, *hash = arg;
-
- crc = ether_crc32_le(LLADDR(sdl), ETHER_ADDR_LEN) & 0x7f;
- crc = bitrev32(~crc) >> 26;
- hashreg = (crc >> 5);
- hashbit = (crc & 0x1f);
- hash[hashreg] |= (1 << hashbit);
-
- return (1);
-}
-
-static void
-awg_setup_rxfilter(struct awg_softc *sc)
-{
- uint32_t val, hash[2], machi, maclo;
- uint8_t *eaddr;
- if_t ifp;
-
- AWG_ASSERT_LOCKED(sc);
-
- ifp = sc->ifp;
- val = 0;
- hash[0] = hash[1] = 0;
-
- if (if_getflags(ifp) & IFF_PROMISC)
- val |= DIS_ADDR_FILTER;
- else if (if_getflags(ifp) & IFF_ALLMULTI) {
- val |= RX_ALL_MULTICAST;
- hash[0] = hash[1] = ~0;
- } else if (if_foreach_llmaddr(ifp, awg_hash_maddr, hash) > 0)
- val |= HASH_MULTICAST;
-
- /* Write our unicast address */
- eaddr = IF_LLADDR(ifp);
- machi = (eaddr[5] << 8) | eaddr[4];
- maclo = (eaddr[3] << 24) | (eaddr[2] << 16) | (eaddr[1] << 8) |
- (eaddr[0] << 0);
- WR4(sc, EMAC_ADDR_HIGH(0), machi);
- WR4(sc, EMAC_ADDR_LOW(0), maclo);
-
- /* Multicast hash filters */
- WR4(sc, EMAC_RX_HASH_0, hash[1]);
- WR4(sc, EMAC_RX_HASH_1, hash[0]);
-
- /* RX frame filter config */
- WR4(sc, EMAC_RX_FRM_FLT, val);
-}
-
-static void
-awg_setup_core(struct awg_softc *sc)
-{
- uint32_t val;
-
- AWG_ASSERT_LOCKED(sc);
- /* Configure DMA burst length and priorities */
- val = awg_burst_len << BASIC_CTL_BURST_LEN_SHIFT;
- if (awg_rx_tx_pri)
- val |= BASIC_CTL_RX_TX_PRI;
- WR4(sc, EMAC_BASIC_CTL_1, val);
-
-}
-
-static void
-awg_enable_mac(struct awg_softc *sc, bool enable)
-{
- uint32_t tx, rx;
-
- AWG_ASSERT_LOCKED(sc);
-
- tx = RD4(sc, EMAC_TX_CTL_0);
- rx = RD4(sc, EMAC_RX_CTL_0);
- if (enable) {
- tx |= TX_EN;
- rx |= RX_EN | CHECK_CRC;
- } else {
- tx &= ~TX_EN;
- rx &= ~(RX_EN | CHECK_CRC);
- }
-
- WR4(sc, EMAC_TX_CTL_0, tx);
- WR4(sc, EMAC_RX_CTL_0, rx);
-}
-
-
-static void
-awg_enable_dma_intr(struct awg_softc *sc)
-{
- /* Enable interrupts */
- WR4(sc, EMAC_INT_EN, RX_INT_EN | TX_INT_EN | TX_BUF_UA_INT_EN);
-}
-
-static void
-awg_disable_dma_intr(struct awg_softc *sc)
-{
- /* Disable interrupts */
- WR4(sc, EMAC_INT_EN, 0);
-}
-
-static void
-awg_init_dma(struct awg_softc *sc)
-{
- uint32_t val;
-
- AWG_ASSERT_LOCKED(sc);
-
- /* Enable interrupts */
-#ifdef DEVICE_POLLING
- if ((if_getcapenable(sc->ifp) & IFCAP_POLLING) == 0)
- awg_enable_dma_intr(sc);
- else
- awg_disable_dma_intr(sc);
-#else
- awg_enable_dma_intr(sc);
-#endif
-
- /* Enable transmit DMA */
- val = RD4(sc, EMAC_TX_CTL_1);
- WR4(sc, EMAC_TX_CTL_1, val | TX_DMA_EN | TX_MD | TX_NEXT_FRAME);
-
- /* Enable receive DMA */
- val = RD4(sc, EMAC_RX_CTL_1);
- WR4(sc, EMAC_RX_CTL_1, val | RX_DMA_EN | RX_MD);
-}
-
-static void
-awg_stop_dma(struct awg_softc *sc)
-{
- uint32_t val;
-
- AWG_ASSERT_LOCKED(sc);
-
- /* Stop transmit DMA and flush data in the TX FIFO */
- val = RD4(sc, EMAC_TX_CTL_1);
- val &= ~TX_DMA_EN;
- val |= FLUSH_TX_FIFO;
- WR4(sc, EMAC_TX_CTL_1, val);
-
- /* Disable interrupts */
- awg_disable_dma_intr(sc);
-
- /* Disable transmit DMA */
- val = RD4(sc, EMAC_TX_CTL_1);
- WR4(sc, EMAC_TX_CTL_1, val & ~TX_DMA_EN);
-
- /* Disable receive DMA */
- val = RD4(sc, EMAC_RX_CTL_1);
- WR4(sc, EMAC_RX_CTL_1, val & ~RX_DMA_EN);
-}
-
-static void
awg_init_locked(struct awg_softc *sc)
{
struct mii_data *mii;
@@ -897,6 +1094,92 @@ awg_stop(struct awg_softc *sc)
}
static int
+awg_ioctl(if_t ifp, u_long cmd, caddr_t data)
+{
+ struct awg_softc *sc;
+ struct mii_data *mii;
+ struct ifreq *ifr;
+ int flags, mask, error;
+
+ sc = if_getsoftc(ifp);
+ mii = device_get_softc(sc->miibus);
+ ifr = (struct ifreq *)data;
+ error = 0;
+
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ AWG_LOCK(sc);
+ if (if_getflags(ifp) & IFF_UP) {
+ if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
+ flags = if_getflags(ifp) ^ sc->if_flags;
+ if ((flags & (IFF_PROMISC|IFF_ALLMULTI)) != 0)
+ awg_setup_rxfilter(sc);
+ } else
+ awg_init_locked(sc);
+ } else {
+ if (if_getdrvflags(ifp) & IFF_DRV_RUNNING)
+ awg_stop(sc);
+ }
+ sc->if_flags = if_getflags(ifp);
+ AWG_UNLOCK(sc);
+ break;
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
+ AWG_LOCK(sc);
+ awg_setup_rxfilter(sc);
+ AWG_UNLOCK(sc);
+ }
+ break;
+ case SIOCSIFMEDIA:
+ case SIOCGIFMEDIA:
+ error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
+ break;
+ case SIOCSIFCAP:
+ mask = ifr->ifr_reqcap ^ if_getcapenable(ifp);
+#ifdef DEVICE_POLLING
+ if (mask & IFCAP_POLLING) {
+ if ((ifr->ifr_reqcap & IFCAP_POLLING) != 0) {
+ error = ether_poll_register(awg_poll, ifp);
+ if (error != 0)
+ break;
+ AWG_LOCK(sc);
+ awg_disable_dma_intr(sc);
+ if_setcapenablebit(ifp, IFCAP_POLLING, 0);
+ AWG_UNLOCK(sc);
+ } else {
+ error = ether_poll_deregister(ifp);
+ AWG_LOCK(sc);
+ awg_enable_dma_intr(sc);
+ if_setcapenablebit(ifp, 0, IFCAP_POLLING);
+ AWG_UNLOCK(sc);
+ }
+ }
+#endif
+ if (mask & IFCAP_VLAN_MTU)
+ if_togglecapenable(ifp, IFCAP_VLAN_MTU);
+ if (mask & IFCAP_RXCSUM)
+ if_togglecapenable(ifp, IFCAP_RXCSUM);
+ if (mask & IFCAP_TXCSUM)
+ if_togglecapenable(ifp, IFCAP_TXCSUM);
+ if ((if_getcapenable(ifp) & IFCAP_TXCSUM) != 0)
+ if_sethwassistbits(ifp, CSUM_IP | CSUM_UDP | CSUM_TCP, 0);
+ else
+ if_sethwassistbits(ifp, 0, CSUM_IP | CSUM_UDP | CSUM_TCP);
+ break;
+ default:
+ error = ether_ioctl(ifp, cmd, data);
+ break;
+ }
+
+ return (error);
+}
+
+/*
+ * Interrupts functions
+ */
+
+static int
awg_rxintr(struct awg_softc *sc)
{
if_t ifp;
@@ -1085,88 +1368,9 @@ awg_poll(if_t ifp, enum poll_cmd cmd, int count)
}
#endif
-static int
-awg_ioctl(if_t ifp, u_long cmd, caddr_t data)
-{
- struct awg_softc *sc;
- struct mii_data *mii;
- struct ifreq *ifr;
- int flags, mask, error;
-
- sc = if_getsoftc(ifp);
- mii = device_get_softc(sc->miibus);
- ifr = (struct ifreq *)data;
- error = 0;
-
- switch (cmd) {
- case SIOCSIFFLAGS:
- AWG_LOCK(sc);
- if (if_getflags(ifp) & IFF_UP) {
- if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
- flags = if_getflags(ifp) ^ sc->if_flags;
- if ((flags & (IFF_PROMISC|IFF_ALLMULTI)) != 0)
- awg_setup_rxfilter(sc);
- } else
- awg_init_locked(sc);
- } else {
- if (if_getdrvflags(ifp) & IFF_DRV_RUNNING)
- awg_stop(sc);
- }
- sc->if_flags = if_getflags(ifp);
- AWG_UNLOCK(sc);
- break;
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
- AWG_LOCK(sc);
- awg_setup_rxfilter(sc);
- AWG_UNLOCK(sc);
- }
- break;
- case SIOCSIFMEDIA:
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
- break;
- case SIOCSIFCAP:
- mask = ifr->ifr_reqcap ^ if_getcapenable(ifp);
-#ifdef DEVICE_POLLING
- if (mask & IFCAP_POLLING) {
- if ((ifr->ifr_reqcap & IFCAP_POLLING) != 0) {
- error = ether_poll_register(awg_poll, ifp);
- if (error != 0)
- break;
- AWG_LOCK(sc);
- awg_disable_dma_intr(sc);
- if_setcapenablebit(ifp, IFCAP_POLLING, 0);
- AWG_UNLOCK(sc);
- } else {
- error = ether_poll_deregister(ifp);
- AWG_LOCK(sc);
- awg_enable_dma_intr(sc);
- if_setcapenablebit(ifp, 0, IFCAP_POLLING);
- AWG_UNLOCK(sc);
- }
- }
-#endif
- if (mask & IFCAP_VLAN_MTU)
- if_togglecapenable(ifp, IFCAP_VLAN_MTU);
- if (mask & IFCAP_RXCSUM)
- if_togglecapenable(ifp, IFCAP_RXCSUM);
- if (mask & IFCAP_TXCSUM)
- if_togglecapenable(ifp, IFCAP_TXCSUM);
- if ((if_getcapenable(ifp) & IFCAP_TXCSUM) != 0)
- if_sethwassistbits(ifp, CSUM_IP | CSUM_UDP | CSUM_TCP, 0);
- else
- if_sethwassistbits(ifp, 0, CSUM_IP | CSUM_UDP | CSUM_TCP);
- break;
- default:
- error = ether_ioctl(ifp, cmd, data);
- break;
- }
-
- return (error);
-}
-
+/*
+ * syscon functions
+ */
static uint32_t
syscon_read_emac_clk_reg(device_t dev)
{
@@ -1193,6 +1397,10 @@ syscon_write_emac_clk_reg(device_t dev, uint32_t val)
bus_write_4(sc->res[_RES_SYSCON], 0, val);
}
+/*
+ * PHY functions
+ */
+
static phandle_t
awg_get_phy_node(device_t dev)
{
@@ -1532,46 +1740,6 @@ fail:
return (error);
}
-static void
-awg_get_eaddr(device_t dev, uint8_t *eaddr)
-{
- struct awg_softc *sc;
- uint32_t maclo, machi, rnd;
- u_char rootkey[16];
- uint32_t rootkey_size;
-
- sc = device_get_softc(dev);
-
- machi = RD4(sc, EMAC_ADDR_HIGH(0)) & 0xffff;
- maclo = RD4(sc, EMAC_ADDR_LOW(0));
-
- rootkey_size = sizeof(rootkey);
- if (maclo == 0xffffffff && machi == 0xffff) {
- /* MAC address in hardware is invalid, create one */
- if (aw_sid_get_fuse(AW_SID_FUSE_ROOTKEY, rootkey,
- &rootkey_size) == 0 &&
- (rootkey[3] | rootkey[12] | rootkey[13] | rootkey[14] |
- rootkey[15]) != 0) {
- /* MAC address is derived from the root key in SID */
- maclo = (rootkey[13] << 24) | (rootkey[12] << 16) |
- (rootkey[3] << 8) | 0x02;
- machi = (rootkey[15] << 8) | rootkey[14];
- } else {
- /* Create one */
- rnd = arc4random();
- maclo = 0x00f2 | (rnd & 0xffff0000);
- machi = rnd & 0xffff;
- }
- }
-
- eaddr[0] = maclo & 0xff;
- eaddr[1] = (maclo >> 8) & 0xff;
- eaddr[2] = (maclo >> 16) & 0xff;
- eaddr[3] = (maclo >> 24) & 0xff;
- eaddr[4] = machi & 0xff;
- eaddr[5] = (machi >> 8) & 0xff;
-}
-
#ifdef AWG_DEBUG
static void
awg_dump_regs(device_t dev)
@@ -1696,166 +1864,39 @@ awg_reset(device_t dev)
return (0);
}
-static void
-awg_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
-{
- if (error != 0)
- return;
- *(bus_addr_t *)arg = segs[0].ds_addr;
-}
+/*
+ * Stats
+ */
-static int
-awg_setup_dma(device_t dev)
+static void
+awg_tick(void *softc)
{
struct awg_softc *sc;
- int error, i;
-
- sc = device_get_softc(dev);
-
- /* Setup TX ring */
- error = bus_dma_tag_create(
- bus_get_dma_tag(dev), /* Parent tag */
- DESC_ALIGN, 0, /* alignment, boundary */
- BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- TX_DESC_SIZE, 1, /* maxsize, nsegs */
- TX_DESC_SIZE, /* maxsegsize */
- 0, /* flags */
- NULL, NULL, /* lockfunc, lockarg */
- &sc->tx.desc_tag);
- if (error != 0) {
- device_printf(dev, "cannot create TX descriptor ring tag\n");
- return (error);
- }
-
- error = bus_dmamem_alloc(sc->tx.desc_tag, (void **)&sc->tx.desc_ring,
- BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->tx.desc_map);
- if (error != 0) {
- device_printf(dev, "cannot allocate TX descriptor ring\n");
- return (error);
- }
-
- error = bus_dmamap_load(sc->tx.desc_tag, sc->tx.desc_map,
- sc->tx.desc_ring, TX_DESC_SIZE, awg_dmamap_cb,
- &sc->tx.desc_ring_paddr, 0);
- if (error != 0) {
- device_printf(dev, "cannot load TX descriptor ring\n");
- return (error);
- }
-
- for (i = 0; i < TX_DESC_COUNT; i++)
- sc->tx.desc_ring[i].next =
- htole32(sc->tx.desc_ring_paddr + DESC_OFF(TX_NEXT(i)));
-
- error = bus_dma_tag_create(
- bus_get_dma_tag(dev), /* Parent tag */
- 1, 0, /* alignment, boundary */
- BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- MCLBYTES, TX_MAX_SEGS, /* maxsize, nsegs */
- MCLBYTES, /* maxsegsize */
- 0, /* flags */
- NULL, NULL, /* lockfunc, lockarg */
- &sc->tx.buf_tag);
- if (error != 0) {
- device_printf(dev, "cannot create TX buffer tag\n");
- return (error);
- }
-
- sc->tx.queued = 0;
- for (i = 0; i < TX_DESC_COUNT; i++) {
- error = bus_dmamap_create(sc->tx.buf_tag, 0,
- &sc->tx.buf_map[i].map);
- if (error != 0) {
- device_printf(dev, "cannot create TX buffer map\n");
- return (error);
- }
- }
-
- /* Setup RX ring */
- error = bus_dma_tag_create(
- bus_get_dma_tag(dev), /* Parent tag */
- DESC_ALIGN, 0, /* alignment, boundary */
- BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- RX_DESC_SIZE, 1, /* maxsize, nsegs */
- RX_DESC_SIZE, /* maxsegsize */
- 0, /* flags */
- NULL, NULL, /* lockfunc, lockarg */
- &sc->rx.desc_tag);
- if (error != 0) {
- device_printf(dev, "cannot create RX descriptor ring tag\n");
- return (error);
- }
-
- error = bus_dmamem_alloc(sc->rx.desc_tag, (void **)&sc->rx.desc_ring,
- BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->rx.desc_map);
- if (error != 0) {
- device_printf(dev, "cannot allocate RX descriptor ring\n");
- return (error);
- }
-
- error = bus_dmamap_load(sc->rx.desc_tag, sc->rx.desc_map,
- sc->rx.desc_ring, RX_DESC_SIZE, awg_dmamap_cb,
- &sc->rx.desc_ring_paddr, 0);
- if (error != 0) {
- device_printf(dev, "cannot load RX descriptor ring\n");
- return (error);
- }
-
- error = bus_dma_tag_create(
- bus_get_dma_tag(dev), /* Parent tag */
- 1, 0, /* alignment, boundary */
- BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- MCLBYTES, 1, /* maxsize, nsegs */
- MCLBYTES, /* maxsegsize */
- 0, /* flags */
- NULL, NULL, /* lockfunc, lockarg */
- &sc->rx.buf_tag);
- if (error != 0) {
- device_printf(dev, "cannot create RX buffer tag\n");
- return (error);
- }
+ struct mii_data *mii;
+ if_t ifp;
+ int link;
- error = bus_dmamap_create(sc->rx.buf_tag, 0, &sc->rx.buf_spare_map);
- if (error != 0) {
- device_printf(dev,
- "cannot create RX buffer spare map\n");
- return (error);
- }
+ sc = softc;
+ ifp = sc->ifp;
+ mii = device_get_softc(sc->miibus);
- for (i = 0; i < RX_DESC_COUNT; i++) {
- sc->rx.desc_ring[i].next =
- htole32(sc->rx.desc_ring_paddr + DESC_OFF(RX_NEXT(i)));
+ AWG_ASSERT_LOCKED(sc);
- error = bus_dmamap_create(sc->rx.buf_tag, 0,
- &sc->rx.buf_map[i].map);
- if (error != 0) {
- device_printf(dev, "cannot create RX buffer map\n");
- return (error);
- }
- sc->rx.buf_map[i].mbuf = NULL;
- error = awg_newbuf_rx(sc, i);
- if (error != 0) {
- device_printf(dev, "cannot create RX buffer\n");
- return (error);
- }
- }
- bus_dmamap_sync(sc->rx.desc_tag, sc->rx.desc_map,
- BUS_DMASYNC_PREWRITE);
+ if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0)
+ return;
- /* Write transmit and receive descriptor base address registers */
- WR4(sc, EMAC_TX_DMA_LIST, sc->tx.desc_ring_paddr);
- WR4(sc, EMAC_RX_DMA_LIST, sc->rx.desc_ring_paddr);
+ link = sc->link;
+ mii_tick(mii);
+ if (sc->link && !link)
+ awg_start_locked(sc);
- return (0);
+ callout_reset(&sc->stat_ch, hz, awg_tick, sc);
}
+/*
+ * Probe/attach functions
+ */
+
static int
awg_probe(device_t dev)
{