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

Cache object: 3a4ab4809045df117b99d77a6e9cee78


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