2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2013 Luiz Otavio O Souza.
5 * Copyright (c) 2011-2012 Stefan Bethke.
6 * Copyright (c) 2012 Adrian Chadd.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include <sys/param.h>
35 #include <sys/errno.h>
36 #include <sys/kernel.h>
38 #include <sys/malloc.h>
39 #include <sys/module.h>
40 #include <sys/mutex.h>
41 #include <sys/socket.h>
42 #include <sys/sockio.h>
43 #include <sys/sysctl.h>
44 #include <sys/systm.h>
47 #include <net/if_var.h>
48 #include <net/ethernet.h>
49 #include <net/if_media.h>
50 #include <net/if_types.h>
52 #include <machine/bus.h>
53 #include <dev/mii/mii.h>
54 #include <dev/mii/miivar.h>
55 #include <dev/mdio/mdio.h>
57 #include <dev/etherswitch/etherswitch.h>
60 #include "miibus_if.h"
61 #include "etherswitch_if.h"
63 MALLOC_DECLARE(M_UKSWITCH);
64 MALLOC_DEFINE(M_UKSWITCH, "ukswitch", "ukswitch data structures");
66 struct ukswitch_softc {
67 struct mtx sc_mtx; /* serialize access to softc */
69 int media; /* cpu port media */
70 int cpuport; /* which PHY is connected to the CPU */
71 int phymask; /* PHYs we manage */
72 int phyoffset; /* PHYs register offset */
73 int numports; /* number of ports */
74 int ifpport[MII_NPHY];
79 struct callout callout_tick;
80 etherswitch_info_t info;
83 #define UKSWITCH_LOCK(_sc) \
84 mtx_lock(&(_sc)->sc_mtx)
85 #define UKSWITCH_UNLOCK(_sc) \
86 mtx_unlock(&(_sc)->sc_mtx)
87 #define UKSWITCH_LOCK_ASSERT(_sc, _what) \
88 mtx_assert(&(_sc)->sc_mtx, (_what))
89 #define UKSWITCH_TRYLOCK(_sc) \
90 mtx_trylock(&(_sc)->sc_mtx)
93 #define DPRINTF(dev, args...) device_printf(dev, args)
95 #define DPRINTF(dev, args...)
98 static inline int ukswitch_portforphy(struct ukswitch_softc *, int);
99 static void ukswitch_tick(void *);
100 static int ukswitch_ifmedia_upd(struct ifnet *);
101 static void ukswitch_ifmedia_sts(struct ifnet *, struct ifmediareq *);
104 ukswitch_probe(device_t dev)
106 struct ukswitch_softc *sc;
108 sc = device_get_softc(dev);
109 bzero(sc, sizeof(*sc));
111 device_set_desc_copy(dev, "Generic MDIO switch driver");
112 return (BUS_PROBE_DEFAULT);
116 ukswitch_attach_phys(struct ukswitch_softc *sc)
118 int phy, port = 0, err = 0;
121 /* PHYs need an interface, so we generate a dummy one */
122 snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->sc_dev));
123 for (phy = 0; phy < MII_NPHY; phy++) {
124 if (((1 << phy) & sc->phymask) == 0)
126 sc->ifpport[phy] = port;
127 sc->portphy[port] = phy;
128 sc->ifp[port] = if_alloc(IFT_ETHER);
129 sc->ifp[port]->if_softc = sc;
130 sc->ifp[port]->if_flags |= IFF_UP | IFF_BROADCAST |
131 IFF_DRV_RUNNING | IFF_SIMPLEX;
132 sc->ifname[port] = malloc(strlen(name)+1, M_UKSWITCH, M_WAITOK);
133 bcopy(name, sc->ifname[port], strlen(name)+1);
134 if_initname(sc->ifp[port], sc->ifname[port], port);
135 sc->miibus[port] = malloc(sizeof(device_t), M_UKSWITCH,
137 err = mii_attach(sc->sc_dev, sc->miibus[port], sc->ifp[port],
138 ukswitch_ifmedia_upd, ukswitch_ifmedia_sts, \
139 BMSR_DEFCAPMASK, phy + sc->phyoffset, MII_OFFSET_ANY, 0);
140 DPRINTF(sc->sc_dev, "%s attached to pseudo interface %s\n",
141 device_get_nameunit(*sc->miibus[port]),
142 sc->ifp[port]->if_xname);
144 device_printf(sc->sc_dev,
145 "attaching PHY %d failed\n",
149 sc->info.es_nports = port + 1;
150 if (++port >= sc->numports)
157 ukswitch_attach(device_t dev)
159 struct ukswitch_softc *sc;
162 sc = device_get_softc(dev);
165 mtx_init(&sc->sc_mtx, "ukswitch", NULL, MTX_DEF);
166 strlcpy(sc->info.es_name, device_get_desc(dev),
167 sizeof(sc->info.es_name));
176 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
177 "numports", &sc->numports);
178 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
179 "phymask", &sc->phymask);
180 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
181 "phyoffset", &sc->phyoffset);
182 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
183 "cpuport", &sc->cpuport);
184 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
185 "media", &sc->media);
187 /* Support only fast and giga ethernet. */
188 if (sc->media != 100 && sc->media != 1000)
191 if (sc->cpuport != -1)
192 /* Always attach the cpu port. */
193 sc->phymask |= (1 << sc->cpuport);
195 /* We do not support any vlan groups. */
196 sc->info.es_nvlangroups = 0;
198 sc->ifp = malloc(sizeof(struct ifnet *) * sc->numports, M_UKSWITCH,
200 sc->ifname = malloc(sizeof(char *) * sc->numports, M_UKSWITCH,
202 sc->miibus = malloc(sizeof(device_t *) * sc->numports, M_UKSWITCH,
204 sc->portphy = malloc(sizeof(int) * sc->numports, M_UKSWITCH,
208 * Attach the PHYs and complete the bus enumeration.
210 err = ukswitch_attach_phys(sc);
214 bus_generic_probe(dev);
215 bus_enumerate_hinted_children(dev);
216 err = bus_generic_attach(dev);
220 callout_init(&sc->callout_tick, 0);
228 ukswitch_detach(device_t dev)
230 struct ukswitch_softc *sc = device_get_softc(dev);
233 callout_drain(&sc->callout_tick);
235 for (i=0; i < MII_NPHY; i++) {
236 if (((1 << i) & sc->phymask) == 0)
238 port = ukswitch_portforphy(sc, i);
239 if (sc->miibus[port] != NULL)
240 device_delete_child(dev, (*sc->miibus[port]));
241 if (sc->ifp[port] != NULL)
242 if_free(sc->ifp[port]);
243 free(sc->ifname[port], M_UKSWITCH);
244 free(sc->miibus[port], M_UKSWITCH);
247 free(sc->portphy, M_UKSWITCH);
248 free(sc->miibus, M_UKSWITCH);
249 free(sc->ifname, M_UKSWITCH);
250 free(sc->ifp, M_UKSWITCH);
252 bus_generic_detach(dev);
253 mtx_destroy(&sc->sc_mtx);
259 * Convert PHY number to port number.
262 ukswitch_portforphy(struct ukswitch_softc *sc, int phy)
265 return (sc->ifpport[phy]);
268 static inline struct mii_data *
269 ukswitch_miiforport(struct ukswitch_softc *sc, int port)
272 if (port < 0 || port > sc->numports)
274 return (device_get_softc(*sc->miibus[port]));
277 static inline struct ifnet *
278 ukswitch_ifpforport(struct ukswitch_softc *sc, int port)
281 if (port < 0 || port > sc->numports)
283 return (sc->ifp[port]);
287 * Poll the status for all PHYs.
290 ukswitch_miipollstat(struct ukswitch_softc *sc)
293 struct mii_data *mii;
294 struct mii_softc *miisc;
296 UKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
298 for (i = 0; i < MII_NPHY; i++) {
299 if (((1 << i) & sc->phymask) == 0)
301 port = ukswitch_portforphy(sc, i);
302 if ((*sc->miibus[port]) == NULL)
304 mii = device_get_softc(*sc->miibus[port]);
305 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
306 if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) !=
310 mii_phy_update(miisc, MII_POLLSTAT);
316 ukswitch_tick(void *arg)
318 struct ukswitch_softc *sc = arg;
320 ukswitch_miipollstat(sc);
321 callout_reset(&sc->callout_tick, hz, ukswitch_tick, sc);
325 ukswitch_lock(device_t dev)
327 struct ukswitch_softc *sc = device_get_softc(dev);
329 UKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
334 ukswitch_unlock(device_t dev)
336 struct ukswitch_softc *sc = device_get_softc(dev);
338 UKSWITCH_LOCK_ASSERT(sc, MA_OWNED);
342 static etherswitch_info_t *
343 ukswitch_getinfo(device_t dev)
345 struct ukswitch_softc *sc = device_get_softc(dev);
351 ukswitch_getport(device_t dev, etherswitch_port_t *p)
353 struct ukswitch_softc *sc = device_get_softc(dev);
354 struct mii_data *mii;
355 struct ifmediareq *ifmr = &p->es_ifmr;
358 if (p->es_port < 0 || p->es_port >= sc->numports)
362 phy = sc->portphy[p->es_port];
363 mii = ukswitch_miiforport(sc, p->es_port);
364 if (sc->cpuport != -1 && phy == sc->cpuport) {
365 /* fill in fixed values for CPU port */
366 p->es_flags |= ETHERSWITCH_PORT_CPU;
368 if (sc->media == 100)
369 ifmr->ifm_current = ifmr->ifm_active =
370 IFM_ETHER | IFM_100_TX | IFM_FDX;
372 ifmr->ifm_current = ifmr->ifm_active =
373 IFM_ETHER | IFM_1000_T | IFM_FDX;
375 ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID;
376 } else if (mii != NULL) {
377 err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr,
378 &mii->mii_media, SIOCGIFMEDIA);
388 ukswitch_setport(device_t dev, etherswitch_port_t *p)
390 struct ukswitch_softc *sc = device_get_softc(dev);
392 struct mii_data *mii;
396 if (p->es_port < 0 || p->es_port >= sc->numports)
399 if (sc->portphy[p->es_port] == sc->cpuport)
402 mii = ukswitch_miiforport(sc, p->es_port);
406 ifp = ukswitch_ifpforport(sc, p->es_port);
408 ifm = &mii->mii_media;
409 err = ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA);
414 ukswitch_getvgroup(device_t dev, etherswitch_vlangroup_t *vg)
419 vg->es_member_ports = 0;
420 vg->es_untagged_ports = 0;
426 ukswitch_setvgroup(device_t dev, etherswitch_vlangroup_t *vg)
434 ukswitch_statchg(device_t dev)
437 DPRINTF(dev, "%s\n", __func__);
441 ukswitch_ifmedia_upd(struct ifnet *ifp)
443 struct ukswitch_softc *sc = ifp->if_softc;
444 struct mii_data *mii = ukswitch_miiforport(sc, ifp->if_dunit);
446 DPRINTF(sc->sc_dev, "%s\n", __func__);
454 ukswitch_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
456 struct ukswitch_softc *sc = ifp->if_softc;
457 struct mii_data *mii = ukswitch_miiforport(sc, ifp->if_dunit);
459 DPRINTF(sc->sc_dev, "%s\n", __func__);
464 ifmr->ifm_active = mii->mii_media_active;
465 ifmr->ifm_status = mii->mii_media_status;
469 ukswitch_readphy(device_t dev, int phy, int reg)
471 struct ukswitch_softc *sc;
474 sc = device_get_softc(dev);
475 UKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
477 if (phy < 0 || phy >= 32)
479 if (reg < 0 || reg >= 32)
483 data = MDIO_READREG(device_get_parent(dev), phy, reg);
490 ukswitch_writephy(device_t dev, int phy, int reg, int data)
492 struct ukswitch_softc *sc;
495 sc = device_get_softc(dev);
496 UKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
498 if (phy < 0 || phy >= 32)
500 if (reg < 0 || reg >= 32)
504 err = MDIO_WRITEREG(device_get_parent(dev), phy, reg, data);
511 ukswitch_readreg(device_t dev, int addr)
513 struct ukswitch_softc *sc;
515 sc = device_get_softc(dev);
516 UKSWITCH_LOCK_ASSERT(sc, MA_OWNED);
523 ukswitch_writereg(device_t dev, int addr, int value)
525 struct ukswitch_softc *sc;
527 sc = device_get_softc(dev);
528 UKSWITCH_LOCK_ASSERT(sc, MA_OWNED);
534 static device_method_t ukswitch_methods[] = {
535 /* Device interface */
536 DEVMETHOD(device_probe, ukswitch_probe),
537 DEVMETHOD(device_attach, ukswitch_attach),
538 DEVMETHOD(device_detach, ukswitch_detach),
541 DEVMETHOD(bus_add_child, device_add_child_ordered),
544 DEVMETHOD(miibus_readreg, ukswitch_readphy),
545 DEVMETHOD(miibus_writereg, ukswitch_writephy),
546 DEVMETHOD(miibus_statchg, ukswitch_statchg),
549 DEVMETHOD(mdio_readreg, ukswitch_readphy),
550 DEVMETHOD(mdio_writereg, ukswitch_writephy),
552 /* etherswitch interface */
553 DEVMETHOD(etherswitch_lock, ukswitch_lock),
554 DEVMETHOD(etherswitch_unlock, ukswitch_unlock),
555 DEVMETHOD(etherswitch_getinfo, ukswitch_getinfo),
556 DEVMETHOD(etherswitch_readreg, ukswitch_readreg),
557 DEVMETHOD(etherswitch_writereg, ukswitch_writereg),
558 DEVMETHOD(etherswitch_readphyreg, ukswitch_readphy),
559 DEVMETHOD(etherswitch_writephyreg, ukswitch_writephy),
560 DEVMETHOD(etherswitch_getport, ukswitch_getport),
561 DEVMETHOD(etherswitch_setport, ukswitch_setport),
562 DEVMETHOD(etherswitch_getvgroup, ukswitch_getvgroup),
563 DEVMETHOD(etherswitch_setvgroup, ukswitch_setvgroup),
568 DEFINE_CLASS_0(ukswitch, ukswitch_driver, ukswitch_methods,
569 sizeof(struct ukswitch_softc));
570 static devclass_t ukswitch_devclass;
572 DRIVER_MODULE(ukswitch, mdio, ukswitch_driver, ukswitch_devclass, 0, 0);
573 DRIVER_MODULE(miibus, ukswitch, miibus_driver, miibus_devclass, 0, 0);
574 DRIVER_MODULE(mdio, ukswitch, mdio_driver, mdio_devclass, 0, 0);
575 DRIVER_MODULE(etherswitch, ukswitch, etherswitch_driver, etherswitch_devclass, 0, 0);
576 MODULE_VERSION(ukswitch, 1);
577 MODULE_DEPEND(ukswitch, miibus, 1, 1, 1); /* XXX which versions? */
578 MODULE_DEPEND(ukswitch, etherswitch, 1, 1, 1); /* XXX which versions? */