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/etherswitch/mtkswitch/mtkswitch.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) 2016 Stanislav Galabov.
    3  * Copyright (c) 2011-2012 Stefan Bethke.
    4  * Copyright (c) 2012 Adrian Chadd.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  *
   28  * $FreeBSD$
   29  */
   30 
   31 #include <sys/param.h>
   32 #include <sys/bus.h>
   33 #include <sys/errno.h>
   34 #include <sys/kernel.h>
   35 #include <sys/lock.h>
   36 #include <sys/malloc.h>
   37 #include <sys/module.h>
   38 #include <sys/mutex.h>
   39 #include <sys/socket.h>
   40 #include <sys/sockio.h>
   41 #include <sys/sysctl.h>
   42 #include <sys/systm.h>
   43 
   44 #include <net/if.h>
   45 #include <net/if_var.h>
   46 #include <net/ethernet.h>
   47 #include <net/if_media.h>
   48 #include <net/if_types.h>
   49 
   50 #include <machine/bus.h>
   51 #include <dev/mii/mii.h>
   52 #include <dev/mii/miivar.h>
   53 #include <dev/mdio/mdio.h>
   54 
   55 #include <dev/etherswitch/etherswitch.h>
   56 #include <dev/etherswitch/mtkswitch/mtkswitchvar.h>
   57 
   58 #include <dev/ofw/ofw_bus_subr.h>
   59 
   60 #include "mdio_if.h"
   61 #include "miibus_if.h"
   62 #include "etherswitch_if.h"
   63 
   64 #define DEBUG
   65 
   66 #if defined(DEBUG)
   67 static SYSCTL_NODE(_debug, OID_AUTO, mtkswitch, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
   68     "mtkswitch");
   69 #endif
   70 
   71 static inline int mtkswitch_portforphy(int phy);
   72 static int mtkswitch_ifmedia_upd(if_t ifp);
   73 static void mtkswitch_ifmedia_sts(if_t ifp, struct ifmediareq *ifmr);
   74 static void mtkswitch_tick(void *arg);
   75 
   76 static const struct ofw_compat_data compat_data[] = {
   77         { "ralink,rt3050-esw",          MTK_SWITCH_RT3050 },
   78         { "ralink,rt3352-esw",          MTK_SWITCH_RT3352 },
   79         { "ralink,rt5350-esw",          MTK_SWITCH_RT5350 },
   80         { "mediatek,mt7620-gsw",        MTK_SWITCH_MT7620 },
   81         { "mediatek,mt7621-gsw",        MTK_SWITCH_MT7621 },
   82         { "mediatek,mt7628-esw",        MTK_SWITCH_MT7628 },
   83 
   84         /* Sentinel */
   85         { NULL,                         MTK_SWITCH_NONE }
   86 };
   87 
   88 static int
   89 mtkswitch_probe(device_t dev)
   90 {
   91         struct mtkswitch_softc *sc;
   92         mtk_switch_type switch_type;
   93 
   94         if (!ofw_bus_status_okay(dev))
   95                 return (ENXIO);
   96 
   97         switch_type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
   98         if (switch_type == MTK_SWITCH_NONE)
   99                 return (ENXIO);
  100 
  101         sc = device_get_softc(dev);
  102         bzero(sc, sizeof(*sc));
  103         sc->sc_switchtype = switch_type;
  104 
  105         device_set_desc_copy(dev, "MTK Switch Driver");
  106 
  107         return (0);
  108 }
  109 
  110 static int
  111 mtkswitch_attach_phys(struct mtkswitch_softc *sc)
  112 {
  113         int phy, err = 0;
  114         char name[IFNAMSIZ];
  115 
  116         /* PHYs need an interface, so we generate a dummy one */
  117         snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->sc_dev));
  118         for (phy = 0; phy < sc->numphys; phy++) {
  119                 if ((sc->phymap & (1u << phy)) == 0) {
  120                         sc->ifp[phy] = NULL;
  121                         sc->ifname[phy] = NULL;
  122                         sc->miibus[phy] = NULL;
  123                         continue;
  124                 }
  125                 sc->ifp[phy] = if_alloc(IFT_ETHER);
  126                 if (sc->ifp[phy] == NULL) {
  127                         device_printf(sc->sc_dev, "couldn't allocate ifnet structure\n");
  128                         err = ENOMEM;
  129                         break;
  130                 }
  131 
  132                 sc->ifp[phy]->if_softc = sc;
  133                 sc->ifp[phy]->if_flags |= IFF_UP | IFF_BROADCAST |
  134                     IFF_DRV_RUNNING | IFF_SIMPLEX;
  135                 sc->ifname[phy] = malloc(strlen(name) + 1, M_DEVBUF, M_WAITOK);
  136                 bcopy(name, sc->ifname[phy], strlen(name) + 1);
  137                 if_initname(sc->ifp[phy], sc->ifname[phy],
  138                     mtkswitch_portforphy(phy));
  139                 err = mii_attach(sc->sc_dev, &sc->miibus[phy], sc->ifp[phy],
  140                     mtkswitch_ifmedia_upd, mtkswitch_ifmedia_sts,
  141                     BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0);
  142                 if (err != 0) {
  143                         device_printf(sc->sc_dev,
  144                             "attaching PHY %d failed\n",
  145                             phy);
  146                 } else {
  147                         DPRINTF(sc->sc_dev, "%s attached to pseudo interface "
  148                             "%s\n", device_get_nameunit(sc->miibus[phy]),
  149                             sc->ifp[phy]->if_xname);
  150                 }
  151         }
  152         return (err);
  153 }
  154 
  155 static int
  156 mtkswitch_set_vlan_mode(struct mtkswitch_softc *sc, uint32_t mode)
  157 {
  158 
  159         /* Check for invalid modes. */
  160         if ((mode & sc->info.es_vlan_caps) != mode)
  161                 return (EINVAL);
  162 
  163         sc->vlan_mode = mode;
  164 
  165         /* Reset VLANs. */
  166         sc->hal.mtkswitch_vlan_init_hw(sc);
  167 
  168         return (0);
  169 }
  170 
  171 static int
  172 mtkswitch_attach(device_t dev)
  173 {
  174         struct mtkswitch_softc *sc;
  175         int err = 0;
  176         int port, rid;
  177 
  178         sc = device_get_softc(dev);
  179 
  180         /* sc->sc_switchtype is already decided in mtkswitch_probe() */
  181         sc->numports = MTKSWITCH_MAX_PORTS;
  182         sc->numphys = MTKSWITCH_MAX_PHYS;
  183         sc->cpuport = MTKSWITCH_CPU_PORT;
  184         sc->sc_dev = dev;
  185 
  186         /* Attach switch related functions */
  187         if (sc->sc_switchtype == MTK_SWITCH_NONE) {
  188                 device_printf(dev, "Unknown switch type\n");
  189                 return (ENXIO);
  190         }
  191 
  192         if (sc->sc_switchtype == MTK_SWITCH_MT7620 ||
  193             sc->sc_switchtype == MTK_SWITCH_MT7621)
  194                 mtk_attach_switch_mt7620(sc);
  195         else
  196                 mtk_attach_switch_rt3050(sc);
  197 
  198         /* Allocate resources */
  199         rid = 0;
  200         sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  201             RF_ACTIVE);
  202         if (sc->sc_res == NULL) {
  203                 device_printf(dev, "could not map memory\n");
  204                 return (ENXIO);
  205         }
  206 
  207         mtx_init(&sc->sc_mtx, "mtkswitch", NULL, MTX_DEF);
  208 
  209         /* Reset the switch */
  210         if (sc->hal.mtkswitch_reset(sc)) {
  211                 DPRINTF(dev, "%s: mtkswitch_reset: failed\n", __func__);
  212                 return (ENXIO);
  213         }
  214 
  215         err = sc->hal.mtkswitch_hw_setup(sc);
  216         DPRINTF(dev, "%s: hw_setup: err=%d\n", __func__, err);
  217         if (err != 0)
  218                 return (err);
  219 
  220         err = sc->hal.mtkswitch_hw_global_setup(sc);
  221         DPRINTF(dev, "%s: hw_global_setup: err=%d\n", __func__, err);
  222         if (err != 0)
  223                 return (err);
  224 
  225         /* Initialize the switch ports */
  226         for (port = 0; port < sc->numports; port++) {
  227                 sc->hal.mtkswitch_port_init(sc, port);
  228         }
  229 
  230         /* Attach the PHYs and complete the bus enumeration */
  231         err = mtkswitch_attach_phys(sc);
  232         DPRINTF(dev, "%s: attach_phys: err=%d\n", __func__, err);
  233         if (err != 0)
  234                 return (err);
  235 
  236         /* Default to ingress filters off. */
  237         err = mtkswitch_set_vlan_mode(sc, ETHERSWITCH_VLAN_DOT1Q);
  238         DPRINTF(dev, "%s: set_vlan_mode: err=%d\n", __func__, err);
  239         if (err != 0)
  240                 return (err);
  241 
  242         bus_generic_probe(dev);
  243         bus_enumerate_hinted_children(dev);
  244         err = bus_generic_attach(dev);
  245         DPRINTF(dev, "%s: bus_generic_attach: err=%d\n", __func__, err);
  246         if (err != 0)
  247                 return (err);
  248 
  249         callout_init_mtx(&sc->callout_tick, &sc->sc_mtx, 0);
  250 
  251         MTKSWITCH_LOCK(sc);
  252         mtkswitch_tick(sc);
  253         MTKSWITCH_UNLOCK(sc);
  254 
  255         return (0);
  256 }
  257 
  258 static int
  259 mtkswitch_detach(device_t dev)
  260 {
  261         struct mtkswitch_softc *sc = device_get_softc(dev);
  262         int phy;
  263 
  264         callout_drain(&sc->callout_tick);
  265 
  266         for (phy = 0; phy < MTKSWITCH_MAX_PHYS; phy++) {
  267                 if (sc->miibus[phy] != NULL)
  268                         device_delete_child(dev, sc->miibus[phy]);
  269                 if (sc->ifp[phy] != NULL)
  270                         if_free(sc->ifp[phy]);
  271                 free(sc->ifname[phy], M_DEVBUF);
  272         }
  273 
  274         bus_generic_detach(dev);
  275         mtx_destroy(&sc->sc_mtx);
  276 
  277         return (0);
  278 }
  279 
  280 /* PHY <-> port mapping is currently 1:1 */
  281 static inline int
  282 mtkswitch_portforphy(int phy)
  283 {
  284 
  285         return (phy);
  286 }
  287 
  288 static inline int
  289 mtkswitch_phyforport(int port)
  290 {
  291 
  292         return (port);
  293 }
  294 
  295 static inline struct mii_data *
  296 mtkswitch_miiforport(struct mtkswitch_softc *sc, int port)
  297 {
  298         int phy = mtkswitch_phyforport(port);
  299 
  300         if (phy < 0 || phy >= MTKSWITCH_MAX_PHYS || sc->miibus[phy] == NULL)
  301                 return (NULL);
  302 
  303         return (device_get_softc(sc->miibus[phy]));
  304 }
  305 
  306 static inline if_t 
  307 mtkswitch_ifpforport(struct mtkswitch_softc *sc, int port)
  308 {
  309         int phy = mtkswitch_phyforport(port);
  310 
  311         if (phy < 0 || phy >= MTKSWITCH_MAX_PHYS)
  312                 return (NULL);
  313 
  314         return (sc->ifp[phy]);
  315 }
  316 
  317 /*
  318  * Convert port status to ifmedia.
  319  */
  320 static void
  321 mtkswitch_update_ifmedia(uint32_t portstatus, u_int *media_status,
  322     u_int *media_active)
  323 {
  324         *media_active = IFM_ETHER;
  325         *media_status = IFM_AVALID;
  326 
  327         if ((portstatus & MTKSWITCH_LINK_UP) != 0)
  328                 *media_status |= IFM_ACTIVE;
  329         else {
  330                 *media_active |= IFM_NONE;
  331                 return;
  332         }
  333 
  334         switch (portstatus & MTKSWITCH_SPEED_MASK) {
  335         case MTKSWITCH_SPEED_10:
  336                 *media_active |= IFM_10_T;
  337                 break;
  338         case MTKSWITCH_SPEED_100:
  339                 *media_active |= IFM_100_TX;
  340                 break;
  341         case MTKSWITCH_SPEED_1000:
  342                 *media_active |= IFM_1000_T;
  343                 break;
  344         }
  345 
  346         if ((portstatus & MTKSWITCH_DUPLEX) != 0)
  347                 *media_active |= IFM_FDX;
  348         else
  349                 *media_active |= IFM_HDX;
  350 
  351         if ((portstatus & MTKSWITCH_TXFLOW) != 0)
  352                 *media_active |= IFM_ETH_TXPAUSE;
  353         if ((portstatus & MTKSWITCH_RXFLOW) != 0)
  354                 *media_active |= IFM_ETH_RXPAUSE;
  355 }
  356 
  357 static void
  358 mtkswitch_miipollstat(struct mtkswitch_softc *sc)
  359 {
  360         struct mii_data *mii;
  361         struct mii_softc *miisc;
  362         uint32_t portstatus;
  363         int i, port_flap = 0;
  364 
  365         MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED);
  366 
  367         for (i = 0; i < sc->numphys; i++) {
  368                 if (sc->miibus[i] == NULL)
  369                         continue;
  370                 mii = device_get_softc(sc->miibus[i]);
  371                 portstatus = sc->hal.mtkswitch_get_port_status(sc,
  372                     mtkswitch_portforphy(i));
  373 
  374                 /* If a port has flapped - mark it so we can flush the ATU */
  375                 if (((mii->mii_media_status & IFM_ACTIVE) == 0 &&
  376                     (portstatus & MTKSWITCH_LINK_UP) != 0) ||
  377                     ((mii->mii_media_status & IFM_ACTIVE) != 0 &&
  378                     (portstatus & MTKSWITCH_LINK_UP) == 0)) {
  379                         port_flap = 1;
  380                 }
  381 
  382                 mtkswitch_update_ifmedia(portstatus, &mii->mii_media_status,
  383                     &mii->mii_media_active);
  384                 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
  385                         if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) !=
  386                             miisc->mii_inst)
  387                                 continue;
  388                         mii_phy_update(miisc, MII_POLLSTAT);
  389                 }
  390         }
  391 
  392         if (port_flap)
  393                 sc->hal.mtkswitch_atu_flush(sc);
  394 }
  395 
  396 static void
  397 mtkswitch_tick(void *arg)
  398 {
  399         struct mtkswitch_softc *sc = arg;
  400 
  401         mtkswitch_miipollstat(sc);
  402         callout_reset(&sc->callout_tick, hz, mtkswitch_tick, sc);
  403 }
  404 
  405 static void
  406 mtkswitch_lock(device_t dev)
  407 {
  408         struct mtkswitch_softc *sc = device_get_softc(dev);
  409 
  410         MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
  411         MTKSWITCH_LOCK(sc);
  412 }
  413 
  414 static void
  415 mtkswitch_unlock(device_t dev)
  416 {
  417         struct mtkswitch_softc *sc = device_get_softc(dev);
  418 
  419         MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED);
  420         MTKSWITCH_UNLOCK(sc);
  421 }
  422 
  423 static etherswitch_info_t *
  424 mtkswitch_getinfo(device_t dev)
  425 {
  426         struct mtkswitch_softc *sc = device_get_softc(dev);
  427 
  428         return (&sc->info);
  429 }
  430 
  431 static inline int
  432 mtkswitch_is_cpuport(struct mtkswitch_softc *sc, int port)
  433 {
  434 
  435         return (sc->cpuport == port);
  436 }
  437 
  438 static int
  439 mtkswitch_getport(device_t dev, etherswitch_port_t *p)
  440 {       
  441         struct mtkswitch_softc *sc;
  442         struct mii_data *mii;
  443         struct ifmediareq *ifmr;
  444         int err;
  445 
  446         sc = device_get_softc(dev);
  447         if (p->es_port < 0 || p->es_port > sc->info.es_nports)
  448                 return (ENXIO);
  449 
  450         err = sc->hal.mtkswitch_port_vlan_get(sc, p);
  451         if (err != 0)
  452                 return (err);
  453 
  454         mii = mtkswitch_miiforport(sc, p->es_port);
  455         if (mtkswitch_is_cpuport(sc, p->es_port)) {
  456                 /* fill in fixed values for CPU port */
  457                 /* XXX is this valid in all cases? */
  458                 p->es_flags |= ETHERSWITCH_PORT_CPU;
  459                 ifmr = &p->es_ifmr;
  460                 ifmr->ifm_count = 0;
  461                 ifmr->ifm_current = ifmr->ifm_active =
  462                     IFM_ETHER | IFM_1000_T | IFM_FDX;
  463                 ifmr->ifm_mask = 0;
  464                 ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID;
  465         } else if (mii != NULL) {
  466                 err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr,
  467                     &mii->mii_media, SIOCGIFMEDIA);
  468                 if (err)
  469                         return (err);
  470         } else {
  471                 ifmr = &p->es_ifmr;
  472                 ifmr->ifm_count = 0;
  473                 ifmr->ifm_current = ifmr->ifm_active = IFM_NONE;
  474                 ifmr->ifm_mask = 0;
  475                 ifmr->ifm_status = 0;
  476         }
  477         return (0);
  478 }
  479 
  480 static int
  481 mtkswitch_setport(device_t dev, etherswitch_port_t *p)
  482 {       
  483         int err;
  484         struct mtkswitch_softc *sc;
  485         struct ifmedia *ifm;
  486         struct mii_data *mii;
  487         if_t ifp;
  488 
  489         sc = device_get_softc(dev);
  490         if (p->es_port < 0 || p->es_port > sc->info.es_nports)
  491                 return (ENXIO);
  492         
  493         /* Port flags. */ 
  494         if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
  495                 err = sc->hal.mtkswitch_port_vlan_setup(sc, p);
  496                 if (err)
  497                         return (err);
  498         }
  499 
  500         /* Do not allow media changes on CPU port. */
  501         if (mtkswitch_is_cpuport(sc, p->es_port))
  502                 return (0);
  503 
  504         mii = mtkswitch_miiforport(sc, p->es_port);
  505         if (mii == NULL)
  506                 return (ENXIO);
  507 
  508         ifp = mtkswitch_ifpforport(sc, p->es_port);
  509 
  510         ifm = &mii->mii_media;
  511         return (ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA));
  512 }
  513 
  514 static void
  515 mtkswitch_statchg(device_t dev)
  516 {
  517 
  518         DPRINTF(dev, "%s\n", __func__);
  519 }
  520 
  521 static int
  522 mtkswitch_ifmedia_upd(if_t ifp)
  523 {
  524         struct mtkswitch_softc *sc = if_getsoftc(ifp);
  525         struct mii_data *mii = mtkswitch_miiforport(sc, ifp->if_dunit); /* XXX - DRVAPI */
  526         
  527         if (mii == NULL)
  528                 return (ENXIO);
  529         mii_mediachg(mii);
  530         return (0);
  531 }
  532 
  533 static void
  534 mtkswitch_ifmedia_sts(if_t ifp, struct ifmediareq *ifmr)
  535 {
  536         struct mtkswitch_softc *sc = if_getsoftc(ifp);
  537         struct mii_data *mii = mtkswitch_miiforport(sc, ifp->if_dunit); /* XXX - DRVAPI */
  538 
  539         DPRINTF(sc->sc_dev, "%s\n", __func__);
  540 
  541         if (mii == NULL)
  542                 return;
  543         mii_pollstat(mii); 
  544         ifmr->ifm_active = mii->mii_media_active;
  545         ifmr->ifm_status = mii->mii_media_status;
  546 }
  547 
  548 static int
  549 mtkswitch_getconf(device_t dev, etherswitch_conf_t *conf)
  550 {
  551         struct mtkswitch_softc *sc;
  552 
  553         sc = device_get_softc(dev);
  554 
  555         /* Return the VLAN mode. */
  556         conf->cmd = ETHERSWITCH_CONF_VLAN_MODE;
  557         conf->vlan_mode = sc->vlan_mode;
  558 
  559         return (0);
  560 }
  561 
  562 static int
  563 mtkswitch_setconf(device_t dev, etherswitch_conf_t *conf)
  564 {
  565         struct mtkswitch_softc *sc;
  566         int err;
  567         
  568         sc = device_get_softc(dev);
  569         
  570         /* Set the VLAN mode. */
  571         if (conf->cmd & ETHERSWITCH_CONF_VLAN_MODE) {
  572                 err = mtkswitch_set_vlan_mode(sc, conf->vlan_mode);
  573                 if (err != 0)
  574                         return (err);
  575         }
  576 
  577         return (0);
  578 }
  579 
  580 static int
  581 mtkswitch_getvgroup(device_t dev, etherswitch_vlangroup_t *e)
  582 {
  583         struct mtkswitch_softc *sc = device_get_softc(dev);
  584 
  585         return (sc->hal.mtkswitch_vlan_getvgroup(sc, e));
  586 }
  587 
  588 static int
  589 mtkswitch_setvgroup(device_t dev, etherswitch_vlangroup_t *e)
  590 {
  591         struct mtkswitch_softc *sc = device_get_softc(dev);
  592 
  593         return (sc->hal.mtkswitch_vlan_setvgroup(sc, e));
  594 }
  595 
  596 static int
  597 mtkswitch_readphy(device_t dev, int phy, int reg)
  598 {
  599         struct mtkswitch_softc *sc = device_get_softc(dev);
  600 
  601         return (sc->hal.mtkswitch_phy_read(dev, phy, reg));
  602 }
  603 
  604 static int
  605 mtkswitch_writephy(device_t dev, int phy, int reg, int val)
  606 {
  607         struct mtkswitch_softc *sc = device_get_softc(dev);
  608 
  609         return (sc->hal.mtkswitch_phy_write(dev, phy, reg, val));
  610 }
  611 
  612 static int
  613 mtkswitch_readreg(device_t dev, int addr)
  614 {
  615         struct mtkswitch_softc *sc = device_get_softc(dev);
  616 
  617         return (sc->hal.mtkswitch_reg_read(dev, addr));
  618 }
  619 
  620 static int
  621 mtkswitch_writereg(device_t dev, int addr, int value)
  622 {
  623         struct mtkswitch_softc *sc = device_get_softc(dev);
  624 
  625         return (sc->hal.mtkswitch_reg_write(dev, addr, value));
  626 }
  627 
  628 static device_method_t mtkswitch_methods[] = {
  629         /* Device interface */
  630         DEVMETHOD(device_probe,         mtkswitch_probe),
  631         DEVMETHOD(device_attach,        mtkswitch_attach),
  632         DEVMETHOD(device_detach,        mtkswitch_detach),
  633 
  634         /* bus interface */
  635         DEVMETHOD(bus_add_child,        device_add_child_ordered),
  636 
  637         /* MII interface */
  638         DEVMETHOD(miibus_readreg,       mtkswitch_readphy),
  639         DEVMETHOD(miibus_writereg,      mtkswitch_writephy),
  640         DEVMETHOD(miibus_statchg,       mtkswitch_statchg),
  641 
  642         /* MDIO interface */
  643         DEVMETHOD(mdio_readreg,         mtkswitch_readphy),
  644         DEVMETHOD(mdio_writereg,        mtkswitch_writephy),
  645 
  646         /* ehterswitch interface */
  647         DEVMETHOD(etherswitch_lock,     mtkswitch_lock),
  648         DEVMETHOD(etherswitch_unlock,   mtkswitch_unlock),
  649         DEVMETHOD(etherswitch_getinfo,  mtkswitch_getinfo),
  650         DEVMETHOD(etherswitch_readreg,  mtkswitch_readreg),
  651         DEVMETHOD(etherswitch_writereg, mtkswitch_writereg),
  652         DEVMETHOD(etherswitch_readphyreg,       mtkswitch_readphy),
  653         DEVMETHOD(etherswitch_writephyreg,      mtkswitch_writephy),
  654         DEVMETHOD(etherswitch_getport,  mtkswitch_getport),
  655         DEVMETHOD(etherswitch_setport,  mtkswitch_setport),
  656         DEVMETHOD(etherswitch_getvgroup,        mtkswitch_getvgroup),
  657         DEVMETHOD(etherswitch_setvgroup,        mtkswitch_setvgroup),
  658         DEVMETHOD(etherswitch_getconf,  mtkswitch_getconf),
  659         DEVMETHOD(etherswitch_setconf,  mtkswitch_setconf),
  660 
  661         DEVMETHOD_END
  662 };
  663 
  664 DEFINE_CLASS_0(mtkswitch, mtkswitch_driver, mtkswitch_methods,
  665     sizeof(struct mtkswitch_softc));
  666 
  667 DRIVER_MODULE(mtkswitch, simplebus, mtkswitch_driver, 0, 0);
  668 DRIVER_MODULE(miibus, mtkswitch, miibus_driver, 0, 0);
  669 DRIVER_MODULE(mdio, mtkswitch, mdio_driver, 0, 0);
  670 DRIVER_MODULE(etherswitch, mtkswitch, etherswitch_driver, 0, 0);
  671 MODULE_VERSION(mtkswitch, 1);
  672 MODULE_DEPEND(mtkswitch, miibus, 1, 1, 1);
  673 MODULE_DEPEND(mtkswitch, etherswitch, 1, 1, 1);

Cache object: f98d2f7aa54cc5d27d04227c1d53b404


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