2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2019 Ruslan Bukin <br@bsdpad.com>
6 * This software was developed by SRI International and the University of
7 * Cambridge Computer Laboratory (Department of Computer Science and
8 * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
9 * DARPA SSITH research programme.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
36 #include <sys/param.h>
37 #include <sys/systm.h>
39 #include <sys/kernel.h>
41 #include <sys/malloc.h>
43 #include <sys/module.h>
44 #include <sys/mutex.h>
46 #include <sys/socket.h>
47 #include <sys/sockio.h>
51 #include <net/ethernet.h>
52 #include <net/if_dl.h>
53 #include <net/if_media.h>
54 #include <net/if_types.h>
55 #include <net/if_var.h>
57 #include <machine/bus.h>
59 #include <dev/mii/mii.h>
60 #include <dev/mii/miivar.h>
61 #include <dev/mii/tiphy.h>
62 #include <dev/ofw/ofw_bus.h>
63 #include <dev/ofw/ofw_bus_subr.h>
64 #include <dev/xilinx/if_xaereg.h>
65 #include <dev/xilinx/if_xaevar.h>
67 #include <dev/xilinx/axidma.h>
69 #include "miibus_if.h"
71 #define READ4(_sc, _reg) \
72 bus_read_4((_sc)->res[0], _reg)
73 #define WRITE4(_sc, _reg, _val) \
74 bus_write_4((_sc)->res[0], _reg, _val)
76 #define READ8(_sc, _reg) \
77 bus_read_8((_sc)->res[0], _reg)
78 #define WRITE8(_sc, _reg, _val) \
79 bus_write_8((_sc)->res[0], _reg, _val)
81 #define XAE_LOCK(sc) mtx_lock(&(sc)->mtx)
82 #define XAE_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
83 #define XAE_ASSERT_LOCKED(sc) mtx_assert(&(sc)->mtx, MA_OWNED)
84 #define XAE_ASSERT_UNLOCKED(sc) mtx_assert(&(sc)->mtx, MA_NOTOWNED)
90 #define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__)
92 #define dprintf(fmt, ...)
95 #define RX_QUEUE_SIZE 64
96 #define TX_QUEUE_SIZE 64
97 #define NUM_RX_MBUF 16
98 #define BUFRING_SIZE 8192
99 #define MDIO_CLK_DIV_DEFAULT 29
101 #define PHY1_RD(sc, _r) \
102 xae_miibus_read_reg(sc->dev, 1, _r)
103 #define PHY1_WR(sc, _r, _v) \
104 xae_miibus_write_reg(sc->dev, 1, _r, _v)
106 #define PHY_RD(sc, _r) \
107 xae_miibus_read_reg(sc->dev, sc->phy_addr, _r)
108 #define PHY_WR(sc, _r, _v) \
109 xae_miibus_write_reg(sc->dev, sc->phy_addr, _r, _v)
111 /* Use this macro to access regs > 0x1f */
112 #define WRITE_TI_EREG(sc, reg, data) { \
113 PHY_WR(sc, MII_MMDACR, MMDACR_DADDRMASK); \
114 PHY_WR(sc, MII_MMDAADR, reg); \
115 PHY_WR(sc, MII_MMDACR, MMDACR_DADDRMASK | MMDACR_FN_DATANPI); \
116 PHY_WR(sc, MII_MMDAADR, data); \
119 /* Not documented, Xilinx VCU118 workaround */
120 #define CFG4_SGMII_TMR 0x160 /* bits 8:7 MUST be '10' */
121 #define DP83867_SGMIICTL1 0xD3 /* not documented register */
122 #define SGMIICTL1_SGMII_6W (1 << 14) /* no idea what it is */
124 static struct resource_spec xae_spec[] = {
125 { SYS_RES_MEMORY, 0, RF_ACTIVE },
126 { SYS_RES_IRQ, 0, RF_ACTIVE },
130 static void xae_stop_locked(struct xae_softc *sc);
131 static void xae_setup_rxfilter(struct xae_softc *sc);
134 xae_rx_enqueue(struct xae_softc *sc, uint32_t n)
139 for (i = 0; i < n; i++) {
140 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
142 device_printf(sc->dev,
143 "%s: Can't alloc rx mbuf\n", __func__);
147 m->m_pkthdr.len = m->m_len = m->m_ext.ext_size;
148 xdma_enqueue_mbuf(sc->xchan_rx, &m, 0, 4, 4, XDMA_DEV_TO_MEM);
155 xae_get_phyaddr(phandle_t node, int *phy_addr)
158 pcell_t phy_handle, phy_reg;
160 if (OF_getencprop(node, "phy-handle", (void *)&phy_handle,
161 sizeof(phy_handle)) <= 0)
164 phy_node = OF_node_from_xref(phy_handle);
166 if (OF_getencprop(phy_node, "reg", (void *)&phy_reg,
167 sizeof(phy_reg)) <= 0)
176 xae_xdma_tx_intr(void *arg, xdma_transfer_status_t *status)
178 xdma_transfer_status_t st;
179 struct xae_softc *sc;
191 err = xdma_dequeue_mbuf(sc->xchan_tx, &m, &st);
197 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
203 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
211 xae_xdma_rx_intr(void *arg, xdma_transfer_status_t *status)
213 xdma_transfer_status_t st;
214 struct xae_softc *sc;
218 uint32_t cnt_processed;
222 dprintf("%s\n", __func__);
230 err = xdma_dequeue_mbuf(sc->xchan_rx, &m, &st);
237 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
242 m->m_pkthdr.len = m->m_len = st.transferred;
243 m->m_pkthdr.rcvif = ifp;
245 (*ifp->if_input)(ifp, m);
249 xae_rx_enqueue(sc, cnt_processed);
257 xae_qflush(struct ifnet *ifp)
259 struct xae_softc *sc;
265 xae_transmit_locked(struct ifnet *ifp)
267 struct xae_softc *sc;
273 dprintf("%s\n", __func__);
280 while ((m = drbr_peek(ifp, br)) != NULL) {
281 error = xdma_enqueue_mbuf(sc->xchan_tx,
282 &m, 0, 4, 4, XDMA_MEM_TO_DEV);
284 /* No space in request queue available yet. */
285 drbr_putback(ifp, br, m);
289 drbr_advance(ifp, br);
293 /* If anyone is interested give them a copy. */
294 ETHER_BPF_MTAP(ifp, m);
298 xdma_queue_submit(sc->xchan_tx);
304 xae_transmit(struct ifnet *ifp, struct mbuf *m)
306 struct xae_softc *sc;
309 dprintf("%s\n", __func__);
315 error = drbr_enqueue(ifp, sc->br, m);
321 if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
327 if (!sc->link_is_up) {
332 error = xae_transmit_locked(ifp);
340 xae_stop_locked(struct xae_softc *sc)
345 XAE_ASSERT_LOCKED(sc);
348 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
350 callout_stop(&sc->xae_callout);
352 /* Stop the transmitter */
353 reg = READ4(sc, XAE_TC);
355 WRITE4(sc, XAE_TC, reg);
357 /* Stop the receiver. */
358 reg = READ4(sc, XAE_RCW1);
360 WRITE4(sc, XAE_RCW1, reg);
364 xae_stat(struct xae_softc *sc, int counter_id)
369 KASSERT(counter_id < XAE_MAX_COUNTERS,
370 ("counter %d is out of range", counter_id));
372 new = READ8(sc, XAE_STATCNT(counter_id));
373 old = sc->counters[counter_id];
378 delta = UINT64_MAX - old + new;
379 sc->counters[counter_id] = new;
385 xae_harvest_stats(struct xae_softc *sc)
391 if_inc_counter(ifp, IFCOUNTER_IPACKETS, xae_stat(sc, RX_GOOD_FRAMES));
392 if_inc_counter(ifp, IFCOUNTER_IMCASTS, xae_stat(sc, RX_GOOD_MCASTS));
393 if_inc_counter(ifp, IFCOUNTER_IERRORS,
394 xae_stat(sc, RX_FRAME_CHECK_SEQ_ERROR) +
395 xae_stat(sc, RX_LEN_OUT_OF_RANGE) +
396 xae_stat(sc, RX_ALIGNMENT_ERRORS));
398 if_inc_counter(ifp, IFCOUNTER_OBYTES, xae_stat(sc, TX_BYTES));
399 if_inc_counter(ifp, IFCOUNTER_OPACKETS, xae_stat(sc, TX_GOOD_FRAMES));
400 if_inc_counter(ifp, IFCOUNTER_OMCASTS, xae_stat(sc, TX_GOOD_MCASTS));
401 if_inc_counter(ifp, IFCOUNTER_OERRORS,
402 xae_stat(sc, TX_GOOD_UNDERRUN_ERRORS));
404 if_inc_counter(ifp, IFCOUNTER_COLLISIONS,
405 xae_stat(sc, TX_SINGLE_COLLISION_FRAMES) +
406 xae_stat(sc, TX_MULTI_COLLISION_FRAMES) +
407 xae_stat(sc, TX_LATE_COLLISIONS) +
408 xae_stat(sc, TX_EXCESS_COLLISIONS));
414 struct xae_softc *sc;
420 XAE_ASSERT_LOCKED(sc);
424 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
427 /* Gather stats from hardware counters. */
428 xae_harvest_stats(sc);
430 /* Check the media status. */
431 link_was_up = sc->link_is_up;
432 mii_tick(sc->mii_softc);
433 if (sc->link_is_up && !link_was_up)
434 xae_transmit_locked(sc->ifp);
436 /* Schedule another check one second from now. */
437 callout_reset(&sc->xae_callout, hz, xae_tick, sc);
441 xae_init_locked(struct xae_softc *sc)
445 XAE_ASSERT_LOCKED(sc);
448 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
451 ifp->if_drv_flags |= IFF_DRV_RUNNING;
453 xae_setup_rxfilter(sc);
455 /* Enable the transmitter */
456 WRITE4(sc, XAE_TC, TC_TX);
458 /* Enable the receiver. */
459 WRITE4(sc, XAE_RCW1, RCW1_RX);
462 * Call mii_mediachg() which will call back into xae_miibus_statchg()
463 * to set up the remaining config registers based on current media.
465 mii_mediachg(sc->mii_softc);
466 callout_reset(&sc->xae_callout, hz, xae_tick, sc);
472 struct xae_softc *sc;
482 xae_media_status(struct ifnet * ifp, struct ifmediareq *ifmr)
484 struct xae_softc *sc;
485 struct mii_data *mii;
492 ifmr->ifm_active = mii->mii_media_active;
493 ifmr->ifm_status = mii->mii_media_status;
498 xae_media_change_locked(struct xae_softc *sc)
501 return (mii_mediachg(sc->mii_softc));
505 xae_media_change(struct ifnet * ifp)
507 struct xae_softc *sc;
513 error = xae_media_change_locked(sc);
520 xae_write_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
522 struct xae_softc *sc = arg;
526 if (cnt >= XAE_MULTICAST_TABLE_SIZE)
531 reg = READ4(sc, XAE_FFC) & 0xffffff00;
533 WRITE4(sc, XAE_FFC, reg);
537 reg |= (ma[2] << 16);
538 reg |= (ma[3] << 24);
539 WRITE4(sc, XAE_FFV(0), reg);
543 WRITE4(sc, XAE_FFV(1), reg);
549 xae_setup_rxfilter(struct xae_softc *sc)
554 XAE_ASSERT_LOCKED(sc);
559 * Set the multicast (group) filter hash.
561 if ((ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
562 reg = READ4(sc, XAE_FFC);
564 WRITE4(sc, XAE_FFC, reg);
566 reg = READ4(sc, XAE_FFC);
568 WRITE4(sc, XAE_FFC, reg);
570 if_foreach_llmaddr(ifp, xae_write_maddr, sc);
574 * Set the primary address.
576 reg = sc->macaddr[0];
577 reg |= (sc->macaddr[1] << 8);
578 reg |= (sc->macaddr[2] << 16);
579 reg |= (sc->macaddr[3] << 24);
580 WRITE4(sc, XAE_UAW0, reg);
582 reg = sc->macaddr[4];
583 reg |= (sc->macaddr[5] << 8);
584 WRITE4(sc, XAE_UAW1, reg);
588 xae_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
590 struct xae_softc *sc;
591 struct mii_data *mii;
596 ifr = (struct ifreq *)data;
602 if (ifp->if_flags & IFF_UP) {
603 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
604 if ((ifp->if_flags ^ sc->if_flags) &
605 (IFF_PROMISC | IFF_ALLMULTI))
606 xae_setup_rxfilter(sc);
608 if (!sc->is_detaching)
612 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
615 sc->if_flags = ifp->if_flags;
620 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
622 xae_setup_rxfilter(sc);
629 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
632 mask = ifp->if_capenable ^ ifr->ifr_reqcap;
633 if (mask & IFCAP_VLAN_MTU) {
634 /* No work to do except acknowledge the change took */
635 ifp->if_capenable ^= IFCAP_VLAN_MTU;
640 error = ether_ioctl(ifp, cmd, data);
654 xae_get_hwaddr(struct xae_softc *sc, uint8_t *hwaddr)
659 node = ofw_bus_get_node(sc->dev);
661 /* Check if there is property */
662 if ((len = OF_getproplen(node, "local-mac-address")) <= 0)
665 if (len != ETHER_ADDR_LEN)
668 OF_getprop(node, "local-mac-address", hwaddr,
675 mdio_wait(struct xae_softc *sc)
683 reg = READ4(sc, XAE_MDIO_CTRL);
684 if (reg & MDIO_CTRL_READY)
690 printf("Failed to get MDIO ready\n");
698 xae_miibus_read_reg(device_t dev, int phy, int reg)
700 struct xae_softc *sc;
704 sc = device_get_softc(dev);
709 mii = MDIO_CTRL_TX_OP_READ | MDIO_CTRL_INITIATE;
710 mii |= (reg << MDIO_TX_REGAD_S);
711 mii |= (phy << MDIO_TX_PHYAD_S);
713 WRITE4(sc, XAE_MDIO_CTRL, mii);
718 rv = READ4(sc, XAE_MDIO_READ);
724 xae_miibus_write_reg(device_t dev, int phy, int reg, int val)
726 struct xae_softc *sc;
729 sc = device_get_softc(dev);
734 mii = MDIO_CTRL_TX_OP_WRITE | MDIO_CTRL_INITIATE;
735 mii |= (reg << MDIO_TX_REGAD_S);
736 mii |= (phy << MDIO_TX_PHYAD_S);
738 WRITE4(sc, XAE_MDIO_WRITE, val);
739 WRITE4(sc, XAE_MDIO_CTRL, mii);
748 xae_phy_fixup(struct xae_softc *sc)
756 WRITE_TI_EREG(sc, DP83867_SGMIICTL1, SGMIICTL1_SGMII_6W);
757 PHY_WR(sc, DP83867_PHYCR, PHYCR_SGMII_EN);
759 reg = PHY_RD(sc, DP83867_CFG2);
760 reg &= ~CFG2_SPEED_OPT_ATTEMPT_CNT_M;
761 reg |= (CFG2_SPEED_OPT_ATTEMPT_CNT_4);
762 reg |= CFG2_INTERRUPT_POLARITY;
763 reg |= CFG2_SPEED_OPT_ENHANCED_EN;
764 reg |= CFG2_SPEED_OPT_10M_EN;
765 PHY_WR(sc, DP83867_CFG2, reg);
767 WRITE_TI_EREG(sc, DP83867_CFG4, CFG4_SGMII_TMR);
769 BMCR_AUTOEN | BMCR_FDX | BMCR_SPEED1 | BMCR_RESET);
770 } while (PHY1_RD(sc, MII_BMCR) == 0x0ffff);
773 PHY1_WR(sc, MII_BMCR,
774 BMCR_AUTOEN | BMCR_FDX | BMCR_SPEED1 | BMCR_STARTNEG);
776 } while ((PHY1_RD(sc, MII_BMSR) & BMSR_ACOMP) == 0);
780 get_xdma_std(struct xae_softc *sc)
783 sc->xdma_tx = xdma_ofw_get(sc->dev, "tx");
784 if (sc->xdma_tx == NULL)
787 sc->xdma_rx = xdma_ofw_get(sc->dev, "rx");
788 if (sc->xdma_rx == NULL) {
789 xdma_put(sc->xdma_tx);
797 get_xdma_axistream(struct xae_softc *sc)
799 struct axidma_fdt_data *data;
805 node = ofw_bus_get_node(sc->dev);
806 len = OF_getencprop(node, "axistream-connected", &prop, sizeof(prop));
807 if (len != sizeof(prop)) {
808 device_printf(sc->dev,
809 "%s: Couldn't get axistream-connected prop.\n", __func__);
812 dma_dev = OF_device_from_xref(prop);
813 if (dma_dev == NULL) {
814 device_printf(sc->dev, "Could not get DMA device by xref.\n");
818 sc->xdma_tx = xdma_get(sc->dev, dma_dev);
819 if (sc->xdma_tx == NULL) {
820 device_printf(sc->dev, "Could not find DMA controller.\n");
823 data = malloc(sizeof(struct axidma_fdt_data),
824 M_DEVBUF, (M_WAITOK | M_ZERO));
825 data->id = AXIDMA_TX_CHAN;
826 sc->xdma_tx->data = data;
828 sc->xdma_rx = xdma_get(sc->dev, dma_dev);
829 if (sc->xdma_rx == NULL) {
830 device_printf(sc->dev, "Could not find DMA controller.\n");
833 data = malloc(sizeof(struct axidma_fdt_data),
834 M_DEVBUF, (M_WAITOK | M_ZERO));
835 data->id = AXIDMA_RX_CHAN;
836 sc->xdma_rx->data = data;
842 setup_xdma(struct xae_softc *sc)
850 /* Get xDMA controller */
851 error = get_xdma_std(sc);
854 device_printf(sc->dev,
855 "Fallback to axistream-connected property\n");
856 error = get_xdma_axistream(sc);
860 device_printf(dev, "Could not find xDMA controllers.\n");
864 /* Alloc xDMA TX virtual channel. */
865 sc->xchan_tx = xdma_channel_alloc(sc->xdma_tx, 0);
866 if (sc->xchan_tx == NULL) {
867 device_printf(dev, "Can't alloc virtual DMA TX channel.\n");
871 /* Setup interrupt handler. */
872 error = xdma_setup_intr(sc->xchan_tx, 0,
873 xae_xdma_tx_intr, sc, &sc->ih_tx);
875 device_printf(sc->dev,
876 "Can't setup xDMA TX interrupt handler.\n");
880 /* Alloc xDMA RX virtual channel. */
881 sc->xchan_rx = xdma_channel_alloc(sc->xdma_rx, 0);
882 if (sc->xchan_rx == NULL) {
883 device_printf(dev, "Can't alloc virtual DMA RX channel.\n");
887 /* Setup interrupt handler. */
888 error = xdma_setup_intr(sc->xchan_rx, XDMA_INTR_NET,
889 xae_xdma_rx_intr, sc, &sc->ih_rx);
891 device_printf(sc->dev,
892 "Can't setup xDMA RX interrupt handler.\n");
896 /* Setup bounce buffer */
897 vmem = xdma_get_memory(dev);
899 xchan_set_memory(sc->xchan_tx, vmem);
900 xchan_set_memory(sc->xchan_rx, vmem);
903 xdma_prep_sg(sc->xchan_tx,
904 TX_QUEUE_SIZE, /* xchan requests queue size */
905 MCLBYTES, /* maxsegsize */
909 BUS_SPACE_MAXADDR_32BIT,
912 xdma_prep_sg(sc->xchan_rx,
913 RX_QUEUE_SIZE, /* xchan requests queue size */
914 MCLBYTES, /* maxsegsize */
918 BUS_SPACE_MAXADDR_32BIT,
925 xae_probe(device_t dev)
928 if (!ofw_bus_status_okay(dev))
931 if (!ofw_bus_is_compatible(dev, "xlnx,axi-ethernet-1.00.a"))
934 device_set_desc(dev, "Xilinx AXI Ethernet");
936 return (BUS_PROBE_DEFAULT);
940 xae_attach(device_t dev)
942 struct xae_softc *sc;
948 sc = device_get_softc(dev);
950 node = ofw_bus_get_node(dev);
952 if (setup_xdma(sc) != 0) {
953 device_printf(dev, "Could not setup xDMA.\n");
957 mtx_init(&sc->mtx, device_get_nameunit(sc->dev),
958 MTX_NETWORK_LOCK, MTX_DEF);
960 sc->br = buf_ring_alloc(BUFRING_SIZE, M_DEVBUF,
965 if (bus_alloc_resources(dev, xae_spec, sc->res)) {
966 device_printf(dev, "could not allocate resources\n");
970 /* Memory interface */
971 sc->bst = rman_get_bustag(sc->res[0]);
972 sc->bsh = rman_get_bushandle(sc->res[0]);
974 device_printf(sc->dev, "Identification: %x\n",
975 READ4(sc, XAE_IDENT));
978 if (xae_get_hwaddr(sc, sc->macaddr)) {
979 device_printf(sc->dev, "can't get mac\n");
983 /* Enable MII clock */
984 reg = (MDIO_CLK_DIV_DEFAULT << MDIO_SETUP_CLK_DIV_S);
985 reg |= MDIO_SETUP_ENABLE;
986 WRITE4(sc, XAE_MDIO_SETUP, reg);
990 callout_init_mtx(&sc->xae_callout, &sc->mtx, 0);
992 /* Setup interrupt handler. */
993 error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_NET | INTR_MPSAFE,
994 NULL, xae_intr, sc, &sc->intr_cookie);
996 device_printf(dev, "could not setup interrupt handler.\n");
1000 /* Set up the ethernet interface. */
1001 sc->ifp = ifp = if_alloc(IFT_ETHER);
1003 device_printf(dev, "could not allocate ifp.\n");
1008 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
1009 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1010 ifp->if_capabilities = IFCAP_VLAN_MTU;
1011 ifp->if_capenable = ifp->if_capabilities;
1012 ifp->if_transmit = xae_transmit;
1013 ifp->if_qflush = xae_qflush;
1014 ifp->if_ioctl = xae_ioctl;
1015 ifp->if_init = xae_init;
1016 IFQ_SET_MAXLEN(&ifp->if_snd, TX_DESC_COUNT - 1);
1017 ifp->if_snd.ifq_drv_maxlen = TX_DESC_COUNT - 1;
1018 IFQ_SET_READY(&ifp->if_snd);
1020 if (xae_get_phyaddr(node, &sc->phy_addr) != 0)
1023 /* Attach the mii driver. */
1024 error = mii_attach(dev, &sc->miibus, ifp, xae_media_change,
1025 xae_media_status, BMSR_DEFCAPMASK, sc->phy_addr,
1029 device_printf(dev, "PHY attach failed\n");
1032 sc->mii_softc = device_get_softc(sc->miibus);
1034 /* Apply vcu118 workaround. */
1035 if (OF_getproplen(node, "xlnx,vcu118") >= 0)
1038 /* All ready to run, attach the ethernet interface. */
1039 ether_ifattach(ifp, sc->macaddr);
1040 sc->is_attached = true;
1042 xae_rx_enqueue(sc, NUM_RX_MBUF);
1043 xdma_queue_submit(sc->xchan_rx);
1049 xae_detach(device_t dev)
1051 struct xae_softc *sc;
1054 sc = device_get_softc(dev);
1056 KASSERT(mtx_initialized(&sc->mtx), ("%s: mutex not initialized",
1057 device_get_nameunit(dev)));
1061 /* Only cleanup if attach succeeded. */
1062 if (device_is_attached(dev)) {
1064 xae_stop_locked(sc);
1066 callout_drain(&sc->xae_callout);
1067 ether_ifdetach(ifp);
1070 if (sc->miibus != NULL)
1071 device_delete_child(dev, sc->miibus);
1076 mtx_destroy(&sc->mtx);
1078 bus_teardown_intr(dev, sc->res[1], sc->intr_cookie);
1080 bus_release_resources(dev, xae_spec, sc->res);
1082 xdma_channel_free(sc->xchan_tx);
1083 xdma_channel_free(sc->xchan_rx);
1084 xdma_put(sc->xdma_tx);
1085 xdma_put(sc->xdma_rx);
1091 xae_miibus_statchg(device_t dev)
1093 struct xae_softc *sc;
1094 struct mii_data *mii;
1098 * Called by the MII bus driver when the PHY establishes
1099 * link to set the MAC interface registers.
1102 sc = device_get_softc(dev);
1104 XAE_ASSERT_LOCKED(sc);
1106 mii = sc->mii_softc;
1108 if (mii->mii_media_status & IFM_ACTIVE)
1109 sc->link_is_up = true;
1111 sc->link_is_up = false;
1113 switch (IFM_SUBTYPE(mii->mii_media_active)) {
1125 sc->link_is_up = false;
1128 sc->link_is_up = false;
1129 device_printf(dev, "Unsupported media %u\n",
1130 IFM_SUBTYPE(mii->mii_media_active));
1134 WRITE4(sc, XAE_SPEED, reg);
1137 static device_method_t xae_methods[] = {
1138 DEVMETHOD(device_probe, xae_probe),
1139 DEVMETHOD(device_attach, xae_attach),
1140 DEVMETHOD(device_detach, xae_detach),
1143 DEVMETHOD(miibus_readreg, xae_miibus_read_reg),
1144 DEVMETHOD(miibus_writereg, xae_miibus_write_reg),
1145 DEVMETHOD(miibus_statchg, xae_miibus_statchg),
1149 driver_t xae_driver = {
1152 sizeof(struct xae_softc),
1155 static devclass_t xae_devclass;
1157 DRIVER_MODULE(xae, simplebus, xae_driver, xae_devclass, 0, 0);
1158 DRIVER_MODULE(miibus, xae, miibus_driver, miibus_devclass, 0, 0);
1160 MODULE_DEPEND(xae, ether, 1, 1, 1);
1161 MODULE_DEPEND(xae, miibus, 1, 1, 1);