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/etherswitch/ar40xx/ar40xx_hw_atu.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-FreeBSD
    3  *
    4  * Copyright (c) 2022 Adrian Chadd <adrian@FreeBSD.org>.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/param.h>
   29 #include <sys/bus.h>
   30 #include <sys/errno.h>
   31 #include <sys/kernel.h>
   32 #include <sys/malloc.h>
   33 #include <sys/module.h>
   34 #include <sys/socket.h>
   35 #include <sys/sockio.h>
   36 #include <sys/sysctl.h>
   37 #include <sys/systm.h>
   38 
   39 #include <net/if.h>
   40 #include <net/if_var.h>
   41 #include <net/if_arp.h>
   42 #include <net/ethernet.h>
   43 #include <net/if_dl.h>
   44 #include <net/if_media.h>
   45 #include <net/if_types.h>
   46 
   47 #include <machine/bus.h>
   48 #include <dev/iicbus/iic.h>
   49 #include <dev/iicbus/iiconf.h>
   50 #include <dev/iicbus/iicbus.h>
   51 #include <dev/mii/mii.h>
   52 #include <dev/mii/miivar.h>
   53 #include <dev/mdio/mdio.h>
   54 #include <dev/extres/clk/clk.h>
   55 #include <dev/extres/hwreset/hwreset.h>
   56 
   57 #include <dev/fdt/fdt_common.h>
   58 #include <dev/ofw/ofw_bus.h>
   59 #include <dev/ofw/ofw_bus_subr.h>
   60 
   61 #include <dev/etherswitch/etherswitch.h>
   62 
   63 #include <dev/etherswitch/ar40xx/ar40xx_var.h>
   64 #include <dev/etherswitch/ar40xx/ar40xx_reg.h>
   65 #include <dev/etherswitch/ar40xx/ar40xx_hw.h>
   66 #include <dev/etherswitch/ar40xx/ar40xx_hw_atu.h>
   67 #include <dev/etherswitch/ar40xx/ar40xx_debug.h>
   68 
   69 #include "mdio_if.h"
   70 #include "miibus_if.h"
   71 #include "etherswitch_if.h"
   72 
   73 int
   74 ar40xx_hw_atu_wait_busy(struct ar40xx_softc *sc)
   75 {
   76         int ret;
   77 
   78         ret = ar40xx_hw_wait_bit(sc, AR40XX_REG_ATU_FUNC,
   79             AR40XX_ATU_FUNC_BUSY, 0);
   80         return (ret);
   81 }
   82 
   83 int
   84 ar40xx_hw_atu_flush_all(struct ar40xx_softc *sc)
   85 {
   86         int ret;
   87 
   88         AR40XX_LOCK_ASSERT(sc);
   89 
   90         AR40XX_DPRINTF(sc, AR40XX_DBG_ATU_OP, "%s: called\n", __func__);
   91         ret = ar40xx_hw_atu_wait_busy(sc);
   92         if (ret != 0)
   93                 return (ret);
   94 
   95         AR40XX_REG_WRITE(sc, AR40XX_REG_ATU_FUNC,
   96             AR40XX_ATU_FUNC_OP_FLUSH
   97             | AR40XX_ATU_FUNC_BUSY);
   98         AR40XX_REG_BARRIER_WRITE(sc);
   99 
  100         return (ret);
  101 }
  102 
  103 int
  104 ar40xx_hw_atu_flush_port(struct ar40xx_softc *sc, int port)
  105 {
  106         uint32_t val;
  107         int ret;
  108 
  109         AR40XX_LOCK_ASSERT(sc);
  110 
  111         AR40XX_DPRINTF(sc, AR40XX_DBG_ATU_OP, "%s: called, port=%d\n",
  112              __func__, port);
  113 
  114         if (port >= AR40XX_NUM_PORTS) {
  115                 return (EINVAL);
  116         }
  117 
  118         ret = ar40xx_hw_atu_wait_busy(sc);
  119         if (ret != 0)
  120                 return (ret);
  121 
  122         val = AR40XX_ATU_FUNC_OP_FLUSH_UNICAST;
  123         val |= (port << AR40XX_ATU_FUNC_PORT_NUM_S)
  124             & AR40XX_ATU_FUNC_PORT_NUM;
  125 
  126         AR40XX_REG_WRITE(sc, AR40XX_REG_ATU_FUNC,
  127             val | AR40XX_ATU_FUNC_BUSY);
  128         AR40XX_REG_BARRIER_WRITE(sc);
  129 
  130         return (0);
  131 }
  132 
  133 int
  134 ar40xx_hw_atu_fetch_entry(struct ar40xx_softc *sc, etherswitch_atu_entry_t *e,
  135     int atu_fetch_op)
  136 {
  137         uint32_t ret0, ret1, ret2, val;
  138         int ret;
  139 
  140         AR40XX_LOCK_ASSERT(sc);
  141 
  142         switch (atu_fetch_op) {
  143         case 0:
  144                 /* Initialise things for the first fetch */
  145 
  146                 AR40XX_DPRINTF(sc, AR40XX_DBG_ATU_OP,
  147                     "%s: initializing\n", __func__);
  148 
  149                 ret = ar40xx_hw_atu_wait_busy(sc);
  150                 if (ret != 0)
  151                         return (ret);
  152 
  153                 AR40XX_REG_WRITE(sc, AR40XX_REG_ATU_FUNC,
  154                     AR40XX_ATU_FUNC_OP_GET_NEXT);
  155                 AR40XX_REG_WRITE(sc, AR40XX_REG_ATU_DATA0, 0);
  156                 AR40XX_REG_WRITE(sc, AR40XX_REG_ATU_DATA1, 0);
  157                 AR40XX_REG_WRITE(sc, AR40XX_REG_ATU_DATA2, 0);
  158                 AR40XX_REG_BARRIER_WRITE(sc);
  159 
  160                 return (0);
  161         case 1:
  162                 AR40XX_DPRINTF(sc, AR40XX_DBG_ATU_OP,
  163                     "%s: reading next\n", __func__);
  164                 /*
  165                  * Attempt to read the next address entry; don't modify what
  166                  * is there in these registers as its used for the next fetch
  167                  */
  168                 ret = ar40xx_hw_atu_wait_busy(sc);
  169                 if (ret != 0)
  170                         return (ret);
  171 
  172                 /* Begin the next read event; not modifying anything */
  173                 AR40XX_REG_BARRIER_READ(sc);
  174                 val = AR40XX_REG_READ(sc, AR40XX_REG_ATU_FUNC);
  175                 val |= AR40XX_ATU_FUNC_BUSY;
  176                 AR40XX_REG_WRITE(sc, AR40XX_REG_ATU_FUNC, val);
  177                 AR40XX_REG_BARRIER_WRITE(sc);
  178 
  179                 /* Wait for it to complete */
  180                 ret = ar40xx_hw_atu_wait_busy(sc);
  181                 if (ret != 0)
  182                         return (ret);
  183 
  184                 /* Fetch the ethernet address and ATU status */
  185                 AR40XX_REG_BARRIER_READ(sc);
  186                 ret0 = AR40XX_REG_READ(sc, AR40XX_REG_ATU_DATA0);
  187                 ret1 = AR40XX_REG_READ(sc, AR40XX_REG_ATU_DATA1);
  188                 ret2 = AR40XX_REG_READ(sc, AR40XX_REG_ATU_DATA2);
  189 
  190                 /* If the status is zero, then we're done */
  191                 if (MS(ret2, AR40XX_ATU_FUNC_DATA2_STATUS) == 0)
  192                         return (ENOENT);
  193 
  194                 /* MAC address */
  195                 e->es_macaddr[5] = MS(ret0, AR40XX_ATU_DATA0_MAC_ADDR3);
  196                 e->es_macaddr[4] = MS(ret0, AR40XX_ATU_DATA0_MAC_ADDR2);
  197                 e->es_macaddr[3] = MS(ret0, AR40XX_ATU_DATA0_MAC_ADDR1);
  198                 e->es_macaddr[2] = MS(ret0, AR40XX_ATU_DATA0_MAC_ADDR0);
  199                 e->es_macaddr[0] = MS(ret1, AR40XX_ATU_DATA1_MAC_ADDR5);
  200                 e->es_macaddr[1] = MS(ret1, AR40XX_ATU_DATA1_MAC_ADDR4);
  201 
  202                 /* Bitmask of ports this entry is for */
  203                 e->es_portmask = MS(ret1, AR40XX_ATU_DATA1_DEST_PORT);
  204 
  205                 /* TODO: other flags that are interesting */
  206 
  207                 AR40XX_DPRINTF(sc, AR40XX_DBG_ATU_OP,
  208                     "%s: MAC %6D portmask 0x%08x\n",
  209                     __func__,
  210                     e->es_macaddr, ":", e->es_portmask);
  211                 return (0);
  212         default:
  213                 return (EINVAL);
  214         }
  215         return (EINVAL);
  216 }

Cache object: 116598b72c2c926d0b35f79ed629c3c7


[ 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.