Author: manu Date: Fri Nov 20 11:29:37 2020 New Revision: 367883 URL: https://svnweb.freebsd.org/changeset/base/367883
Log: if_awg: Reorder functions and sort them by usage No functional changes intended Modified: head/sys/arm/allwinner/if_awg.c Modified: head/sys/arm/allwinner/if_awg.c ============================================================================== --- head/sys/arm/allwinner/if_awg.c Fri Nov 20 11:29:20 2020 (r367882) +++ head/sys/arm/allwinner/if_awg.c Fri Nov 20 11:29:37 2020 (r367883) @@ -217,7 +217,10 @@ 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); static uint32_t syscon_read_emac_clk_reg(device_t dev); @@ -225,6 +228,10 @@ static void syscon_write_emac_clk_reg(device_t dev, ui 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,165 +1864,38 @@ awg_reset(device_t dev) return (0); } +/* + * Stats + */ + static void -awg_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) +awg_tick(void *softc) { - 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; + struct mii_data *mii; + if_t ifp; + int link; - sc = device_get_softc(dev); + sc = softc; + ifp = sc->ifp; + mii = device_get_softc(sc->miibus); - /* 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); - } + AWG_ASSERT_LOCKED(sc); - 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); - } + if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) + return; - 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); - } + link = sc->link; + mii_tick(mii); + if (sc->link && !link) + awg_start_locked(sc); - 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 */ *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** _______________________________________________ svn-src-head@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"