2 * Copyright (c) 2016-2017 Hiroki Mori
3 * Copyright (c) 2013 Luiz Otavio O Souza.
4 * Copyright (c) 2011-2012 Stefan Bethke.
5 * Copyright (c) 2012 Adrian Chadd.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * This code is Marvell 88E6060 ethernet switch support code on etherswitch
35 * 88E6060 support is only port vlan support. Not support ingress/egress
37 * 88E6065 support is port and dot1q vlan. Also group base tag support.
40 #include <sys/param.h>
42 #include <sys/errno.h>
43 #include <sys/kernel.h>
45 #include <sys/malloc.h>
46 #include <sys/module.h>
47 #include <sys/mutex.h>
48 #include <sys/socket.h>
49 #include <sys/sockio.h>
50 #include <sys/sysctl.h>
51 #include <sys/systm.h>
54 #include <net/if_var.h>
55 #include <net/ethernet.h>
56 #include <net/if_media.h>
57 #include <net/if_types.h>
59 #include <machine/bus.h>
60 #include <dev/mii/mii.h>
61 #include <dev/mii/miivar.h>
62 #include <dev/mdio/mdio.h>
64 #include <dev/etherswitch/etherswitch.h>
67 #include "miibus_if.h"
68 #include "etherswitch_if.h"
70 #define CORE_REGISTER 0x8
73 #define PORT_CONTROL 4
74 #define ENGRESSFSHIFT 2
75 #define ENGRESSFMASK 3
76 #define ENGRESSTAGSHIFT 12
77 #define ENGRESSTAGMASK 3
79 #define PORT_VLAN_MAP 6
80 #define FORCEMAPSHIFT 8
81 #define FORCEMAPMASK 1
83 #define PORT_DEFVLAN 7
84 #define DEFVIDMASK 0xfff
87 #define PORT_CONTROL2 8
88 #define DOT1QMODESHIFT 10
89 #define DOT1QMODEMASK 3
91 #define DOT1QFALLBACK 1
95 #define GLOBAL_REGISTER 0xf
97 #define VTU_OPERATION 5
99 #define VTU_DATA1_REG 7
100 #define VTU_DATA2_REG 8
101 #define VTU_DATA3_REG 9
102 #define VTU_BUSY 0x8000
104 #define VTU_LOAD_PURGE 3
105 #define VTU_GET_NEXT 4
106 #define VTU_VIOLATION 7
108 MALLOC_DECLARE(M_E6060SW);
109 MALLOC_DEFINE(M_E6060SW, "e6060sw", "e6060sw data structures");
111 struct e6060sw_softc {
112 struct mtx sc_mtx; /* serialize access to softc */
115 int media; /* cpu port media */
116 int cpuport; /* which PHY is connected to the CPU */
117 int phymask; /* PHYs we manage */
118 int numports; /* number of ports */
119 int ifpport[MII_NPHY];
124 struct callout callout_tick;
125 etherswitch_info_t info;
130 /* Switch Identifier DeviceID */
136 #define E6060SW_LOCK(_sc) \
137 mtx_lock(&(_sc)->sc_mtx)
138 #define E6060SW_UNLOCK(_sc) \
139 mtx_unlock(&(_sc)->sc_mtx)
140 #define E6060SW_LOCK_ASSERT(_sc, _what) \
141 mtx_assert(&(_sc)->sc_mtx, (_what))
142 #define E6060SW_TRYLOCK(_sc) \
143 mtx_trylock(&(_sc)->sc_mtx)
146 #define DPRINTF(dev, args...) device_printf(dev, args)
148 #define DPRINTF(dev, args...)
151 static inline int e6060sw_portforphy(struct e6060sw_softc *, int);
152 static void e6060sw_tick(void *);
153 static int e6060sw_ifmedia_upd(struct ifnet *);
154 static void e6060sw_ifmedia_sts(struct ifnet *, struct ifmediareq *);
156 static void e6060sw_setup(device_t dev);
157 static int e6060sw_read_vtu(device_t dev, int num, int *data1, int *data2);
158 static void e6060sw_set_vtu(device_t dev, int num, int data1, int data2);
161 e6060sw_probe(device_t dev)
164 struct e6060sw_softc *sc;
169 sc = device_get_softc(dev);
170 bzero(sc, sizeof(*sc));
173 for (i = 0; i < 2; ++i) {
174 data = MDIO_READREG(device_get_parent(dev),
175 CORE_REGISTER + i * 0x10, SWITCH_ID);
177 device_printf(dev,"Switch Identifier Register %x\n",
181 if (devid == E6060 ||
182 devid == E6063 || devid == E6065) {
183 sc->sw_model = devid;
184 sc->smi_offset = i * 0x10;
191 else if (devid == E6063)
193 else if (devid == E6065)
198 sprintf(desc, "Marvell %s MDIO switch driver at 0x%02x",
199 devname, sc->smi_offset);
200 device_set_desc_copy(dev, desc);
202 return (BUS_PROBE_DEFAULT);
206 e6060sw_attach_phys(struct e6060sw_softc *sc)
213 /* PHYs need an interface, so we generate a dummy one */
214 snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->sc_dev));
215 for (phy = 0; phy < sc->numports; phy++) {
216 if (((1 << phy) & sc->phymask) == 0)
218 sc->ifpport[phy] = port;
219 sc->portphy[port] = phy;
220 sc->ifp[port] = if_alloc(IFT_ETHER);
221 if (sc->ifp[port] == NULL) {
222 device_printf(sc->sc_dev, "couldn't allocate ifnet structure\n");
227 sc->ifp[port]->if_softc = sc;
228 sc->ifp[port]->if_flags |= IFF_UP | IFF_BROADCAST |
229 IFF_DRV_RUNNING | IFF_SIMPLEX;
230 if_initname(sc->ifp[port], name, port);
231 sc->miibus[port] = malloc(sizeof(device_t), M_E6060SW,
233 err = mii_attach(sc->sc_dev, sc->miibus[port], sc->ifp[port],
234 e6060sw_ifmedia_upd, e6060sw_ifmedia_sts, \
235 BMSR_DEFCAPMASK, phy + sc->smi_offset, MII_OFFSET_ANY, 0);
236 DPRINTF(sc->sc_dev, "%s attached to pseudo interface %s\n",
237 device_get_nameunit(*sc->miibus[port]),
238 sc->ifp[port]->if_xname);
240 device_printf(sc->sc_dev,
241 "attaching PHY %d failed\n",
247 sc->info.es_nports = port;
248 if (sc->cpuport != -1) {
249 /* assume cpuport is last one */
250 sc->ifpport[sc->cpuport] = port;
251 sc->portphy[port] = sc->cpuport;
252 ++sc->info.es_nports;
258 e6060sw_attach(device_t dev)
260 struct e6060sw_softc *sc;
263 sc = device_get_softc(dev);
267 mtx_init(&sc->sc_mtx, "e6060sw", NULL, MTX_DEF);
268 strlcpy(sc->info.es_name, device_get_desc(dev),
269 sizeof(sc->info.es_name));
272 if (sc->sw_model == E6063) {
283 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
284 "numports", &sc->numports);
285 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
286 "phymask", &sc->phymask);
287 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
288 "cpuport", &sc->cpuport);
289 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
290 "media", &sc->media);
292 if (sc->sw_model == E6060) {
293 sc->info.es_nvlangroups = sc->numports;
294 sc->info.es_vlan_caps = ETHERSWITCH_VLAN_PORT;
296 sc->info.es_nvlangroups = 64;
297 sc->info.es_vlan_caps = ETHERSWITCH_VLAN_PORT |
298 ETHERSWITCH_VLAN_DOT1Q;
303 sc->ifp = malloc(sizeof(struct ifnet *) * sc->numports, M_E6060SW,
305 sc->ifname = malloc(sizeof(char *) * sc->numports, M_E6060SW,
307 sc->miibus = malloc(sizeof(device_t *) * sc->numports, M_E6060SW,
309 sc->portphy = malloc(sizeof(int) * sc->numports, M_E6060SW,
313 * Attach the PHYs and complete the bus enumeration.
315 err = e6060sw_attach_phys(sc);
319 bus_generic_probe(dev);
320 bus_enumerate_hinted_children(dev);
321 err = bus_generic_attach(dev);
325 callout_init(&sc->callout_tick, 0);
333 e6060sw_detach(device_t dev)
335 struct e6060sw_softc *sc;
338 sc = device_get_softc(dev);
340 callout_drain(&sc->callout_tick);
342 for (i = 0; i < MII_NPHY; i++) {
343 if (((1 << i) & sc->phymask) == 0)
345 port = e6060sw_portforphy(sc, i);
346 if (sc->miibus[port] != NULL)
347 device_delete_child(dev, (*sc->miibus[port]));
348 if (sc->ifp[port] != NULL)
349 if_free(sc->ifp[port]);
350 free(sc->ifname[port], M_E6060SW);
351 free(sc->miibus[port], M_E6060SW);
354 free(sc->portphy, M_E6060SW);
355 free(sc->miibus, M_E6060SW);
356 free(sc->ifname, M_E6060SW);
357 free(sc->ifp, M_E6060SW);
359 bus_generic_detach(dev);
360 mtx_destroy(&sc->sc_mtx);
366 * Convert PHY number to port number.
369 e6060sw_portforphy(struct e6060sw_softc *sc, int phy)
372 return (sc->ifpport[phy]);
375 static inline struct mii_data *
376 e6060sw_miiforport(struct e6060sw_softc *sc, int port)
379 if (port < 0 || port > sc->numports)
381 if (port == sc->cpuport)
383 return (device_get_softc(*sc->miibus[port]));
386 static inline struct ifnet *
387 e6060sw_ifpforport(struct e6060sw_softc *sc, int port)
390 if (port < 0 || port > sc->numports)
392 return (sc->ifp[port]);
396 * Poll the status for all PHYs.
399 e6060sw_miipollstat(struct e6060sw_softc *sc)
402 struct mii_data *mii;
403 struct mii_softc *miisc;
405 E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED);
407 for (i = 0; i < MII_NPHY; i++) {
408 if (((1 << i) & sc->phymask) == 0)
410 port = e6060sw_portforphy(sc, i);
411 if ((*sc->miibus[port]) == NULL)
413 mii = device_get_softc(*sc->miibus[port]);
414 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
415 if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) !=
419 mii_phy_update(miisc, MII_POLLSTAT);
425 e6060sw_tick(void *arg)
427 struct e6060sw_softc *sc;
431 e6060sw_miipollstat(sc);
432 callout_reset(&sc->callout_tick, hz, e6060sw_tick, sc);
436 e6060sw_lock(device_t dev)
438 struct e6060sw_softc *sc;
440 sc = device_get_softc(dev);
442 E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED);
447 e6060sw_unlock(device_t dev)
449 struct e6060sw_softc *sc;
451 sc = device_get_softc(dev);
453 E6060SW_LOCK_ASSERT(sc, MA_OWNED);
457 static etherswitch_info_t *
458 e6060sw_getinfo(device_t dev)
460 struct e6060sw_softc *sc;
462 sc = device_get_softc(dev);
468 e6060sw_getport(device_t dev, etherswitch_port_t *p)
470 struct e6060sw_softc *sc;
471 struct mii_data *mii;
472 struct ifmediareq *ifmr;
475 sc = device_get_softc(dev);
478 if (p->es_port < 0 || p->es_port >= sc->numports)
482 if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
483 p->es_pvid = MDIO_READREG(device_get_parent(dev),
484 CORE_REGISTER + sc->smi_offset + p->es_port,
485 PORT_DEFVLAN) & 0xfff;
488 phy = sc->portphy[p->es_port];
489 mii = e6060sw_miiforport(sc, p->es_port);
490 if (sc->cpuport != -1 && phy == sc->cpuport) {
491 /* fill in fixed values for CPU port */
492 p->es_flags |= ETHERSWITCH_PORT_CPU;
494 if (sc->media == 100)
495 ifmr->ifm_current = ifmr->ifm_active =
496 IFM_ETHER | IFM_100_TX | IFM_FDX;
498 ifmr->ifm_current = ifmr->ifm_active =
499 IFM_ETHER | IFM_1000_T | IFM_FDX;
501 ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID;
502 } else if (mii != NULL) {
503 err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr,
504 &mii->mii_media, SIOCGIFMEDIA);
514 e6060sw_setport(device_t dev, etherswitch_port_t *p)
516 struct e6060sw_softc *sc;
518 struct mii_data *mii;
523 sc = device_get_softc(dev);
525 if (p->es_port < 0 || p->es_port >= sc->numports)
528 if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
529 data = MDIO_READREG(device_get_parent(dev),
530 CORE_REGISTER + sc->smi_offset + p->es_port,
535 MDIO_WRITEREG(device_get_parent(dev),
536 CORE_REGISTER + sc->smi_offset + p->es_port,
540 if (sc->portphy[p->es_port] == sc->cpuport)
543 mii = e6060sw_miiforport(sc, p->es_port);
547 ifp = e6060sw_ifpforport(sc, p->es_port);
549 ifm = &mii->mii_media;
550 err = ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA);
555 e6060sw_getvgroup(device_t dev, etherswitch_vlangroup_t *vg)
557 struct e6060sw_softc *sc;
562 sc = device_get_softc(dev);
564 if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) {
565 vg->es_vid = ETHERSWITCH_VID_VALID;
566 vg->es_vid |= vg->es_vlangroup;
567 data1 = MDIO_READREG(device_get_parent(dev),
568 CORE_REGISTER + sc->smi_offset + vg->es_vlangroup,
570 vg->es_member_ports = data1 & 0x3f;
571 vg->es_untagged_ports = vg->es_member_ports;
573 } else if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
574 if (vg->es_vlangroup == 0)
576 vid = e6060sw_read_vtu(dev, vg->es_vlangroup, &data1, &data2);
578 vg->es_vid = ETHERSWITCH_VID_VALID;
580 vg->es_member_ports = 0;
581 vg->es_untagged_ports = 0;
582 for (i = 0; i < 4; ++i) {
583 tag = data1 >> (i * 4) & 3;
584 if (tag == 0 || tag == 1) {
585 vg->es_member_ports |= 1 << i;
586 vg->es_untagged_ports |= 1 << i;
587 } else if (tag == 2) {
588 vg->es_member_ports |= 1 << i;
591 for (i = 0; i < 2; ++i) {
592 tag = data2 >> (i * 4) & 3;
593 if (tag == 0 || tag == 1) {
594 vg->es_member_ports |= 1 << (i + 4);
595 vg->es_untagged_ports |= 1 << (i + 4);
596 } else if (tag == 2) {
597 vg->es_member_ports |= 1 << (i + 4);
609 e6060sw_setvgroup(device_t dev, etherswitch_vlangroup_t *vg)
611 struct e6060sw_softc *sc;
615 sc = device_get_softc(dev);
617 if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) {
618 data1 = MDIO_READREG(device_get_parent(dev),
619 CORE_REGISTER + sc->smi_offset + vg->es_vlangroup,
622 data1 |= vg->es_member_ports;
623 MDIO_WRITEREG(device_get_parent(dev),
624 CORE_REGISTER + sc->smi_offset + vg->es_vlangroup,
625 PORT_VLAN_MAP, data1);
626 } else if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
627 if (vg->es_vlangroup == 0)
631 for (i = 0; i < 6; ++i) {
632 if (vg->es_member_ports &
633 vg->es_untagged_ports & (1 << i)) {
635 data1 |= (0xd << i * 4);
637 data2 |= (0xd << (i - 4) * 4);
639 } else if (vg->es_member_ports & (1 << i)) {
641 data1 |= (0xe << i * 4);
643 data2 |= (0xe << (i - 4) * 4);
647 data1 |= (0x3 << i * 4);
649 data2 |= (0x3 << (i - 4) * 4);
653 e6060sw_set_vtu(dev, vg->es_vlangroup, data1, data2);
659 e6060sw_reset_vlans(device_t dev)
661 struct e6060sw_softc *sc;
666 sc = device_get_softc(dev);
668 for (i = 0; i <= sc->numports; i++) {
669 ports = (1 << (sc->numports + 1)) - 1;
671 if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) {
673 } else if (sc->vlan_mode == 0) {
679 MDIO_WRITEREG(device_get_parent(dev),
680 CORE_REGISTER + sc->smi_offset + i, PORT_VLAN_MAP, data);
685 e6060sw_setup(device_t dev)
687 struct e6060sw_softc *sc;
691 sc = device_get_softc(dev);
693 for (i = 0; i <= sc->numports; i++) {
694 if (sc->sw_model == E6063 || sc->sw_model == E6065) {
695 data = MDIO_READREG(device_get_parent(dev),
696 CORE_REGISTER + sc->smi_offset + i, PORT_VLAN_MAP);
697 data &= ~(FORCEMAPMASK << FORCEMAPSHIFT);
698 MDIO_WRITEREG(device_get_parent(dev),
699 CORE_REGISTER + sc->smi_offset + i,
700 PORT_VLAN_MAP, data);
702 data = MDIO_READREG(device_get_parent(dev),
703 CORE_REGISTER + sc->smi_offset + i, PORT_CONTROL);
704 data |= 3 << ENGRESSFSHIFT;
705 MDIO_WRITEREG(device_get_parent(dev),
706 CORE_REGISTER + sc->smi_offset + i,
713 e6060sw_dot1q_mode(device_t dev, int mode)
715 struct e6060sw_softc *sc;
719 sc = device_get_softc(dev);
721 for (i = 0; i <= sc->numports; i++) {
722 data = MDIO_READREG(device_get_parent(dev),
723 CORE_REGISTER + sc->smi_offset + i, PORT_CONTROL2);
724 data &= ~(DOT1QMODEMASK << DOT1QMODESHIFT);
725 data |= mode << DOT1QMODESHIFT;
726 MDIO_WRITEREG(device_get_parent(dev),
727 CORE_REGISTER + sc->smi_offset + i, PORT_CONTROL2, data);
729 data = MDIO_READREG(device_get_parent(dev),
730 CORE_REGISTER + sc->smi_offset + i,
734 MDIO_WRITEREG(device_get_parent(dev),
735 CORE_REGISTER + sc->smi_offset + i,
741 e6060sw_getconf(device_t dev, etherswitch_conf_t *conf)
743 struct e6060sw_softc *sc;
745 sc = device_get_softc(dev);
747 /* Return the VLAN mode. */
748 conf->cmd = ETHERSWITCH_CONF_VLAN_MODE;
749 conf->vlan_mode = sc->vlan_mode;
755 e6060sw_init_vtu(device_t dev)
757 struct e6060sw_softc *sc;
760 sc = device_get_softc(dev);
762 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset,
763 VTU_OPERATION, VTU_BUSY | (VTU_FLASH << 12));
765 busy = MDIO_READREG(device_get_parent(dev),
766 GLOBAL_REGISTER + sc->smi_offset, VTU_OPERATION);
767 if ((busy & VTU_BUSY) == 0)
771 /* initial member set at vlan 1*/
772 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset,
773 VTU_DATA1_REG, 0xcccc);
774 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset,
775 VTU_DATA2_REG, 0x00cc);
776 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset,
777 VTU_VID_REG, 0x1000 | 1);
778 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset,
779 VTU_OPERATION, VTU_BUSY | (VTU_LOAD_PURGE << 12) | 1);
781 busy = MDIO_READREG(device_get_parent(dev),
782 GLOBAL_REGISTER + sc->smi_offset, VTU_OPERATION);
783 if ((busy & VTU_BUSY) == 0)
789 e6060sw_set_vtu(device_t dev, int num, int data1, int data2)
791 struct e6060sw_softc *sc;
794 sc = device_get_softc(dev);
796 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset,
797 VTU_DATA1_REG, data1);
798 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset,
799 VTU_DATA2_REG, data2);
800 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset,
801 VTU_VID_REG, 0x1000 | num);
802 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset,
803 VTU_OPERATION, VTU_BUSY | (VTU_LOAD_PURGE << 12) | num);
805 busy = MDIO_READREG(device_get_parent(dev),
806 GLOBAL_REGISTER + sc->smi_offset, VTU_OPERATION);
807 if ((busy & VTU_BUSY) == 0)
814 e6060sw_read_vtu(device_t dev, int num, int *data1, int *data2)
816 struct e6060sw_softc *sc;
819 sc = device_get_softc(dev);
823 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset,
824 VTU_VID_REG, num & 0xfff);
826 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset,
827 VTU_OPERATION, VTU_BUSY | (VTU_GET_NEXT << 12));
829 busy = MDIO_READREG(device_get_parent(dev),
830 GLOBAL_REGISTER + sc->smi_offset, VTU_OPERATION);
831 if ((busy & VTU_BUSY) == 0)
835 int vid = MDIO_READREG(device_get_parent(dev),
836 GLOBAL_REGISTER + sc->smi_offset, VTU_VID_REG);
838 *data1 = MDIO_READREG(device_get_parent(dev),
839 GLOBAL_REGISTER + sc->smi_offset, VTU_DATA1_REG);
840 *data2 = MDIO_READREG(device_get_parent(dev),
841 GLOBAL_REGISTER + sc->smi_offset, VTU_DATA2_REG);
843 return (vid & 0xfff);
850 e6060sw_setconf(device_t dev, etherswitch_conf_t *conf)
852 struct e6060sw_softc *sc;
854 sc = device_get_softc(dev);
856 /* Set the VLAN mode. */
857 if (conf->cmd & ETHERSWITCH_CONF_VLAN_MODE) {
858 if (conf->vlan_mode == ETHERSWITCH_VLAN_PORT) {
859 sc->vlan_mode = ETHERSWITCH_VLAN_PORT;
860 e6060sw_dot1q_mode(dev, DOT1QNONE);
861 e6060sw_reset_vlans(dev);
862 } else if ((sc->sw_model == E6063 || sc->sw_model == E6065) &&
863 conf->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
864 sc->vlan_mode = ETHERSWITCH_VLAN_DOT1Q;
865 e6060sw_dot1q_mode(dev, DOT1QSECURE);
866 e6060sw_init_vtu(dev);
870 e6060sw_dot1q_mode(dev, DOT1QNONE);
871 e6060sw_reset_vlans(dev);
879 e6060sw_statchg(device_t dev)
882 DPRINTF(dev, "%s\n", __func__);
886 e6060sw_ifmedia_upd(struct ifnet *ifp)
888 struct e6060sw_softc *sc;
889 struct mii_data *mii;
892 mii = e6060sw_miiforport(sc, ifp->if_dunit);
894 DPRINTF(sc->sc_dev, "%s\n", __func__);
902 e6060sw_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
904 struct e6060sw_softc *sc;
905 struct mii_data *mii;
908 mii = e6060sw_miiforport(sc, ifp->if_dunit);
910 DPRINTF(sc->sc_dev, "%s\n", __func__);
915 ifmr->ifm_active = mii->mii_media_active;
916 ifmr->ifm_status = mii->mii_media_status;
920 e6060sw_readphy(device_t dev, int phy, int reg)
922 struct e6060sw_softc *sc;
925 sc = device_get_softc(dev);
926 E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED);
928 if (phy < 0 || phy >= 32)
930 if (reg < 0 || reg >= 32)
934 data = MDIO_READREG(device_get_parent(dev), phy, reg);
941 e6060sw_writephy(device_t dev, int phy, int reg, int data)
943 struct e6060sw_softc *sc;
946 sc = device_get_softc(dev);
947 E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED);
949 if (phy < 0 || phy >= 32)
951 if (reg < 0 || reg >= 32)
955 err = MDIO_WRITEREG(device_get_parent(dev), phy, reg, data);
961 /* addr is 5-8 bit is SMI Device Addres, 0-4 bit is SMI Register Address */
964 e6060sw_readreg(device_t dev, int addr)
966 int devaddr, regaddr;
968 devaddr = (addr >> 5) & 0x1f;
969 regaddr = addr & 0x1f;
971 return MDIO_READREG(device_get_parent(dev), devaddr, regaddr);
974 /* addr is 5-8 bit is SMI Device Addres, 0-4 bit is SMI Register Address */
977 e6060sw_writereg(device_t dev, int addr, int value)
979 int devaddr, regaddr;
981 devaddr = (addr >> 5) & 0x1f;
982 regaddr = addr & 0x1f;
984 return (MDIO_WRITEREG(device_get_parent(dev), devaddr, regaddr, value));
987 static device_method_t e6060sw_methods[] = {
988 /* Device interface */
989 DEVMETHOD(device_probe, e6060sw_probe),
990 DEVMETHOD(device_attach, e6060sw_attach),
991 DEVMETHOD(device_detach, e6060sw_detach),
994 DEVMETHOD(bus_add_child, device_add_child_ordered),
997 DEVMETHOD(miibus_readreg, e6060sw_readphy),
998 DEVMETHOD(miibus_writereg, e6060sw_writephy),
999 DEVMETHOD(miibus_statchg, e6060sw_statchg),
1001 /* MDIO interface */
1002 DEVMETHOD(mdio_readreg, e6060sw_readphy),
1003 DEVMETHOD(mdio_writereg, e6060sw_writephy),
1005 /* etherswitch interface */
1006 DEVMETHOD(etherswitch_lock, e6060sw_lock),
1007 DEVMETHOD(etherswitch_unlock, e6060sw_unlock),
1008 DEVMETHOD(etherswitch_getinfo, e6060sw_getinfo),
1009 DEVMETHOD(etherswitch_readreg, e6060sw_readreg),
1010 DEVMETHOD(etherswitch_writereg, e6060sw_writereg),
1011 DEVMETHOD(etherswitch_readphyreg, e6060sw_readphy),
1012 DEVMETHOD(etherswitch_writephyreg, e6060sw_writephy),
1013 DEVMETHOD(etherswitch_getport, e6060sw_getport),
1014 DEVMETHOD(etherswitch_setport, e6060sw_setport),
1015 DEVMETHOD(etherswitch_getvgroup, e6060sw_getvgroup),
1016 DEVMETHOD(etherswitch_setvgroup, e6060sw_setvgroup),
1017 DEVMETHOD(etherswitch_setconf, e6060sw_setconf),
1018 DEVMETHOD(etherswitch_getconf, e6060sw_getconf),
1023 DEFINE_CLASS_0(e6060sw, e6060sw_driver, e6060sw_methods,
1024 sizeof(struct e6060sw_softc));
1025 static devclass_t e6060sw_devclass;
1027 DRIVER_MODULE(e6060sw, mdio, e6060sw_driver, e6060sw_devclass, 0, 0);
1028 DRIVER_MODULE(miibus, e6060sw, miibus_driver, miibus_devclass, 0, 0);
1029 DRIVER_MODULE(mdio, e6060sw, mdio_driver, mdio_devclass, 0, 0);
1030 DRIVER_MODULE(etherswitch, e6060sw, etherswitch_driver, etherswitch_devclass, 0, 0);
1031 MODULE_VERSION(e6060sw, 1);
1032 MODULE_DEPEND(e6060sw, miibus, 1, 1, 1); /* XXX which versions? */
1033 MODULE_DEPEND(e6060sw, etherswitch, 1, 1, 1); /* XXX which versions? */