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/dpaa/if_dtsec.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) 2011-2012 Semihalf.
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: releng/12.0/sys/dev/dpaa/if_dtsec.c 325927 2017-11-17 04:29:32Z jhibbits $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/kernel.h>
   33 #include <sys/module.h>
   34 #include <sys/bus.h>
   35 #include <sys/rman.h>
   36 #include <sys/malloc.h>
   37 #include <sys/mbuf.h>
   38 #include <sys/socket.h>
   39 #include <sys/sysctl.h>
   40 #include <sys/sockio.h>
   41 
   42 #include <machine/bus.h>
   43 #include <machine/resource.h>
   44 
   45 #include <net/ethernet.h>
   46 #include <net/if.h>
   47 #include <net/if_dl.h>
   48 #include <net/if_media.h>
   49 #include <net/if_types.h>
   50 #include <net/if_arp.h>
   51 
   52 #include <dev/mii/mii.h>
   53 #include <dev/mii/miivar.h>
   54 #include <dev/ofw/ofw_bus.h>
   55 #include <dev/ofw/ofw_bus_subr.h>
   56 #include <dev/ofw/openfirm.h>
   57 
   58 #include "miibus_if.h"
   59 
   60 #include <contrib/ncsw/inc/integrations/dpaa_integration_ext.h>
   61 #include <contrib/ncsw/inc/Peripherals/fm_mac_ext.h>
   62 #include <contrib/ncsw/inc/Peripherals/fm_port_ext.h>
   63 #include <contrib/ncsw/inc/xx_ext.h>
   64 
   65 #include "fman.h"
   66 #include "if_dtsec.h"
   67 #include "if_dtsec_im.h"
   68 #include "if_dtsec_rm.h"
   69 
   70 #define DTSEC_MIN_FRAME_SIZE    64
   71 #define DTSEC_MAX_FRAME_SIZE    9600
   72 
   73 #define DTSEC_REG_MAXFRM        0x110
   74 
   75 /**
   76  * @group dTSEC private defines.
   77  * @{
   78  */
   79 /**
   80  * dTSEC FMan MAC exceptions info struct.
   81  */
   82 struct dtsec_fm_mac_ex_str {
   83         const int num;
   84         const char *str;
   85 };
   86 /** @} */
   87 
   88 
   89 /**
   90  * @group FMan MAC routines.
   91  * @{
   92  */
   93 #define DTSEC_MAC_EXCEPTIONS_END        (-1)
   94 
   95 /**
   96  * FMan MAC exceptions.
   97  */
   98 static const struct dtsec_fm_mac_ex_str dtsec_fm_mac_exceptions[] = {
   99         { e_FM_MAC_EX_10G_MDIO_SCAN_EVENTMDIO, "MDIO scan event" },
  100         { e_FM_MAC_EX_10G_MDIO_CMD_CMPL, "MDIO command completion" },
  101         { e_FM_MAC_EX_10G_REM_FAULT, "Remote fault" },
  102         { e_FM_MAC_EX_10G_LOC_FAULT, "Local fault" },
  103         { e_FM_MAC_EX_10G_1TX_ECC_ER, "Transmit frame ECC error" },
  104         { e_FM_MAC_EX_10G_TX_FIFO_UNFL, "Transmit FIFO underflow" },
  105         { e_FM_MAC_EX_10G_TX_FIFO_OVFL, "Receive FIFO overflow" },
  106         { e_FM_MAC_EX_10G_TX_ER, "Transmit frame error" },
  107         { e_FM_MAC_EX_10G_RX_FIFO_OVFL, "Receive FIFO overflow" },
  108         { e_FM_MAC_EX_10G_RX_ECC_ER, "Receive frame ECC error" },
  109         { e_FM_MAC_EX_10G_RX_JAB_FRM, "Receive jabber frame" },
  110         { e_FM_MAC_EX_10G_RX_OVRSZ_FRM, "Receive oversized frame" },
  111         { e_FM_MAC_EX_10G_RX_RUNT_FRM, "Receive runt frame" },
  112         { e_FM_MAC_EX_10G_RX_FRAG_FRM, "Receive fragment frame" },
  113         { e_FM_MAC_EX_10G_RX_LEN_ER, "Receive payload length error" },
  114         { e_FM_MAC_EX_10G_RX_CRC_ER, "Receive CRC error" },
  115         { e_FM_MAC_EX_10G_RX_ALIGN_ER, "Receive alignment error" },
  116         { e_FM_MAC_EX_1G_BAB_RX, "Babbling receive error" },
  117         { e_FM_MAC_EX_1G_RX_CTL, "Receive control (pause frame) interrupt" },
  118         { e_FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET, "Graceful transmit stop "
  119             "complete" },
  120         { e_FM_MAC_EX_1G_BAB_TX, "Babbling transmit error" },
  121         { e_FM_MAC_EX_1G_TX_CTL, "Transmit control (pause frame) interrupt" },
  122         { e_FM_MAC_EX_1G_TX_ERR, "Transmit error" },
  123         { e_FM_MAC_EX_1G_LATE_COL, "Late collision" },
  124         { e_FM_MAC_EX_1G_COL_RET_LMT, "Collision retry limit" },
  125         { e_FM_MAC_EX_1G_TX_FIFO_UNDRN, "Transmit FIFO underrun" },
  126         { e_FM_MAC_EX_1G_MAG_PCKT, "Magic Packet detected when dTSEC is in "
  127             "Magic Packet detection mode" },
  128         { e_FM_MAC_EX_1G_MII_MNG_RD_COMPLET, "MII management read completion" },
  129         { e_FM_MAC_EX_1G_MII_MNG_WR_COMPLET, "MII management write completion" },
  130         { e_FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET, "Graceful receive stop "
  131             "complete" },
  132         { e_FM_MAC_EX_1G_TX_DATA_ERR, "Internal data error on transmit" },
  133         { e_FM_MAC_EX_1G_RX_DATA_ERR, "Internal data error on receive" },
  134         { e_FM_MAC_EX_1G_1588_TS_RX_ERR, "Time-Stamp Receive Error" },
  135         { e_FM_MAC_EX_1G_RX_MIB_CNT_OVFL, "MIB counter overflow" },
  136         { DTSEC_MAC_EXCEPTIONS_END, "" }
  137 };
  138 
  139 static const char *
  140 dtsec_fm_mac_ex_to_str(e_FmMacExceptions exception)
  141 {
  142         int i;
  143 
  144         for (i = 0; dtsec_fm_mac_exceptions[i].num != exception &&
  145             dtsec_fm_mac_exceptions[i].num != DTSEC_MAC_EXCEPTIONS_END; ++i)
  146                 ;
  147 
  148         if (dtsec_fm_mac_exceptions[i].num == DTSEC_MAC_EXCEPTIONS_END)
  149                 return ("<Unknown Exception>");
  150 
  151         return (dtsec_fm_mac_exceptions[i].str);
  152 }
  153 
  154 static void
  155 dtsec_fm_mac_mdio_event_callback(t_Handle h_App,
  156     e_FmMacExceptions exception)
  157 {
  158         struct dtsec_softc *sc;
  159 
  160         sc = h_App;
  161         device_printf(sc->sc_dev, "MDIO event %i: %s.\n", exception,
  162             dtsec_fm_mac_ex_to_str(exception));
  163 }
  164 
  165 static void
  166 dtsec_fm_mac_exception_callback(t_Handle app, e_FmMacExceptions exception)
  167 {
  168         struct dtsec_softc *sc;
  169 
  170         sc = app;
  171         device_printf(sc->sc_dev, "MAC exception %i: %s.\n", exception,
  172             dtsec_fm_mac_ex_to_str(exception));
  173 }
  174 
  175 static void
  176 dtsec_fm_mac_free(struct dtsec_softc *sc)
  177 {
  178         if (sc->sc_mach == NULL)
  179                 return;
  180 
  181         FM_MAC_Disable(sc->sc_mach, e_COMM_MODE_RX_AND_TX);
  182         FM_MAC_Free(sc->sc_mach);
  183         sc->sc_mach = NULL;
  184 }
  185 
  186 static int
  187 dtsec_fm_mac_init(struct dtsec_softc *sc, uint8_t *mac)
  188 {
  189         t_FmMacParams params;
  190         t_Error error;
  191 
  192         memset(&params, 0, sizeof(params));
  193         memcpy(&params.addr, mac, sizeof(params.addr));
  194 
  195         params.baseAddr = rman_get_bushandle(sc->sc_mem);
  196         params.enetMode = sc->sc_mac_enet_mode;
  197         params.macId = sc->sc_eth_id;
  198         params.mdioIrq = sc->sc_mac_mdio_irq;
  199         params.f_Event = dtsec_fm_mac_mdio_event_callback;
  200         params.f_Exception = dtsec_fm_mac_exception_callback;
  201         params.h_App = sc;
  202         params.h_Fm = sc->sc_fmh;
  203 
  204         sc->sc_mach = FM_MAC_Config(&params);
  205         if (sc->sc_mach == NULL) {
  206                 device_printf(sc->sc_dev, "couldn't configure FM_MAC module.\n"
  207                     );
  208                 return (ENXIO);
  209         }
  210 
  211         error = FM_MAC_ConfigResetOnInit(sc->sc_mach, TRUE);
  212         if (error != E_OK) {
  213                 device_printf(sc->sc_dev, "couldn't enable reset on init "
  214                     "feature.\n");
  215                 dtsec_fm_mac_free(sc);
  216                 return (ENXIO);
  217         }
  218 
  219         /* Do not inform about pause frames */
  220         error = FM_MAC_ConfigException(sc->sc_mach, e_FM_MAC_EX_1G_RX_CTL,
  221             FALSE);
  222         if (error != E_OK) {
  223                 device_printf(sc->sc_dev, "couldn't disable pause frames "
  224                         "exception.\n");
  225                 dtsec_fm_mac_free(sc);
  226                 return (ENXIO);
  227         }
  228 
  229         error = FM_MAC_Init(sc->sc_mach);
  230         if (error != E_OK) {
  231                 device_printf(sc->sc_dev, "couldn't initialize FM_MAC module."
  232                     "\n");
  233                 dtsec_fm_mac_free(sc);
  234                 return (ENXIO);
  235         }
  236 
  237         return (0);
  238 }
  239 /** @} */
  240 
  241 
  242 /**
  243  * @group FMan PORT routines.
  244  * @{
  245  */
  246 static const char *
  247 dtsec_fm_port_ex_to_str(e_FmPortExceptions exception)
  248 {
  249 
  250         switch (exception) {
  251         case e_FM_PORT_EXCEPTION_IM_BUSY:
  252                 return ("IM: RX busy");
  253         default:
  254                 return ("<Unknown Exception>");
  255         }
  256 }
  257 
  258 void
  259 dtsec_fm_port_rx_exception_callback(t_Handle app,
  260     e_FmPortExceptions exception)
  261 {
  262         struct dtsec_softc *sc;
  263 
  264         sc = app;
  265         device_printf(sc->sc_dev, "RX exception: %i: %s.\n", exception,
  266             dtsec_fm_port_ex_to_str(exception));
  267 }
  268 
  269 void
  270 dtsec_fm_port_tx_exception_callback(t_Handle app,
  271     e_FmPortExceptions exception)
  272 {
  273         struct dtsec_softc *sc;
  274 
  275         sc = app;
  276         device_printf(sc->sc_dev, "TX exception: %i: %s.\n", exception,
  277             dtsec_fm_port_ex_to_str(exception));
  278 }
  279 
  280 e_FmPortType
  281 dtsec_fm_port_rx_type(enum eth_dev_type type)
  282 {
  283         switch (type) {
  284         case ETH_DTSEC:
  285                 return (e_FM_PORT_TYPE_RX);
  286         case ETH_10GSEC:
  287                 return (e_FM_PORT_TYPE_RX_10G);
  288         default:
  289                 return (e_FM_PORT_TYPE_DUMMY);
  290         }
  291 }
  292 
  293 e_FmPortType
  294 dtsec_fm_port_tx_type(enum eth_dev_type type)
  295 {
  296 
  297         switch (type) {
  298         case ETH_DTSEC:
  299                 return (e_FM_PORT_TYPE_TX);
  300         case ETH_10GSEC:
  301                 return (e_FM_PORT_TYPE_TX_10G);
  302         default:
  303                 return (e_FM_PORT_TYPE_DUMMY);
  304         }
  305 }
  306 
  307 static void
  308 dtsec_fm_port_free_both(struct dtsec_softc *sc)
  309 {
  310         if (sc->sc_rxph) {
  311                 FM_PORT_Free(sc->sc_rxph);
  312                 sc->sc_rxph = NULL;
  313         }
  314 
  315         if (sc->sc_txph) {
  316                 FM_PORT_Free(sc->sc_txph);
  317                 sc->sc_txph = NULL;
  318         }
  319 }
  320 /** @} */
  321 
  322 
  323 /**
  324  * @group IFnet routines.
  325  * @{
  326  */
  327 static int
  328 dtsec_set_mtu(struct dtsec_softc *sc, unsigned int mtu)
  329 {
  330 
  331         mtu += ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + ETHER_CRC_LEN;
  332 
  333         DTSEC_LOCK_ASSERT(sc);
  334 
  335         if (mtu >= DTSEC_MIN_FRAME_SIZE && mtu <= DTSEC_MAX_FRAME_SIZE) {
  336                 bus_write_4(sc->sc_mem, DTSEC_REG_MAXFRM, mtu);
  337                 return (mtu);
  338         }
  339 
  340         return (0);
  341 }
  342 
  343 static int
  344 dtsec_if_enable_locked(struct dtsec_softc *sc)
  345 {
  346         int error;
  347 
  348         DTSEC_LOCK_ASSERT(sc);
  349 
  350         error = FM_MAC_Enable(sc->sc_mach, e_COMM_MODE_RX_AND_TX);
  351         if (error != E_OK)
  352                 return (EIO);
  353 
  354         error = FM_PORT_Enable(sc->sc_rxph);
  355         if (error != E_OK)
  356                 return (EIO);
  357 
  358         error = FM_PORT_Enable(sc->sc_txph);
  359         if (error != E_OK)
  360                 return (EIO);
  361 
  362         sc->sc_ifnet->if_drv_flags |= IFF_DRV_RUNNING;
  363 
  364         /* Refresh link state */
  365         dtsec_miibus_statchg(sc->sc_dev);
  366 
  367         return (0);
  368 }
  369 
  370 static int
  371 dtsec_if_disable_locked(struct dtsec_softc *sc)
  372 {
  373         int error;
  374 
  375         DTSEC_LOCK_ASSERT(sc);
  376 
  377         error = FM_MAC_Disable(sc->sc_mach, e_COMM_MODE_RX_AND_TX);
  378         if (error != E_OK)
  379                 return (EIO);
  380 
  381         error = FM_PORT_Disable(sc->sc_rxph);
  382         if (error != E_OK)
  383                 return (EIO);
  384 
  385         error = FM_PORT_Disable(sc->sc_txph);
  386         if (error != E_OK)
  387                 return (EIO);
  388 
  389         sc->sc_ifnet->if_drv_flags &= ~IFF_DRV_RUNNING;
  390 
  391         return (0);
  392 }
  393 
  394 static int
  395 dtsec_if_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
  396 {
  397         struct dtsec_softc *sc;
  398         struct ifreq *ifr;
  399         int error;
  400 
  401         sc = ifp->if_softc;
  402         ifr = (struct ifreq *)data;
  403         error = 0;
  404 
  405         /* Basic functionality to achieve media status reports */
  406         switch (command) {
  407         case SIOCSIFMTU:
  408                 DTSEC_LOCK(sc);
  409                 if (dtsec_set_mtu(sc, ifr->ifr_mtu))
  410                         ifp->if_mtu = ifr->ifr_mtu;
  411                 else
  412                         error = EINVAL;
  413                 DTSEC_UNLOCK(sc);
  414                 break;
  415         case SIOCSIFFLAGS:
  416                 DTSEC_LOCK(sc);
  417 
  418                 if (sc->sc_ifnet->if_flags & IFF_UP)
  419                         error = dtsec_if_enable_locked(sc);
  420                 else
  421                         error = dtsec_if_disable_locked(sc);
  422 
  423                 DTSEC_UNLOCK(sc);
  424                 break;
  425 
  426         case SIOCGIFMEDIA:
  427         case SIOCSIFMEDIA:
  428                 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media,
  429                     command);
  430                 break;
  431 
  432         default:
  433                 error = ether_ioctl(ifp, command, data);
  434         }
  435 
  436         return (error);
  437 }
  438 
  439 static void
  440 dtsec_if_tick(void *arg)
  441 {
  442         struct dtsec_softc *sc;
  443 
  444         sc = arg;
  445 
  446         /* TODO */
  447         DTSEC_LOCK(sc);
  448 
  449         mii_tick(sc->sc_mii);
  450         callout_reset(&sc->sc_tick_callout, hz, dtsec_if_tick, sc);
  451 
  452         DTSEC_UNLOCK(sc);
  453 }
  454 
  455 static void
  456 dtsec_if_deinit_locked(struct dtsec_softc *sc)
  457 {
  458 
  459         DTSEC_LOCK_ASSERT(sc);
  460 
  461         DTSEC_UNLOCK(sc);
  462         callout_drain(&sc->sc_tick_callout);
  463         DTSEC_LOCK(sc);
  464 }
  465 
  466 static void
  467 dtsec_if_init_locked(struct dtsec_softc *sc)
  468 {
  469         int error;
  470 
  471         DTSEC_LOCK_ASSERT(sc);
  472 
  473         /* Set MAC address */
  474         error = FM_MAC_ModifyMacAddr(sc->sc_mach,
  475             (t_EnetAddr *)IF_LLADDR(sc->sc_ifnet));
  476         if (error != E_OK) {
  477                 device_printf(sc->sc_dev, "couldn't set MAC address.\n");
  478                 goto err;
  479         }
  480 
  481         /* Start MII polling */
  482         if (sc->sc_mii)
  483                 callout_reset(&sc->sc_tick_callout, hz, dtsec_if_tick, sc);
  484 
  485         if (sc->sc_ifnet->if_flags & IFF_UP) {
  486                 error = dtsec_if_enable_locked(sc);
  487                 if (error != 0)
  488                         goto err;
  489         } else {
  490                 error = dtsec_if_disable_locked(sc);
  491                 if (error != 0)
  492                         goto err;
  493         }
  494 
  495         return;
  496 
  497 err:
  498         dtsec_if_deinit_locked(sc);
  499         device_printf(sc->sc_dev, "initialization error.\n");
  500         return;
  501 }
  502 
  503 static void
  504 dtsec_if_init(void *data)
  505 {
  506         struct dtsec_softc *sc;
  507 
  508         sc = data;
  509 
  510         DTSEC_LOCK(sc);
  511         dtsec_if_init_locked(sc);
  512         DTSEC_UNLOCK(sc);
  513 }
  514 
  515 static void
  516 dtsec_if_start(struct ifnet *ifp)
  517 {
  518         struct dtsec_softc *sc;
  519 
  520         sc = ifp->if_softc;
  521         DTSEC_LOCK(sc);
  522         sc->sc_start_locked(sc);
  523         DTSEC_UNLOCK(sc);
  524 }
  525 
  526 static void
  527 dtsec_if_watchdog(struct ifnet *ifp)
  528 {
  529         /* TODO */
  530 }
  531 /** @} */
  532 
  533 
  534 /**
  535  * @group IFmedia routines.
  536  * @{
  537  */
  538 static int
  539 dtsec_ifmedia_upd(struct ifnet *ifp)
  540 {
  541         struct dtsec_softc *sc = ifp->if_softc;
  542 
  543         DTSEC_LOCK(sc);
  544         mii_mediachg(sc->sc_mii);
  545         DTSEC_UNLOCK(sc);
  546 
  547         return (0);
  548 }
  549 
  550 static void
  551 dtsec_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
  552 {
  553         struct dtsec_softc *sc = ifp->if_softc;
  554 
  555         DTSEC_LOCK(sc);
  556 
  557         mii_pollstat(sc->sc_mii);
  558 
  559         ifmr->ifm_active = sc->sc_mii->mii_media_active;
  560         ifmr->ifm_status = sc->sc_mii->mii_media_status;
  561 
  562         DTSEC_UNLOCK(sc);
  563 }
  564 /** @} */
  565 
  566 
  567 /**
  568  * @group dTSEC bus interface.
  569  * @{
  570  */
  571 static void
  572 dtsec_configure_mode(struct dtsec_softc *sc)
  573 {
  574         char tunable[64];
  575 
  576         snprintf(tunable, sizeof(tunable), "%s.independent_mode",
  577             device_get_nameunit(sc->sc_dev));
  578 
  579         sc->sc_mode = DTSEC_MODE_REGULAR;
  580         TUNABLE_INT_FETCH(tunable, &sc->sc_mode);
  581 
  582         if (sc->sc_mode == DTSEC_MODE_REGULAR) {
  583                 sc->sc_port_rx_init = dtsec_rm_fm_port_rx_init;
  584                 sc->sc_port_tx_init = dtsec_rm_fm_port_tx_init;
  585                 sc->sc_start_locked = dtsec_rm_if_start_locked;
  586         } else {
  587                 sc->sc_port_rx_init = dtsec_im_fm_port_rx_init;
  588                 sc->sc_port_tx_init = dtsec_im_fm_port_tx_init;
  589                 sc->sc_start_locked = dtsec_im_if_start_locked;
  590         }
  591 
  592         device_printf(sc->sc_dev, "Configured for %s mode.\n",
  593             (sc->sc_mode == DTSEC_MODE_REGULAR) ? "regular" : "independent");
  594 }
  595 
  596 int
  597 dtsec_attach(device_t dev)
  598 {
  599         struct dtsec_softc *sc;
  600         device_t parent;
  601         int error;
  602         struct ifnet *ifp;
  603 
  604         sc = device_get_softc(dev);
  605 
  606         parent = device_get_parent(dev);
  607         sc->sc_dev = dev;
  608         sc->sc_mac_mdio_irq = NO_IRQ;
  609 
  610         /* Check if MallocSmart allocator is ready */
  611         if (XX_MallocSmartInit() != E_OK)
  612                 return (ENXIO);
  613 
  614         /* Init locks */
  615         mtx_init(&sc->sc_lock, device_get_nameunit(dev),
  616             "DTSEC Global Lock", MTX_DEF);
  617 
  618         mtx_init(&sc->sc_mii_lock, device_get_nameunit(dev),
  619             "DTSEC MII Lock", MTX_DEF);
  620 
  621         /* Init callouts */
  622         callout_init(&sc->sc_tick_callout, CALLOUT_MPSAFE);
  623 
  624         /* Read configuraton */
  625         if ((error = fman_get_handle(parent, &sc->sc_fmh)) != 0)
  626                 return (error);
  627 
  628         if ((error = fman_get_muram_handle(parent, &sc->sc_muramh)) != 0)
  629                 return (error);
  630 
  631         if ((error = fman_get_bushandle(parent, &sc->sc_fm_base)) != 0)
  632                 return (error);
  633 
  634         /* Configure working mode */
  635         dtsec_configure_mode(sc);
  636 
  637         /* If we are working in regular mode configure BMAN and QMAN */
  638         if (sc->sc_mode == DTSEC_MODE_REGULAR) {
  639                 /* Create RX buffer pool */
  640                 error = dtsec_rm_pool_rx_init(sc);
  641                 if (error != 0)
  642                         return (EIO);
  643 
  644                 /* Create RX frame queue range */
  645                 error = dtsec_rm_fqr_rx_init(sc);
  646                 if (error != 0)
  647                         return (EIO);
  648 
  649                 /* Create frame info pool */
  650                 error = dtsec_rm_fi_pool_init(sc);
  651                 if (error != 0)
  652                         return (EIO);
  653 
  654                 /* Create TX frame queue range */
  655                 error = dtsec_rm_fqr_tx_init(sc);
  656                 if (error != 0)
  657                         return (EIO);
  658         }
  659 
  660         /* Init FMan MAC module. */
  661         error = dtsec_fm_mac_init(sc, sc->sc_mac_addr);
  662         if (error != 0) {
  663                 dtsec_detach(dev);
  664                 return (ENXIO);
  665         }
  666 
  667         /* Init FMan TX port */
  668         error = sc->sc_port_tx_init(sc, device_get_unit(sc->sc_dev));
  669         if (error != 0) {
  670                 dtsec_detach(dev);
  671                 return (ENXIO);
  672         }
  673 
  674         /* Init FMan RX port */
  675         error = sc->sc_port_rx_init(sc, device_get_unit(sc->sc_dev));
  676         if (error != 0) {
  677                 dtsec_detach(dev);
  678                 return (ENXIO);
  679         }
  680 
  681         /* Create network interface for upper layers */
  682         ifp = sc->sc_ifnet = if_alloc(IFT_ETHER);
  683         if (ifp == NULL) {
  684                 device_printf(sc->sc_dev, "if_alloc() failed.\n");
  685                 dtsec_detach(dev);
  686                 return (ENOMEM);
  687         }
  688 
  689         ifp->if_softc = sc;
  690         ifp->if_mtu = ETHERMTU; /* TODO: Configure */
  691         ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST;
  692         ifp->if_init = dtsec_if_init;
  693         ifp->if_start = dtsec_if_start;
  694         ifp->if_ioctl = dtsec_if_ioctl;
  695         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  696 
  697         if (sc->sc_phy_addr >= 0)
  698                 if_initname(ifp, device_get_name(sc->sc_dev),
  699                     device_get_unit(sc->sc_dev));
  700         else
  701                 if_initname(ifp, "dtsec_phy", device_get_unit(sc->sc_dev));
  702 
  703         /* TODO */
  704 #if 0
  705         IFQ_SET_MAXLEN(&ifp->if_snd, TSEC_TX_NUM_DESC - 1);
  706         ifp->if_snd.ifq_drv_maxlen = TSEC_TX_NUM_DESC - 1;
  707         IFQ_SET_READY(&ifp->if_snd);
  708 #endif
  709         ifp->if_capabilities = IFCAP_JUMBO_MTU; /* TODO: HWCSUM */
  710         ifp->if_capenable = ifp->if_capabilities;
  711 
  712         /* Attach PHY(s) */
  713         error = mii_attach(sc->sc_dev, &sc->sc_mii_dev, ifp, dtsec_ifmedia_upd,
  714             dtsec_ifmedia_sts, BMSR_DEFCAPMASK, sc->sc_phy_addr,
  715             MII_OFFSET_ANY, 0);
  716         if (error) {
  717                 device_printf(sc->sc_dev, "attaching PHYs failed: %d\n", error);
  718                 dtsec_detach(sc->sc_dev);
  719                 return (error);
  720         }
  721         sc->sc_mii = device_get_softc(sc->sc_mii_dev);
  722 
  723         /* Attach to stack */
  724         ether_ifattach(ifp, sc->sc_mac_addr);
  725 
  726         return (0);
  727 }
  728 
  729 int
  730 dtsec_detach(device_t dev)
  731 {
  732         struct dtsec_softc *sc;
  733         if_t ifp;
  734 
  735         sc = device_get_softc(dev);
  736         ifp = sc->sc_ifnet;
  737 
  738         if (device_is_attached(dev)) {
  739                 ether_ifdetach(ifp);
  740                 /* Shutdown interface */
  741                 DTSEC_LOCK(sc);
  742                 dtsec_if_deinit_locked(sc);
  743                 DTSEC_UNLOCK(sc);
  744         }
  745 
  746         if (sc->sc_ifnet) {
  747                 if_free(sc->sc_ifnet);
  748                 sc->sc_ifnet = NULL;
  749         }
  750 
  751         if (sc->sc_mode == DTSEC_MODE_REGULAR) {
  752                 /* Free RX/TX FQRs */
  753                 dtsec_rm_fqr_rx_free(sc);
  754                 dtsec_rm_fqr_tx_free(sc);
  755 
  756                 /* Free frame info pool */
  757                 dtsec_rm_fi_pool_free(sc);
  758 
  759                 /* Free RX buffer pool */
  760                 dtsec_rm_pool_rx_free(sc);
  761         }
  762 
  763         dtsec_fm_mac_free(sc);
  764         dtsec_fm_port_free_both(sc);
  765 
  766         /* Destroy lock */
  767         mtx_destroy(&sc->sc_lock);
  768 
  769         return (0);
  770 }
  771 
  772 int
  773 dtsec_suspend(device_t dev)
  774 {
  775 
  776         return (0);
  777 }
  778 
  779 int
  780 dtsec_resume(device_t dev)
  781 {
  782 
  783         return (0);
  784 }
  785 
  786 int
  787 dtsec_shutdown(device_t dev)
  788 {
  789 
  790         return (0);
  791 }
  792 /** @} */
  793 
  794 
  795 /**
  796  * @group MII bus interface.
  797  * @{
  798  */
  799 int
  800 dtsec_miibus_readreg(device_t dev, int phy, int reg)
  801 {
  802         struct dtsec_softc *sc;
  803 
  804         sc = device_get_softc(dev);
  805 
  806         return (MIIBUS_READREG(sc->sc_mdio, phy, reg));
  807 }
  808 
  809 int
  810 dtsec_miibus_writereg(device_t dev, int phy, int reg, int value)
  811 {
  812 
  813         struct dtsec_softc *sc;
  814 
  815         sc = device_get_softc(dev);
  816 
  817         return (MIIBUS_WRITEREG(sc->sc_mdio, phy, reg, value));
  818 }
  819 
  820 void
  821 dtsec_miibus_statchg(device_t dev)
  822 {
  823         struct dtsec_softc *sc;
  824         e_EnetSpeed speed;
  825         bool duplex;
  826         int error;
  827 
  828         sc = device_get_softc(dev);
  829 
  830         DTSEC_LOCK_ASSERT(sc);
  831 
  832         duplex = ((sc->sc_mii->mii_media_active & IFM_GMASK) == IFM_FDX);
  833 
  834         switch (IFM_SUBTYPE(sc->sc_mii->mii_media_active)) {
  835         case IFM_1000_T:
  836         case IFM_1000_SX:
  837                 speed = e_ENET_SPEED_1000;
  838                 break;
  839 
  840         case IFM_100_TX:
  841                 speed = e_ENET_SPEED_100;
  842                 break;
  843 
  844         case IFM_10_T:
  845                 speed = e_ENET_SPEED_10;
  846                 break;
  847 
  848         default:
  849                 speed = e_ENET_SPEED_10;
  850         }
  851 
  852         error = FM_MAC_AdjustLink(sc->sc_mach, speed, duplex);
  853         if (error != E_OK)
  854                 device_printf(sc->sc_dev, "error while adjusting MAC speed.\n");
  855 }
  856 /** @} */

Cache object: f85cf6ffe41079cbd8ff5593b002f128


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