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$");
   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(if_t ifp, u_long command, caddr_t data)
  396 {
  397         struct dtsec_softc *sc;
  398         struct ifreq *ifr;
  399         int error;
  400 
  401         sc = if_getsoftc(ifp);
  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                         if_setmtu(ifp, 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_getlladdr(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(if_t ifp)
  517 {
  518         struct dtsec_softc *sc;
  519 
  520         sc = if_getsoftc(ifp);
  521         DTSEC_LOCK(sc);
  522         sc->sc_start_locked(sc);
  523         DTSEC_UNLOCK(sc);
  524 }
  525 
  526 static void
  527 dtsec_if_watchdog(if_t ifp)
  528 {
  529         /* TODO */
  530 }
  531 /** @} */
  532 
  533 
  534 /**
  535  * @group IFmedia routines.
  536  * @{
  537  */
  538 static int
  539 dtsec_ifmedia_upd(if_t ifp)
  540 {
  541         struct dtsec_softc *sc = if_getsoftc(ifp);
  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(if_t ifp, struct ifmediareq *ifmr)
  552 {
  553         struct dtsec_softc *sc = if_getsoftc(ifp);
  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         if_t 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         if_setsoftc(ifp, sc);
  690 
  691         if_setflags(ifp, IFF_SIMPLEX | IFF_BROADCAST);
  692         if_setinitfn(ifp, dtsec_if_init);
  693         if_setstartfn(ifp, dtsec_if_start);
  694         if_setioctlfn(ifp, dtsec_if_ioctl);
  695         if_setsendqlen(ifp, 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         if_setsendqlen(ifp, TSEC_TX_NUM_DESC - 1);
  706         if_setsendqready(ifp);
  707 #endif
  708 
  709         if_setcapenable(ifp, if_getcapabilities(ifp));
  710 
  711         /* Attach PHY(s) */
  712         error = mii_attach(sc->sc_dev, &sc->sc_mii_dev, ifp, dtsec_ifmedia_upd,
  713             dtsec_ifmedia_sts, BMSR_DEFCAPMASK, sc->sc_phy_addr,
  714             MII_OFFSET_ANY, 0);
  715         if (error) {
  716                 device_printf(sc->sc_dev, "attaching PHYs failed: %d\n", error);
  717                 dtsec_detach(sc->sc_dev);
  718                 return (error);
  719         }
  720         sc->sc_mii = device_get_softc(sc->sc_mii_dev);
  721 
  722         /* Attach to stack */
  723         ether_ifattach(ifp, sc->sc_mac_addr);
  724 
  725         return (0);
  726 }
  727 
  728 int
  729 dtsec_detach(device_t dev)
  730 {
  731         struct dtsec_softc *sc;
  732         if_t ifp;
  733 
  734         sc = device_get_softc(dev);
  735         ifp = sc->sc_ifnet;
  736 
  737         if (device_is_attached(dev)) {
  738                 ether_ifdetach(ifp);
  739                 /* Shutdown interface */
  740                 DTSEC_LOCK(sc);
  741                 dtsec_if_deinit_locked(sc);
  742                 DTSEC_UNLOCK(sc);
  743         }
  744 
  745         if (sc->sc_ifnet) {
  746                 if_free(sc->sc_ifnet);
  747                 sc->sc_ifnet = NULL;
  748         }
  749 
  750         if (sc->sc_mode == DTSEC_MODE_REGULAR) {
  751                 /* Free RX/TX FQRs */
  752                 dtsec_rm_fqr_rx_free(sc);
  753                 dtsec_rm_fqr_tx_free(sc);
  754 
  755                 /* Free frame info pool */
  756                 dtsec_rm_fi_pool_free(sc);
  757 
  758                 /* Free RX buffer pool */
  759                 dtsec_rm_pool_rx_free(sc);
  760         }
  761 
  762         dtsec_fm_mac_free(sc);
  763         dtsec_fm_port_free_both(sc);
  764 
  765         /* Destroy lock */
  766         mtx_destroy(&sc->sc_lock);
  767 
  768         return (0);
  769 }
  770 
  771 int
  772 dtsec_suspend(device_t dev)
  773 {
  774 
  775         return (0);
  776 }
  777 
  778 int
  779 dtsec_resume(device_t dev)
  780 {
  781 
  782         return (0);
  783 }
  784 
  785 int
  786 dtsec_shutdown(device_t dev)
  787 {
  788 
  789         return (0);
  790 }
  791 /** @} */
  792 
  793 
  794 /**
  795  * @group MII bus interface.
  796  * @{
  797  */
  798 int
  799 dtsec_miibus_readreg(device_t dev, int phy, int reg)
  800 {
  801         struct dtsec_softc *sc;
  802 
  803         sc = device_get_softc(dev);
  804 
  805         return (MIIBUS_READREG(sc->sc_mdio, phy, reg));
  806 }
  807 
  808 int
  809 dtsec_miibus_writereg(device_t dev, int phy, int reg, int value)
  810 {
  811 
  812         struct dtsec_softc *sc;
  813 
  814         sc = device_get_softc(dev);
  815 
  816         return (MIIBUS_WRITEREG(sc->sc_mdio, phy, reg, value));
  817 }
  818 
  819 void
  820 dtsec_miibus_statchg(device_t dev)
  821 {
  822         struct dtsec_softc *sc;
  823         e_EnetSpeed speed;
  824         bool duplex;
  825         int error;
  826 
  827         sc = device_get_softc(dev);
  828 
  829         DTSEC_LOCK_ASSERT(sc);
  830 
  831         duplex = ((sc->sc_mii->mii_media_active & IFM_GMASK) == IFM_FDX);
  832 
  833         switch (IFM_SUBTYPE(sc->sc_mii->mii_media_active)) {
  834         case IFM_1000_T:
  835         case IFM_1000_SX:
  836                 speed = e_ENET_SPEED_1000;
  837                 break;
  838 
  839         case IFM_100_TX:
  840                 speed = e_ENET_SPEED_100;
  841                 break;
  842 
  843         case IFM_10_T:
  844                 speed = e_ENET_SPEED_10;
  845                 break;
  846 
  847         default:
  848                 speed = e_ENET_SPEED_10;
  849         }
  850 
  851         error = FM_MAC_AdjustLink(sc->sc_mach, speed, duplex);
  852         if (error != E_OK)
  853                 device_printf(sc->sc_dev, "error while adjusting MAC speed.\n");
  854 }
  855 /** @} */

Cache object: c8e271fc2fc1eb44ee9f3409ce74608a


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