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/mips/cavium/octe/ethernet-common.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-3-Clause
    3 
    4 Copyright (c) 2003-2007  Cavium Networks (support@cavium.com). All rights
    5 reserved.
    6 
    7 Redistribution and use in source and binary forms, with or without
    8 modification, are permitted provided that the following conditions are
    9 met:
   10 
   11     * Redistributions of source code must retain the above copyright
   12       notice, this list of conditions and the following disclaimer.
   13 
   14     * Redistributions in binary form must reproduce the above
   15       copyright notice, this list of conditions and the following
   16       disclaimer in the documentation and/or other materials provided
   17       with the distribution.
   18 
   19     * Neither the name of Cavium Networks nor the names of
   20       its contributors may be used to endorse or promote products
   21       derived from this software without specific prior written
   22       permission.
   23 
   24 This Software, including technical data, may be subject to U.S. export  control laws, including the U.S. Export Administration Act and its  associated regulations, and may be subject to export or import  regulations in other countries.
   25 
   26 TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
   27 AND WITH ALL FAULTS AND CAVIUM  NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
   28 
   29 *************************************************************************/
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/bus.h>
   37 #include <sys/endian.h>
   38 #include <sys/kernel.h>
   39 #include <sys/mbuf.h>
   40 #include <sys/socket.h>
   41 
   42 #include <net/ethernet.h>
   43 #include <net/if.h>
   44 #include <net/if_var.h>
   45 
   46 #include "wrapper-cvmx-includes.h"
   47 #include "ethernet-headers.h"
   48 
   49 static uint64_t cvm_oct_mac_addr = 0;
   50 static uint32_t cvm_oct_mac_addr_offset = 0;
   51 
   52 /**
   53  * Set the multicast list. Currently unimplemented.
   54  *
   55  * @param dev    Device to work on
   56  */
   57 void cvm_oct_common_set_multicast_list(struct ifnet *ifp)
   58 {
   59         cvmx_gmxx_prtx_cfg_t gmx_cfg;
   60         cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
   61         int interface = INTERFACE(priv->port);
   62         int index = INDEX(priv->port);
   63 
   64         if ((interface < 2) && (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_SPI)) {
   65                 cvmx_gmxx_rxx_adr_ctl_t control;
   66                 control.u64 = 0;
   67                 control.s.bcst = 1;     /* Allow broadcast MAC addresses */
   68 
   69                 if (/*ifp->mc_list || */(ifp->if_flags&IFF_ALLMULTI) ||
   70                     (ifp->if_flags & IFF_PROMISC))
   71                         control.s.mcst = 2; /* Force accept multicast packets */
   72                 else
   73                         control.s.mcst = 1; /* Force reject multicat packets */
   74 
   75                 if (ifp->if_flags & IFF_PROMISC)
   76                         control.s.cam_mode = 0; /* Reject matches if promisc. Since CAM is shut off, should accept everything */
   77                 else
   78                         control.s.cam_mode = 1; /* Filter packets based on the CAM */
   79 
   80                 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
   81                 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64 & ~1ull);
   82 
   83                 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CTL(index, interface), control.u64);
   84                 if (ifp->if_flags&IFF_PROMISC)
   85                         cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN(index, interface), 0);
   86                 else
   87                         cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN(index, interface), 1);
   88 
   89                 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
   90         }
   91 }
   92 
   93 /**
   94  * Assign a MAC addres from the pool of available MAC addresses
   95  * Can return as either a 64-bit value and/or 6 octets.
   96  *
   97  * @param macp    Filled in with the assigned address if non-NULL
   98  * @param octets  Filled in with the assigned address if non-NULL
   99  * @return Zero on success
  100  */
  101 int cvm_assign_mac_address(uint64_t *macp, uint8_t *octets)
  102 {
  103         /* Initialize from global MAC address base; fail if not set */
  104         if (cvm_oct_mac_addr == 0) {
  105                 memcpy((uint8_t *)&cvm_oct_mac_addr + 2,
  106                     cvmx_sysinfo_get()->mac_addr_base, 6);
  107 
  108                 if (cvm_oct_mac_addr == 0)
  109                         return ENXIO;
  110 
  111                 cvm_oct_mac_addr_offset = cvmx_mgmt_port_num_ports();
  112                 cvm_oct_mac_addr += cvm_oct_mac_addr_offset;
  113         }
  114 
  115         if (cvm_oct_mac_addr_offset >= cvmx_sysinfo_get()->mac_addr_count)
  116                 return ENXIO;       /* Out of addresses to assign */
  117 
  118         if (macp)
  119                 *macp = cvm_oct_mac_addr;
  120         if (octets)
  121                 memcpy(octets, (u_int8_t *)&cvm_oct_mac_addr + 2, 6);
  122 
  123         cvm_oct_mac_addr++;
  124         cvm_oct_mac_addr_offset++;
  125 
  126         return 0;
  127 }
  128 
  129 /**
  130  * Set the hardware MAC address for a device
  131  *
  132  * @param dev    Device to change the MAC address for
  133  * @param addr   Address structure to change it too.
  134  */
  135 void cvm_oct_common_set_mac_address(struct ifnet *ifp, const void *addr)
  136 {
  137         cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
  138         cvmx_gmxx_prtx_cfg_t gmx_cfg;
  139         int interface = INTERFACE(priv->port);
  140         int index = INDEX(priv->port);
  141 
  142         memcpy(priv->mac, addr, 6);
  143 
  144         if ((interface < 2) && (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_SPI)) {
  145                 int i;
  146                 const uint8_t *ptr = addr;
  147                 uint64_t mac = 0;
  148                 for (i = 0; i < 6; i++)
  149                         mac = (mac<<8) | (uint64_t)(ptr[i]);
  150 
  151                 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
  152                 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64 & ~1ull);
  153 
  154                 cvmx_write_csr(CVMX_GMXX_SMACX(index, interface), mac);
  155                 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM0(index, interface), ptr[0]);
  156                 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM1(index, interface), ptr[1]);
  157                 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM2(index, interface), ptr[2]);
  158                 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM3(index, interface), ptr[3]);
  159                 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM4(index, interface), ptr[4]);
  160                 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM5(index, interface), ptr[5]);
  161                 cvm_oct_common_set_multicast_list(ifp);
  162                 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
  163         }
  164 }
  165 
  166 /**
  167  * Change the link MTU. Unimplemented
  168  *
  169  * @param dev     Device to change
  170  * @param new_mtu The new MTU
  171  * @return Zero on success
  172  */
  173 int cvm_oct_common_change_mtu(struct ifnet *ifp, int new_mtu)
  174 {
  175         cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
  176         int interface = INTERFACE(priv->port);
  177         int index = INDEX(priv->port);
  178         int vlan_bytes = 4;
  179 
  180         /* Limit the MTU to make sure the ethernet packets are between 64 bytes
  181            and 65535 bytes */
  182         if ((new_mtu + 14 + 4 + vlan_bytes < 64) || (new_mtu + 14 + 4 + vlan_bytes > 65392)) {
  183                 printf("MTU must be between %d and %d.\n", 64-14-4-vlan_bytes, 65392-14-4-vlan_bytes);
  184                 return -EINVAL;
  185         }
  186         ifp->if_mtu = new_mtu;
  187 
  188         if ((interface < 2) && (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_SPI)) {
  189                 int max_packet = new_mtu + 14 + 4 + vlan_bytes; /* Add ethernet header and FCS, and VLAN if configured. */
  190 
  191                 if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) {
  192                         /* Signal errors on packets larger than the MTU */
  193                         cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX(index, interface), max_packet);
  194                 } else {
  195                         /* Set the hardware to truncate packets larger than the MTU and
  196                                 smaller the 64 bytes */
  197                         cvmx_pip_frm_len_chkx_t frm_len_chk;
  198                         frm_len_chk.u64 = 0;
  199                         frm_len_chk.s.minlen = 64;
  200                         frm_len_chk.s.maxlen = max_packet;
  201                         cvmx_write_csr(CVMX_PIP_FRM_LEN_CHKX(interface), frm_len_chk.u64);
  202                 }
  203                 /* Set the hardware to truncate packets larger than the MTU. The
  204                    jabber register must be set to a multiple of 8 bytes, so round up */
  205                 cvmx_write_csr(CVMX_GMXX_RXX_JABBER(index, interface), (max_packet + 7) & ~7u);
  206         }
  207         return 0;
  208 }
  209 
  210 /**
  211  * Enable port.
  212  */
  213 int cvm_oct_common_open(struct ifnet *ifp)
  214 {
  215         cvmx_gmxx_prtx_cfg_t gmx_cfg;
  216         cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
  217         int interface = INTERFACE(priv->port);
  218         int index = INDEX(priv->port);
  219         cvmx_helper_link_info_t link_info;
  220 
  221         gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
  222         gmx_cfg.s.en = 1;
  223         cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
  224 
  225         /*
  226          * Set the link state unless we are using MII.
  227          */
  228         if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM && priv->miibus == NULL) {
  229              link_info = cvmx_helper_link_get(priv->port);
  230              if (!link_info.s.link_up)  
  231                 if_link_state_change(ifp, LINK_STATE_DOWN);
  232              else
  233                 if_link_state_change(ifp, LINK_STATE_UP);
  234         }
  235 
  236         return 0;
  237 }
  238 
  239 /**
  240  * Disable port.
  241  */
  242 int cvm_oct_common_stop(struct ifnet *ifp)
  243 {
  244         cvmx_gmxx_prtx_cfg_t gmx_cfg;
  245         cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
  246         int interface = INTERFACE(priv->port);
  247         int index = INDEX(priv->port);
  248 
  249         gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
  250         gmx_cfg.s.en = 0;
  251         cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
  252         return 0;
  253 }
  254 
  255 /**
  256  * Poll for link status change.
  257  */
  258 void cvm_oct_common_poll(struct ifnet *ifp)
  259 {
  260         cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
  261         cvmx_helper_link_info_t link_info;
  262 
  263         /*
  264          * If this is a simulation, do nothing.
  265          */
  266         if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM)
  267                 return;
  268 
  269         /*
  270          * If there is a device-specific poll method, use it.
  271          */
  272         if (priv->poll != NULL) {
  273                 priv->poll(ifp);
  274                 return;
  275         }
  276 
  277         /*
  278          * If an MII bus is attached, don't use the Simple Executive's link
  279          * state routines.
  280          */
  281         if (priv->miibus != NULL)
  282                 return;
  283 
  284         /*
  285          * Use the Simple Executive's link state routines.
  286          */
  287         link_info = cvmx_helper_link_get(priv->port);
  288         if (link_info.u64 == priv->link_info)
  289                 return;
  290 
  291         link_info = cvmx_helper_link_autoconf(priv->port);
  292         priv->link_info = link_info.u64;
  293         priv->need_link_update = 1;
  294 }
  295 
  296 /**
  297  * Per network device initialization
  298  *
  299  * @param dev    Device to initialize
  300  * @return Zero on success
  301  */
  302 int cvm_oct_common_init(struct ifnet *ifp)
  303 {
  304         uint8_t mac[6];
  305         cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
  306 
  307         if (cvm_assign_mac_address(NULL, mac) != 0)
  308                 return ENXIO;
  309 
  310         ifp->if_mtu = ETHERMTU;
  311 
  312         cvm_oct_mdio_setup_device(ifp);
  313 
  314         cvm_oct_common_set_mac_address(ifp, mac);
  315         cvm_oct_common_change_mtu(ifp, ifp->if_mtu);
  316 
  317         /*
  318          * Do any last-minute board-specific initialization.
  319          */
  320         switch (cvmx_sysinfo_get()->board_type) {
  321 #if defined(OCTEON_VENDOR_LANNER)
  322         case CVMX_BOARD_TYPE_CUST_LANNER_MR320:
  323         case CVMX_BOARD_TYPE_CUST_LANNER_MR321X:
  324                 if (priv->phy_id == 16)
  325                         cvm_oct_mv88e61xx_setup_device(ifp);
  326                 break;
  327 #endif
  328         default:
  329                 break;
  330         }
  331 
  332         device_attach(priv->dev);
  333 
  334         return 0;
  335 }
  336 
  337 void cvm_oct_common_uninit(struct ifnet *ifp)
  338 {
  339     /* Currently nothing to do */
  340 }

Cache object: 500d57f74b1f318adad3779cbe262739


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