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

Cache object: 85a0e4ddc13279e60c4159fb6407aae3


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