The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/xilinx/if_xae.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause
    3  *
    4  * Copyright (c) 2019 Ruslan Bukin <br@bsdpad.com>
    5  *
    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.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   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.
   19  *
   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
   30  * SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/bus.h>
   39 #include <sys/kernel.h>
   40 #include <sys/lock.h>
   41 #include <sys/malloc.h>
   42 #include <sys/mbuf.h>
   43 #include <sys/module.h>
   44 #include <sys/mutex.h>
   45 #include <sys/rman.h>
   46 #include <sys/socket.h>
   47 #include <sys/sockio.h>
   48 
   49 #include <net/bpf.h>
   50 #include <net/if.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>
   56 
   57 #include <machine/bus.h>
   58 
   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>
   66 
   67 #include <dev/xilinx/axidma.h>
   68 
   69 #include "miibus_if.h"
   70 
   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)
   75 
   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)
   80 
   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)
   85 
   86 #define XAE_DEBUG
   87 #undef XAE_DEBUG
   88 
   89 #ifdef XAE_DEBUG
   90 #define dprintf(fmt, ...)  printf(fmt, ##__VA_ARGS__)
   91 #else
   92 #define dprintf(fmt, ...)
   93 #endif
   94 
   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
  100 
  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)
  105 
  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)
  110 
  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);                                  \
  117 }
  118 
  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 */
  123 
  124 static struct resource_spec xae_spec[] = {
  125         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
  126         { SYS_RES_IRQ,          0,      RF_ACTIVE },
  127         { -1, 0 }
  128 };
  129 
  130 static void xae_stop_locked(struct xae_softc *sc);
  131 static void xae_setup_rxfilter(struct xae_softc *sc);
  132 
  133 static int
  134 xae_rx_enqueue(struct xae_softc *sc, uint32_t n)
  135 {
  136         struct mbuf *m;
  137         int i;
  138 
  139         for (i = 0; i < n; i++) {
  140                 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
  141                 if (m == NULL) {
  142                         device_printf(sc->dev,
  143                             "%s: Can't alloc rx mbuf\n", __func__);
  144                         return (-1);
  145                 }
  146 
  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);
  149         }
  150 
  151         return (0);
  152 }
  153 
  154 static int
  155 xae_get_phyaddr(phandle_t node, int *phy_addr)
  156 {
  157         phandle_t phy_node;
  158         pcell_t phy_handle, phy_reg;
  159 
  160         if (OF_getencprop(node, "phy-handle", (void *)&phy_handle,
  161             sizeof(phy_handle)) <= 0)
  162                 return (ENXIO);
  163 
  164         phy_node = OF_node_from_xref(phy_handle);
  165 
  166         if (OF_getencprop(phy_node, "reg", (void *)&phy_reg,
  167             sizeof(phy_reg)) <= 0)
  168                 return (ENXIO);
  169 
  170         *phy_addr = phy_reg;
  171 
  172         return (0);
  173 }
  174 
  175 static int
  176 xae_xdma_tx_intr(void *arg, xdma_transfer_status_t *status)
  177 {
  178         xdma_transfer_status_t st;
  179         struct xae_softc *sc;
  180         struct ifnet *ifp;
  181         struct mbuf *m;
  182         int err;
  183 
  184         sc = arg;
  185 
  186         XAE_LOCK(sc);
  187 
  188         ifp = sc->ifp;
  189 
  190         for (;;) {
  191                 err = xdma_dequeue_mbuf(sc->xchan_tx, &m, &st);
  192                 if (err != 0) {
  193                         break;
  194                 }
  195 
  196                 if (st.error != 0) {
  197                         if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
  198                 }
  199 
  200                 m_freem(m);
  201         }
  202 
  203         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  204 
  205         XAE_UNLOCK(sc);
  206 
  207         return (0);
  208 }
  209 
  210 static int
  211 xae_xdma_rx_intr(void *arg, xdma_transfer_status_t *status)
  212 {
  213         xdma_transfer_status_t st;
  214         struct xae_softc *sc;
  215         struct ifnet *ifp;
  216         struct mbuf *m;
  217         int err;
  218         uint32_t cnt_processed;
  219 
  220         sc = arg;
  221 
  222         dprintf("%s\n", __func__);
  223 
  224         XAE_LOCK(sc);
  225 
  226         ifp = sc->ifp;
  227 
  228         cnt_processed = 0;
  229         for (;;) {
  230                 err = xdma_dequeue_mbuf(sc->xchan_rx, &m, &st);
  231                 if (err != 0) {
  232                         break;
  233                 }
  234                 cnt_processed++;
  235 
  236                 if (st.error != 0) {
  237                         if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
  238                         m_freem(m);
  239                         continue;
  240                 }
  241 
  242                 m->m_pkthdr.len = m->m_len = st.transferred;
  243                 m->m_pkthdr.rcvif = ifp;
  244                 XAE_UNLOCK(sc);
  245                 (*ifp->if_input)(ifp, m);
  246                 XAE_LOCK(sc);
  247         }
  248 
  249         xae_rx_enqueue(sc, cnt_processed);
  250 
  251         XAE_UNLOCK(sc);
  252 
  253         return (0);
  254 }
  255 
  256 static void
  257 xae_qflush(struct ifnet *ifp)
  258 {
  259 }
  260 
  261 static int
  262 xae_transmit_locked(struct ifnet *ifp)
  263 {
  264         struct xae_softc *sc;
  265         struct mbuf *m;
  266         struct buf_ring *br;
  267         int error;
  268         int enq;
  269 
  270         dprintf("%s\n", __func__);
  271 
  272         sc = ifp->if_softc;
  273         br = sc->br;
  274 
  275         enq = 0;
  276 
  277         while ((m = drbr_peek(ifp, br)) != NULL) {
  278                 error = xdma_enqueue_mbuf(sc->xchan_tx,
  279                     &m, 0, 4, 4, XDMA_MEM_TO_DEV);
  280                 if (error != 0) {
  281                         /* No space in request queue available yet. */
  282                         drbr_putback(ifp, br, m);
  283                         break;
  284                 }
  285 
  286                 drbr_advance(ifp, br);
  287 
  288                 enq++;
  289 
  290                 /* If anyone is interested give them a copy. */
  291                 ETHER_BPF_MTAP(ifp, m);
  292         }
  293 
  294         if (enq > 0)
  295                 xdma_queue_submit(sc->xchan_tx);
  296 
  297         return (0);
  298 }
  299 
  300 static int
  301 xae_transmit(struct ifnet *ifp, struct mbuf *m)
  302 {
  303         struct xae_softc *sc;
  304         int error;
  305 
  306         dprintf("%s\n", __func__);
  307 
  308         sc = ifp->if_softc;
  309 
  310         XAE_LOCK(sc);
  311 
  312         error = drbr_enqueue(ifp, sc->br, m);
  313         if (error) {
  314                 XAE_UNLOCK(sc);
  315                 return (error);
  316         }
  317 
  318         if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
  319             IFF_DRV_RUNNING) {
  320                 XAE_UNLOCK(sc);
  321                 return (0);
  322         }
  323 
  324         if (!sc->link_is_up) {
  325                 XAE_UNLOCK(sc);
  326                 return (0);
  327         }
  328 
  329         error = xae_transmit_locked(ifp);
  330 
  331         XAE_UNLOCK(sc);
  332 
  333         return (error);
  334 }
  335 
  336 static void
  337 xae_stop_locked(struct xae_softc *sc)
  338 {
  339         struct ifnet *ifp;
  340         uint32_t reg;
  341 
  342         XAE_ASSERT_LOCKED(sc);
  343 
  344         ifp = sc->ifp;
  345         ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
  346 
  347         callout_stop(&sc->xae_callout);
  348 
  349         /* Stop the transmitter */
  350         reg = READ4(sc, XAE_TC);
  351         reg &= ~TC_TX;
  352         WRITE4(sc, XAE_TC, reg);
  353 
  354         /* Stop the receiver. */
  355         reg = READ4(sc, XAE_RCW1);
  356         reg &= ~RCW1_RX;
  357         WRITE4(sc, XAE_RCW1, reg);
  358 }
  359 
  360 static uint64_t
  361 xae_stat(struct xae_softc *sc, int counter_id)
  362 {
  363         uint64_t new, old;
  364         uint64_t delta;
  365 
  366         KASSERT(counter_id < XAE_MAX_COUNTERS,
  367                 ("counter %d is out of range", counter_id));
  368 
  369         new = READ8(sc, XAE_STATCNT(counter_id));
  370         old = sc->counters[counter_id];
  371 
  372         if (new >= old)
  373                 delta = new - old;
  374         else
  375                 delta = UINT64_MAX - old + new;
  376         sc->counters[counter_id] = new;
  377 
  378         return (delta);
  379 }
  380 
  381 static void
  382 xae_harvest_stats(struct xae_softc *sc)
  383 {
  384         struct ifnet *ifp;
  385 
  386         ifp = sc->ifp;
  387 
  388         if_inc_counter(ifp, IFCOUNTER_IPACKETS, xae_stat(sc, RX_GOOD_FRAMES));
  389         if_inc_counter(ifp, IFCOUNTER_IMCASTS, xae_stat(sc, RX_GOOD_MCASTS));
  390         if_inc_counter(ifp, IFCOUNTER_IERRORS,
  391             xae_stat(sc, RX_FRAME_CHECK_SEQ_ERROR) +
  392             xae_stat(sc, RX_LEN_OUT_OF_RANGE) +
  393             xae_stat(sc, RX_ALIGNMENT_ERRORS));
  394 
  395         if_inc_counter(ifp, IFCOUNTER_OBYTES, xae_stat(sc, TX_BYTES));
  396         if_inc_counter(ifp, IFCOUNTER_OPACKETS, xae_stat(sc, TX_GOOD_FRAMES));
  397         if_inc_counter(ifp, IFCOUNTER_OMCASTS, xae_stat(sc, TX_GOOD_MCASTS));
  398         if_inc_counter(ifp, IFCOUNTER_OERRORS,
  399             xae_stat(sc, TX_GOOD_UNDERRUN_ERRORS));
  400 
  401         if_inc_counter(ifp, IFCOUNTER_COLLISIONS,
  402             xae_stat(sc, TX_SINGLE_COLLISION_FRAMES) +
  403             xae_stat(sc, TX_MULTI_COLLISION_FRAMES) +
  404             xae_stat(sc, TX_LATE_COLLISIONS) +
  405             xae_stat(sc, TX_EXCESS_COLLISIONS));
  406 }
  407 
  408 static void
  409 xae_tick(void *arg)
  410 {
  411         struct xae_softc *sc;
  412         struct ifnet *ifp;
  413         int link_was_up;
  414 
  415         sc = arg;
  416 
  417         XAE_ASSERT_LOCKED(sc);
  418 
  419         ifp = sc->ifp;
  420 
  421         if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
  422                 return;
  423 
  424         /* Gather stats from hardware counters. */
  425         xae_harvest_stats(sc);
  426 
  427         /* Check the media status. */
  428         link_was_up = sc->link_is_up;
  429         mii_tick(sc->mii_softc);
  430         if (sc->link_is_up && !link_was_up)
  431                 xae_transmit_locked(sc->ifp);
  432 
  433         /* Schedule another check one second from now. */
  434         callout_reset(&sc->xae_callout, hz, xae_tick, sc);
  435 }
  436 
  437 static void
  438 xae_init_locked(struct xae_softc *sc)
  439 {
  440         struct ifnet *ifp;
  441 
  442         XAE_ASSERT_LOCKED(sc);
  443 
  444         ifp = sc->ifp;
  445         if (ifp->if_drv_flags & IFF_DRV_RUNNING)
  446                 return;
  447 
  448         ifp->if_drv_flags |= IFF_DRV_RUNNING;
  449 
  450         xae_setup_rxfilter(sc);
  451 
  452         /* Enable the transmitter */
  453         WRITE4(sc, XAE_TC, TC_TX);
  454 
  455         /* Enable the receiver. */
  456         WRITE4(sc, XAE_RCW1, RCW1_RX);
  457 
  458         /*
  459          * Call mii_mediachg() which will call back into xae_miibus_statchg()
  460          * to set up the remaining config registers based on current media.
  461          */
  462         mii_mediachg(sc->mii_softc);
  463         callout_reset(&sc->xae_callout, hz, xae_tick, sc);
  464 }
  465 
  466 static void
  467 xae_init(void *arg)
  468 {
  469         struct xae_softc *sc;
  470 
  471         sc = arg;
  472 
  473         XAE_LOCK(sc);
  474         xae_init_locked(sc);
  475         XAE_UNLOCK(sc);
  476 }
  477 
  478 static void
  479 xae_media_status(struct ifnet * ifp, struct ifmediareq *ifmr)
  480 {
  481         struct xae_softc *sc;
  482         struct mii_data *mii;
  483 
  484         sc = ifp->if_softc;
  485         mii = sc->mii_softc;
  486 
  487         XAE_LOCK(sc);
  488         mii_pollstat(mii);
  489         ifmr->ifm_active = mii->mii_media_active;
  490         ifmr->ifm_status = mii->mii_media_status;
  491         XAE_UNLOCK(sc);
  492 }
  493 
  494 static int
  495 xae_media_change_locked(struct xae_softc *sc)
  496 {
  497 
  498         return (mii_mediachg(sc->mii_softc));
  499 }
  500 
  501 static int
  502 xae_media_change(struct ifnet * ifp)
  503 {
  504         struct xae_softc *sc;
  505         int error;
  506 
  507         sc = ifp->if_softc;
  508 
  509         XAE_LOCK(sc);
  510         error = xae_media_change_locked(sc);
  511         XAE_UNLOCK(sc);
  512 
  513         return (error);
  514 }
  515 
  516 static u_int
  517 xae_write_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
  518 {
  519         struct xae_softc *sc = arg;
  520         uint32_t reg;
  521         uint8_t *ma;
  522 
  523         if (cnt >= XAE_MULTICAST_TABLE_SIZE)
  524                 return (1);
  525 
  526         ma = LLADDR(sdl);
  527 
  528         reg = READ4(sc, XAE_FFC) & 0xffffff00;
  529         reg |= cnt;
  530         WRITE4(sc, XAE_FFC, reg);
  531 
  532         reg = (ma[0]);
  533         reg |= (ma[1] << 8);
  534         reg |= (ma[2] << 16);
  535         reg |= (ma[3] << 24);
  536         WRITE4(sc, XAE_FFV(0), reg);
  537 
  538         reg = ma[4];
  539         reg |= ma[5] << 8;
  540         WRITE4(sc, XAE_FFV(1), reg);
  541 
  542         return (1);
  543 }
  544 
  545 static void
  546 xae_setup_rxfilter(struct xae_softc *sc)
  547 {
  548         struct ifnet *ifp;
  549         uint32_t reg;
  550 
  551         XAE_ASSERT_LOCKED(sc);
  552 
  553         ifp = sc->ifp;
  554 
  555         /*
  556          * Set the multicast (group) filter hash.
  557          */
  558         if ((ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
  559                 reg = READ4(sc, XAE_FFC);
  560                 reg |= FFC_PM;
  561                 WRITE4(sc, XAE_FFC, reg);
  562         } else {
  563                 reg = READ4(sc, XAE_FFC);
  564                 reg &= ~FFC_PM;
  565                 WRITE4(sc, XAE_FFC, reg);
  566 
  567                 if_foreach_llmaddr(ifp, xae_write_maddr, sc);
  568         }
  569 
  570         /*
  571          * Set the primary address.
  572          */
  573         reg = sc->macaddr[0];
  574         reg |= (sc->macaddr[1] << 8);
  575         reg |= (sc->macaddr[2] << 16);
  576         reg |= (sc->macaddr[3] << 24);
  577         WRITE4(sc, XAE_UAW0, reg);
  578 
  579         reg = sc->macaddr[4];
  580         reg |= (sc->macaddr[5] << 8);
  581         WRITE4(sc, XAE_UAW1, reg);
  582 }
  583 
  584 static int
  585 xae_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  586 {
  587         struct xae_softc *sc;
  588         struct mii_data *mii;
  589         struct ifreq *ifr;
  590         int mask, error;
  591 
  592         sc = ifp->if_softc;
  593         ifr = (struct ifreq *)data;
  594 
  595         error = 0;
  596         switch (cmd) {
  597         case SIOCSIFFLAGS:
  598                 XAE_LOCK(sc);
  599                 if (ifp->if_flags & IFF_UP) {
  600                         if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
  601                                 if ((ifp->if_flags ^ sc->if_flags) &
  602                                     (IFF_PROMISC | IFF_ALLMULTI))
  603                                         xae_setup_rxfilter(sc);
  604                         } else {
  605                                 if (!sc->is_detaching)
  606                                         xae_init_locked(sc);
  607                         }
  608                 } else {
  609                         if (ifp->if_drv_flags & IFF_DRV_RUNNING)
  610                                 xae_stop_locked(sc);
  611                 }
  612                 sc->if_flags = ifp->if_flags;
  613                 XAE_UNLOCK(sc);
  614                 break;
  615         case SIOCADDMULTI:
  616         case SIOCDELMULTI:
  617                 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
  618                         XAE_LOCK(sc);
  619                         xae_setup_rxfilter(sc);
  620                         XAE_UNLOCK(sc);
  621                 }
  622                 break;
  623         case SIOCSIFMEDIA:
  624         case SIOCGIFMEDIA:
  625                 mii = sc->mii_softc;
  626                 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
  627                 break;
  628         case SIOCSIFCAP:
  629                 mask = ifp->if_capenable ^ ifr->ifr_reqcap;
  630                 if (mask & IFCAP_VLAN_MTU) {
  631                         /* No work to do except acknowledge the change took */
  632                         ifp->if_capenable ^= IFCAP_VLAN_MTU;
  633                 }
  634                 break;
  635 
  636         default:
  637                 error = ether_ioctl(ifp, cmd, data);
  638                 break;
  639         }
  640 
  641         return (error);
  642 }
  643 
  644 static void
  645 xae_intr(void *arg)
  646 {
  647 
  648 }
  649 
  650 static int
  651 xae_get_hwaddr(struct xae_softc *sc, uint8_t *hwaddr)
  652 {
  653         phandle_t node;
  654         int len;
  655 
  656         node = ofw_bus_get_node(sc->dev);
  657 
  658         /* Check if there is property */
  659         if ((len = OF_getproplen(node, "local-mac-address")) <= 0)
  660                 return (EINVAL);
  661 
  662         if (len != ETHER_ADDR_LEN)
  663                 return (EINVAL);
  664 
  665         OF_getprop(node, "local-mac-address", hwaddr,
  666             ETHER_ADDR_LEN);
  667 
  668         return (0);
  669 }
  670 
  671 static int
  672 mdio_wait(struct xae_softc *sc)
  673 {
  674         uint32_t reg;
  675         int timeout;
  676 
  677         timeout = 200;
  678 
  679         do {
  680                 reg = READ4(sc, XAE_MDIO_CTRL);
  681                 if (reg & MDIO_CTRL_READY)
  682                         break;
  683                 DELAY(1);
  684         } while (timeout--);
  685 
  686         if (timeout <= 0) {
  687                 printf("Failed to get MDIO ready\n");
  688                 return (1);
  689         }
  690 
  691         return (0);
  692 }
  693 
  694 static int
  695 xae_miibus_read_reg(device_t dev, int phy, int reg)
  696 {
  697         struct xae_softc *sc;
  698         uint32_t mii;
  699         int rv;
  700 
  701         sc = device_get_softc(dev);
  702 
  703         if (mdio_wait(sc))
  704                 return (0);
  705 
  706         mii = MDIO_CTRL_TX_OP_READ | MDIO_CTRL_INITIATE;
  707         mii |= (reg << MDIO_TX_REGAD_S);
  708         mii |= (phy << MDIO_TX_PHYAD_S);
  709 
  710         WRITE4(sc, XAE_MDIO_CTRL, mii);
  711 
  712         if (mdio_wait(sc))
  713                 return (0);
  714 
  715         rv = READ4(sc, XAE_MDIO_READ);
  716 
  717         return (rv);
  718 }
  719 
  720 static int
  721 xae_miibus_write_reg(device_t dev, int phy, int reg, int val)
  722 {
  723         struct xae_softc *sc;
  724         uint32_t mii;
  725 
  726         sc = device_get_softc(dev);
  727 
  728         if (mdio_wait(sc))
  729                 return (1);
  730 
  731         mii = MDIO_CTRL_TX_OP_WRITE | MDIO_CTRL_INITIATE;
  732         mii |= (reg << MDIO_TX_REGAD_S);
  733         mii |= (phy << MDIO_TX_PHYAD_S);
  734 
  735         WRITE4(sc, XAE_MDIO_WRITE, val);
  736         WRITE4(sc, XAE_MDIO_CTRL, mii);
  737 
  738         if (mdio_wait(sc))
  739                 return (1);
  740 
  741         return (0);
  742 }
  743 
  744 static void
  745 xae_phy_fixup(struct xae_softc *sc)
  746 {
  747         uint32_t reg;
  748 
  749         do {
  750                 WRITE_TI_EREG(sc, DP83867_SGMIICTL1, SGMIICTL1_SGMII_6W);
  751                 PHY_WR(sc, DP83867_PHYCR, PHYCR_SGMII_EN);
  752 
  753                 reg = PHY_RD(sc, DP83867_CFG2);
  754                 reg &= ~CFG2_SPEED_OPT_ATTEMPT_CNT_M;
  755                 reg |= (CFG2_SPEED_OPT_ATTEMPT_CNT_4);
  756                 reg |= CFG2_INTERRUPT_POLARITY;
  757                 reg |= CFG2_SPEED_OPT_ENHANCED_EN;
  758                 reg |= CFG2_SPEED_OPT_10M_EN;
  759                 PHY_WR(sc, DP83867_CFG2, reg);
  760 
  761                 WRITE_TI_EREG(sc, DP83867_CFG4, CFG4_SGMII_TMR);
  762                 PHY_WR(sc, MII_BMCR,
  763                     BMCR_AUTOEN | BMCR_FDX | BMCR_SPEED1 | BMCR_RESET);
  764         } while (PHY1_RD(sc, MII_BMCR) == 0x0ffff);
  765 
  766         do {
  767                 PHY1_WR(sc, MII_BMCR,
  768                     BMCR_AUTOEN | BMCR_FDX | BMCR_SPEED1 | BMCR_STARTNEG);
  769                 DELAY(40000);
  770         } while ((PHY1_RD(sc, MII_BMSR) & BMSR_ACOMP) == 0);
  771 }
  772 
  773 static int
  774 get_xdma_std(struct xae_softc *sc)
  775 {
  776 
  777         sc->xdma_tx = xdma_ofw_get(sc->dev, "tx");
  778         if (sc->xdma_tx == NULL)
  779                 return (ENXIO);
  780 
  781         sc->xdma_rx = xdma_ofw_get(sc->dev, "rx");
  782         if (sc->xdma_rx == NULL) {
  783                 xdma_put(sc->xdma_tx);
  784                 return (ENXIO);
  785         }
  786 
  787         return (0);
  788 }
  789 
  790 static int
  791 get_xdma_axistream(struct xae_softc *sc)
  792 {
  793         struct axidma_fdt_data *data;
  794         device_t dma_dev;
  795         phandle_t node;
  796         pcell_t prop;
  797         size_t len;
  798 
  799         node = ofw_bus_get_node(sc->dev);
  800         len = OF_getencprop(node, "axistream-connected", &prop, sizeof(prop));
  801         if (len != sizeof(prop)) {
  802                 device_printf(sc->dev,
  803                     "%s: Couldn't get axistream-connected prop.\n", __func__);
  804                 return (ENXIO);
  805         }
  806         dma_dev = OF_device_from_xref(prop);
  807         if (dma_dev == NULL) {
  808                 device_printf(sc->dev, "Could not get DMA device by xref.\n");
  809                 return (ENXIO);
  810         }
  811 
  812         sc->xdma_tx = xdma_get(sc->dev, dma_dev);
  813         if (sc->xdma_tx == NULL) {
  814                 device_printf(sc->dev, "Could not find DMA controller.\n");
  815                 return (ENXIO);
  816         }
  817         data = malloc(sizeof(struct axidma_fdt_data),
  818             M_DEVBUF, (M_WAITOK | M_ZERO));
  819         data->id = AXIDMA_TX_CHAN;
  820         sc->xdma_tx->data = data;
  821 
  822         sc->xdma_rx = xdma_get(sc->dev, dma_dev);
  823         if (sc->xdma_rx == NULL) {
  824                 device_printf(sc->dev, "Could not find DMA controller.\n");
  825                 return (ENXIO);
  826         }
  827         data = malloc(sizeof(struct axidma_fdt_data),
  828             M_DEVBUF, (M_WAITOK | M_ZERO));
  829         data->id = AXIDMA_RX_CHAN;
  830         sc->xdma_rx->data = data;
  831 
  832         return (0);
  833 }
  834 
  835 static int
  836 setup_xdma(struct xae_softc *sc)
  837 {
  838         device_t dev;
  839         vmem_t *vmem;
  840         int error;
  841 
  842         dev = sc->dev;
  843 
  844         /* Get xDMA controller */   
  845         error = get_xdma_std(sc);
  846 
  847         if (error) {
  848                 device_printf(sc->dev,
  849                     "Fallback to axistream-connected property\n");
  850                 error = get_xdma_axistream(sc);
  851         }
  852 
  853         if (error) {
  854                 device_printf(dev, "Could not find xDMA controllers.\n");
  855                 return (ENXIO);
  856         }
  857 
  858         /* Alloc xDMA TX virtual channel. */
  859         sc->xchan_tx = xdma_channel_alloc(sc->xdma_tx, 0);
  860         if (sc->xchan_tx == NULL) {
  861                 device_printf(dev, "Can't alloc virtual DMA TX channel.\n");
  862                 return (ENXIO);
  863         }
  864 
  865         /* Setup interrupt handler. */
  866         error = xdma_setup_intr(sc->xchan_tx, 0,
  867             xae_xdma_tx_intr, sc, &sc->ih_tx);
  868         if (error) {
  869                 device_printf(sc->dev,
  870                     "Can't setup xDMA TX interrupt handler.\n");
  871                 return (ENXIO);
  872         }
  873 
  874         /* Alloc xDMA RX virtual channel. */
  875         sc->xchan_rx = xdma_channel_alloc(sc->xdma_rx, 0);
  876         if (sc->xchan_rx == NULL) {
  877                 device_printf(dev, "Can't alloc virtual DMA RX channel.\n");
  878                 return (ENXIO);
  879         }
  880 
  881         /* Setup interrupt handler. */
  882         error = xdma_setup_intr(sc->xchan_rx, XDMA_INTR_NET,
  883             xae_xdma_rx_intr, sc, &sc->ih_rx);
  884         if (error) {
  885                 device_printf(sc->dev,
  886                     "Can't setup xDMA RX interrupt handler.\n");
  887                 return (ENXIO);
  888         }
  889 
  890         /* Setup bounce buffer */
  891         vmem = xdma_get_memory(dev);
  892         if (vmem) {
  893                 xchan_set_memory(sc->xchan_tx, vmem);
  894                 xchan_set_memory(sc->xchan_rx, vmem);
  895         }
  896 
  897         xdma_prep_sg(sc->xchan_tx,
  898             TX_QUEUE_SIZE,      /* xchan requests queue size */
  899             MCLBYTES,   /* maxsegsize */
  900             8,          /* maxnsegs */
  901             16,         /* alignment */
  902             0,          /* boundary */
  903             BUS_SPACE_MAXADDR_32BIT,
  904             BUS_SPACE_MAXADDR);
  905 
  906         xdma_prep_sg(sc->xchan_rx,
  907             RX_QUEUE_SIZE,      /* xchan requests queue size */
  908             MCLBYTES,   /* maxsegsize */
  909             1,          /* maxnsegs */
  910             16,         /* alignment */
  911             0,          /* boundary */
  912             BUS_SPACE_MAXADDR_32BIT,
  913             BUS_SPACE_MAXADDR);
  914 
  915         return (0);
  916 }
  917 
  918 static int
  919 xae_probe(device_t dev)
  920 {
  921 
  922         if (!ofw_bus_status_okay(dev))
  923                 return (ENXIO);
  924 
  925         if (!ofw_bus_is_compatible(dev, "xlnx,axi-ethernet-1.00.a"))
  926                 return (ENXIO);
  927 
  928         device_set_desc(dev, "Xilinx AXI Ethernet");
  929 
  930         return (BUS_PROBE_DEFAULT);
  931 }
  932 
  933 static int
  934 xae_attach(device_t dev)
  935 {
  936         struct xae_softc *sc;
  937         struct ifnet *ifp;
  938         phandle_t node;
  939         uint32_t reg;
  940         int error;
  941 
  942         sc = device_get_softc(dev);
  943         sc->dev = dev;
  944         node = ofw_bus_get_node(dev);
  945 
  946         if (setup_xdma(sc) != 0) {
  947                 device_printf(dev, "Could not setup xDMA.\n");
  948                 return (ENXIO);
  949         }
  950 
  951         mtx_init(&sc->mtx, device_get_nameunit(sc->dev),
  952             MTX_NETWORK_LOCK, MTX_DEF);
  953 
  954         sc->br = buf_ring_alloc(BUFRING_SIZE, M_DEVBUF,
  955             M_NOWAIT, &sc->mtx);
  956         if (sc->br == NULL)
  957                 return (ENOMEM);
  958 
  959         if (bus_alloc_resources(dev, xae_spec, sc->res)) {
  960                 device_printf(dev, "could not allocate resources\n");
  961                 return (ENXIO);
  962         }
  963 
  964         /* Memory interface */
  965         sc->bst = rman_get_bustag(sc->res[0]);
  966         sc->bsh = rman_get_bushandle(sc->res[0]);
  967 
  968         device_printf(sc->dev, "Identification: %x\n",
  969             READ4(sc, XAE_IDENT));
  970 
  971         /* Get MAC addr */
  972         if (xae_get_hwaddr(sc, sc->macaddr)) {
  973                 device_printf(sc->dev, "can't get mac\n");
  974                 return (ENXIO);
  975         }
  976 
  977         /* Enable MII clock */
  978         reg = (MDIO_CLK_DIV_DEFAULT << MDIO_SETUP_CLK_DIV_S);
  979         reg |= MDIO_SETUP_ENABLE;
  980         WRITE4(sc, XAE_MDIO_SETUP, reg);
  981         if (mdio_wait(sc))
  982                 return (ENXIO);
  983 
  984         callout_init_mtx(&sc->xae_callout, &sc->mtx, 0);
  985 
  986         /* Setup interrupt handler. */
  987         error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_NET | INTR_MPSAFE,
  988             NULL, xae_intr, sc, &sc->intr_cookie);
  989         if (error != 0) {
  990                 device_printf(dev, "could not setup interrupt handler.\n");
  991                 return (ENXIO);
  992         }
  993 
  994         /* Set up the ethernet interface. */
  995         sc->ifp = ifp = if_alloc(IFT_ETHER);
  996         if (ifp == NULL) {
  997                 device_printf(dev, "could not allocate ifp.\n");
  998                 return (ENXIO);
  999         }
 1000 
 1001         ifp->if_softc = sc;
 1002         if_initname(ifp, device_get_name(dev), device_get_unit(dev));
 1003         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
 1004         ifp->if_capabilities = IFCAP_VLAN_MTU;
 1005         ifp->if_capenable = ifp->if_capabilities;
 1006         ifp->if_transmit = xae_transmit;
 1007         ifp->if_qflush = xae_qflush;
 1008         ifp->if_ioctl = xae_ioctl;
 1009         ifp->if_init = xae_init;
 1010         IFQ_SET_MAXLEN(&ifp->if_snd, TX_DESC_COUNT - 1);
 1011         ifp->if_snd.ifq_drv_maxlen = TX_DESC_COUNT - 1;
 1012         IFQ_SET_READY(&ifp->if_snd);
 1013 
 1014         if (xae_get_phyaddr(node, &sc->phy_addr) != 0)
 1015                 return (ENXIO);
 1016 
 1017         /* Attach the mii driver. */
 1018         error = mii_attach(dev, &sc->miibus, ifp, xae_media_change,
 1019             xae_media_status, BMSR_DEFCAPMASK, sc->phy_addr,
 1020             MII_OFFSET_ANY, 0);
 1021 
 1022         if (error != 0) {
 1023                 device_printf(dev, "PHY attach failed\n");
 1024                 return (ENXIO);
 1025         }
 1026         sc->mii_softc = device_get_softc(sc->miibus);
 1027 
 1028         /* Apply vcu118 workaround. */
 1029         if (OF_getproplen(node, "xlnx,vcu118") >= 0)
 1030                 xae_phy_fixup(sc);
 1031 
 1032         /* All ready to run, attach the ethernet interface. */
 1033         ether_ifattach(ifp, sc->macaddr);
 1034         sc->is_attached = true;
 1035 
 1036         xae_rx_enqueue(sc, NUM_RX_MBUF);
 1037         xdma_queue_submit(sc->xchan_rx);
 1038 
 1039         return (0);
 1040 }
 1041 
 1042 static int
 1043 xae_detach(device_t dev)
 1044 {
 1045         struct xae_softc *sc;
 1046         struct ifnet *ifp;
 1047 
 1048         sc = device_get_softc(dev);
 1049 
 1050         KASSERT(mtx_initialized(&sc->mtx), ("%s: mutex not initialized",
 1051             device_get_nameunit(dev)));
 1052 
 1053         ifp = sc->ifp;
 1054 
 1055         /* Only cleanup if attach succeeded. */
 1056         if (device_is_attached(dev)) {
 1057                 XAE_LOCK(sc);
 1058                 xae_stop_locked(sc);
 1059                 XAE_UNLOCK(sc);
 1060                 callout_drain(&sc->xae_callout);
 1061                 ether_ifdetach(ifp);
 1062         }
 1063 
 1064         if (sc->miibus != NULL)
 1065                 device_delete_child(dev, sc->miibus);
 1066 
 1067         if (ifp != NULL)
 1068                 if_free(ifp);
 1069 
 1070         mtx_destroy(&sc->mtx);
 1071 
 1072         bus_teardown_intr(dev, sc->res[1], sc->intr_cookie);
 1073 
 1074         bus_release_resources(dev, xae_spec, sc->res);
 1075 
 1076         xdma_channel_free(sc->xchan_tx);
 1077         xdma_channel_free(sc->xchan_rx);
 1078         xdma_put(sc->xdma_tx);
 1079         xdma_put(sc->xdma_rx);
 1080 
 1081         return (0);
 1082 }
 1083 
 1084 static void
 1085 xae_miibus_statchg(device_t dev)
 1086 {
 1087         struct xae_softc *sc;
 1088         struct mii_data *mii;
 1089         uint32_t reg;
 1090 
 1091         /*
 1092          * Called by the MII bus driver when the PHY establishes
 1093          * link to set the MAC interface registers.
 1094          */
 1095 
 1096         sc = device_get_softc(dev);
 1097 
 1098         XAE_ASSERT_LOCKED(sc);
 1099 
 1100         mii = sc->mii_softc;
 1101 
 1102         if (mii->mii_media_status & IFM_ACTIVE)
 1103                 sc->link_is_up = true;
 1104         else
 1105                 sc->link_is_up = false;
 1106 
 1107         switch (IFM_SUBTYPE(mii->mii_media_active)) {
 1108         case IFM_1000_T:
 1109         case IFM_1000_SX:
 1110                 reg = SPEED_1000;
 1111                 break;
 1112         case IFM_100_TX:
 1113                 reg = SPEED_100;
 1114                 break;
 1115         case IFM_10_T:
 1116                 reg = SPEED_10;
 1117                 break;
 1118         case IFM_NONE:
 1119                 sc->link_is_up = false;
 1120                 return;
 1121         default:
 1122                 sc->link_is_up = false;
 1123                 device_printf(dev, "Unsupported media %u\n",
 1124                     IFM_SUBTYPE(mii->mii_media_active));
 1125                 return;
 1126         }
 1127 
 1128         WRITE4(sc, XAE_SPEED, reg);
 1129 }
 1130 
 1131 static device_method_t xae_methods[] = {
 1132         DEVMETHOD(device_probe,         xae_probe),
 1133         DEVMETHOD(device_attach,        xae_attach),
 1134         DEVMETHOD(device_detach,        xae_detach),
 1135 
 1136         /* MII Interface */
 1137         DEVMETHOD(miibus_readreg,       xae_miibus_read_reg),
 1138         DEVMETHOD(miibus_writereg,      xae_miibus_write_reg),
 1139         DEVMETHOD(miibus_statchg,       xae_miibus_statchg),
 1140         { 0, 0 }
 1141 };
 1142 
 1143 driver_t xae_driver = {
 1144         "xae",
 1145         xae_methods,
 1146         sizeof(struct xae_softc),
 1147 };
 1148 
 1149 DRIVER_MODULE(xae, simplebus, xae_driver, 0, 0);
 1150 DRIVER_MODULE(miibus, xae, miibus_driver, 0, 0);
 1151 
 1152 MODULE_DEPEND(xae, ether, 1, 1, 1);
 1153 MODULE_DEPEND(xae, miibus, 1, 1, 1);

Cache object: 74ec552e032c6610a8a6cc7242f2289d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.