2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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
32 #include <sys/param.h>
34 #include <sys/errno.h>
35 #include <sys/kernel.h>
36 #include <sys/malloc.h>
37 #include <sys/module.h>
38 #include <sys/socket.h>
39 #include <sys/sockio.h>
40 #include <sys/sysctl.h>
41 #include <sys/systm.h>
44 #include <net/if_var.h>
45 #include <net/if_arp.h>
46 #include <net/ethernet.h>
47 #include <net/if_dl.h>
48 #include <net/if_media.h>
49 #include <net/if_types.h>
51 #include <machine/bus.h>
52 #include <dev/iicbus/iic.h>
53 #include <dev/iicbus/iiconf.h>
54 #include <dev/iicbus/iicbus.h>
55 #include <dev/mii/mii.h>
56 #include <dev/mii/miivar.h>
57 #include <dev/mdio/mdio.h>
59 #include <dev/etherswitch/etherswitch.h>
61 #include <dev/etherswitch/arswitch/arswitchreg.h>
62 #include <dev/etherswitch/arswitch/arswitchvar.h>
63 #include <dev/etherswitch/arswitch/arswitch_reg.h>
64 #include <dev/etherswitch/arswitch/arswitch_phy.h>
65 #include <dev/etherswitch/arswitch/arswitch_vlans.h>
67 #include <dev/etherswitch/arswitch/arswitch_7240.h>
68 #include <dev/etherswitch/arswitch/arswitch_8216.h>
69 #include <dev/etherswitch/arswitch/arswitch_8226.h>
70 #include <dev/etherswitch/arswitch/arswitch_8316.h>
71 #include <dev/etherswitch/arswitch/arswitch_8327.h>
72 #include <dev/etherswitch/arswitch/arswitch_9340.h>
75 #include "miibus_if.h"
76 #include "etherswitch_if.h"
78 /* Map ETHERSWITCH_PORT_LED_* to Atheros pattern codes */
79 static int led_pattern_table[] = {
80 [ETHERSWITCH_PORT_LED_DEFAULT] = 0x3,
81 [ETHERSWITCH_PORT_LED_ON] = 0x2,
82 [ETHERSWITCH_PORT_LED_OFF] = 0x0,
83 [ETHERSWITCH_PORT_LED_BLINK] = 0x1
86 static inline int arswitch_portforphy(int phy);
87 static void arswitch_tick(void *arg);
88 static int arswitch_ifmedia_upd(struct ifnet *);
89 static void arswitch_ifmedia_sts(struct ifnet *, struct ifmediareq *);
90 static int ar8xxx_port_vlan_setup(struct arswitch_softc *sc,
91 etherswitch_port_t *p);
92 static int ar8xxx_port_vlan_get(struct arswitch_softc *sc,
93 etherswitch_port_t *p);
94 static int arswitch_setled(struct arswitch_softc *sc, int phy, int led,
98 arswitch_probe(device_t dev)
100 struct arswitch_softc *sc;
102 char *chipname, desc[256];
104 sc = device_get_softc(dev);
105 bzero(sc, sizeof(*sc));
109 if (ar7240_probe(dev) == 0) {
111 sc->sc_switchtype = AR8X16_SWITCH_AR7240;
112 sc->is_internal_switch = 1;
118 if (ar9340_probe(dev) == 0) {
120 sc->sc_switchtype = AR8X16_SWITCH_AR9340;
121 sc->is_internal_switch = 1;
127 id = arswitch_readreg(dev, AR8X16_REG_MASK_CTRL);
128 sc->chip_rev = (id & AR8X16_MASK_CTRL_REV_MASK);
129 sc->chip_ver = (id & AR8X16_MASK_CTRL_VER_MASK) > AR8X16_MASK_CTRL_VER_SHIFT;
130 switch (id & (AR8X16_MASK_CTRL_VER_MASK | AR8X16_MASK_CTRL_REV_MASK)) {
133 sc->sc_switchtype = AR8X16_SWITCH_AR8216;
137 sc->sc_switchtype = AR8X16_SWITCH_AR8226;
139 /* 0x0301 - AR8236 */
143 sc->sc_switchtype = AR8X16_SWITCH_AR8316;
148 sc->sc_switchtype = AR8X16_SWITCH_AR8327;
149 sc->mii_lo_first = 1;
157 DPRINTF(sc, ARSWITCH_DBG_ANY, "chipname=%s, id=%08x\n", chipname, id);
158 if (chipname != NULL) {
159 snprintf(desc, sizeof(desc),
160 "Atheros %s Ethernet Switch (ver %d rev %d)",
164 device_set_desc_copy(dev, desc);
165 return (BUS_PROBE_DEFAULT);
171 arswitch_attach_phys(struct arswitch_softc *sc)
176 /* PHYs need an interface, so we generate a dummy one */
177 snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->sc_dev));
178 for (phy = 0; phy < sc->numphys; phy++) {
179 sc->ifp[phy] = if_alloc(IFT_ETHER);
180 if (sc->ifp[phy] == NULL) {
181 device_printf(sc->sc_dev, "couldn't allocate ifnet structure\n");
186 sc->ifp[phy]->if_softc = sc;
187 sc->ifp[phy]->if_flags |= IFF_UP | IFF_BROADCAST |
188 IFF_DRV_RUNNING | IFF_SIMPLEX;
189 sc->ifname[phy] = malloc(strlen(name)+1, M_DEVBUF, M_WAITOK);
190 bcopy(name, sc->ifname[phy], strlen(name)+1);
191 if_initname(sc->ifp[phy], sc->ifname[phy],
192 arswitch_portforphy(phy));
193 err = mii_attach(sc->sc_dev, &sc->miibus[phy], sc->ifp[phy],
194 arswitch_ifmedia_upd, arswitch_ifmedia_sts, \
195 BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0);
197 DPRINTF(sc->sc_dev, "%s attached to pseudo interface %s\n",
198 device_get_nameunit(sc->miibus[phy]),
199 sc->ifp[phy]->if_xname);
202 device_printf(sc->sc_dev,
203 "attaching PHY %d failed\n",
208 if (AR8X16_IS_SWITCH(sc, AR8327)) {
210 char ledname[IFNAMSIZ+4];
212 for (led = 0; led < 3; led++) {
213 sprintf(ledname, "%s%dled%d", name,
214 arswitch_portforphy(phy), led+1);
215 sc->dev_led[phy][led].sc = sc;
216 sc->dev_led[phy][led].phy = phy;
217 sc->dev_led[phy][led].lednum = led;
225 arswitch_reset(device_t dev)
228 arswitch_writereg(dev, AR8X16_REG_MASK_CTRL,
229 AR8X16_MASK_CTRL_SOFT_RESET);
231 if (arswitch_readreg(dev, AR8X16_REG_MASK_CTRL) &
232 AR8X16_MASK_CTRL_SOFT_RESET) {
233 device_printf(dev, "unable to reset switch\n");
240 arswitch_set_vlan_mode(struct arswitch_softc *sc, uint32_t mode)
243 /* Check for invalid modes. */
244 if ((mode & sc->info.es_vlan_caps) != mode)
248 case ETHERSWITCH_VLAN_DOT1Q:
249 sc->vlan_mode = ETHERSWITCH_VLAN_DOT1Q;
251 case ETHERSWITCH_VLAN_PORT:
252 sc->vlan_mode = ETHERSWITCH_VLAN_PORT;
259 sc->hal.arswitch_vlan_init_hw(sc);
265 ar8xxx_port_init(struct arswitch_softc *sc, int port)
269 if (port == AR8X16_PORT_CPU) {
270 arswitch_writereg(sc->sc_dev, AR8X16_REG_PORT_STS(0),
271 (AR8X16_IS_SWITCH(sc, AR8216) ?
272 AR8X16_PORT_STS_SPEED_100 : AR8X16_PORT_STS_SPEED_1000) |
273 (AR8X16_IS_SWITCH(sc, AR8216) ? 0 : AR8X16_PORT_STS_RXFLOW) |
274 (AR8X16_IS_SWITCH(sc, AR8216) ? 0 : AR8X16_PORT_STS_TXFLOW) |
275 AR8X16_PORT_STS_RXMAC |
276 AR8X16_PORT_STS_TXMAC |
277 AR8X16_PORT_STS_DUPLEX);
278 arswitch_writereg(sc->sc_dev, AR8X16_REG_PORT_CTRL(0),
279 arswitch_readreg(sc->sc_dev, AR8X16_REG_PORT_CTRL(0)) &
280 ~AR8X16_PORT_CTRL_HEADER);
282 /* Set ports to auto negotiation. */
283 arswitch_writereg(sc->sc_dev, AR8X16_REG_PORT_STS(port),
284 AR8X16_PORT_STS_LINK_AUTO);
285 arswitch_writereg(sc->sc_dev, AR8X16_REG_PORT_CTRL(port),
286 arswitch_readreg(sc->sc_dev, AR8X16_REG_PORT_CTRL(port)) &
287 ~AR8X16_PORT_CTRL_HEADER);
292 ar8xxx_atu_wait_ready(struct arswitch_softc *sc)
296 ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
298 ret = arswitch_waitreg(sc->sc_dev,
308 * Flush all ATU entries.
311 ar8xxx_atu_flush(struct arswitch_softc *sc)
315 ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
317 DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: flushing all ports\n", __func__);
319 ret = ar8xxx_atu_wait_ready(sc);
321 device_printf(sc->sc_dev, "%s: waitreg failed\n", __func__);
324 arswitch_writereg(sc->sc_dev,
326 AR8216_ATU_OP_FLUSH | AR8216_ATU_ACTIVE);
332 * Flush ATU entries for a single port.
335 ar8xxx_atu_flush_port(struct arswitch_softc *sc, int port)
339 DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: flushing port %d\n", __func__,
342 ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
344 /* Flush unicast entries on port */
345 val = AR8216_ATU_OP_FLUSH_UNICAST;
347 /* TODO: bit 4 indicates whether to flush dynamic (0) or static (1) */
350 val |= SM(port, AR8216_ATU_PORT_NUM);
352 ret = ar8xxx_atu_wait_ready(sc);
354 device_printf(sc->sc_dev, "%s: waitreg failed\n", __func__);
357 arswitch_writereg(sc->sc_dev,
359 val | AR8216_ATU_ACTIVE);
365 * XXX TODO: flush a single MAC address.
369 * Fetch a single entry from the ATU.
372 ar8xxx_atu_fetch_table(struct arswitch_softc *sc, etherswitch_atu_entry_t *e,
375 uint32_t ret0, ret1, ret2, val;
377 ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
379 switch (atu_fetch_op) {
381 /* Initialise things for the first fetch */
383 DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: initializing\n", __func__);
384 (void) ar8xxx_atu_wait_ready(sc);
386 arswitch_writereg(sc->sc_dev,
387 AR8216_REG_ATU, AR8216_ATU_OP_GET_NEXT);
388 arswitch_writereg(sc->sc_dev,
389 AR8216_REG_ATU_DATA, 0);
390 arswitch_writereg(sc->sc_dev,
391 AR8216_REG_ATU_CTRL2, 0);
395 DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: reading next\n", __func__);
397 * Attempt to read the next address entry; don't modify what
398 * is there in AT_ADDR{4,5} as its used for the next fetch
400 (void) ar8xxx_atu_wait_ready(sc);
402 /* Begin the next read event; not modifying anything */
403 val = arswitch_readreg(sc->sc_dev, AR8216_REG_ATU);
404 val |= AR8216_ATU_ACTIVE;
405 arswitch_writereg(sc->sc_dev, AR8216_REG_ATU, val);
407 /* Wait for it to complete */
408 (void) ar8xxx_atu_wait_ready(sc);
410 /* Fetch the ethernet address and ATU status */
411 ret0 = arswitch_readreg(sc->sc_dev, AR8216_REG_ATU);
412 ret1 = arswitch_readreg(sc->sc_dev, AR8216_REG_ATU_DATA);
413 ret2 = arswitch_readreg(sc->sc_dev, AR8216_REG_ATU_CTRL2);
415 /* If the status is zero, then we're done */
416 if (MS(ret2, AR8216_ATU_CTRL2_AT_STATUS) == 0)
420 e->es_macaddr[5] = MS(ret0, AR8216_ATU_ADDR5);
421 e->es_macaddr[4] = MS(ret0, AR8216_ATU_ADDR4);
422 e->es_macaddr[3] = MS(ret1, AR8216_ATU_ADDR3);
423 e->es_macaddr[2] = MS(ret1, AR8216_ATU_ADDR2);
424 e->es_macaddr[1] = MS(ret1, AR8216_ATU_ADDR1);
425 e->es_macaddr[0] = MS(ret1, AR8216_ATU_ADDR0);
427 /* Bitmask of ports this entry is for */
428 e->es_portmask = MS(ret2, AR8216_ATU_CTRL2_DESPORT);
430 /* TODO: other flags that are interesting */
432 DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: MAC %6D portmask 0x%08x\n",
434 e->es_macaddr, ":", e->es_portmask);
443 * Configure aging register defaults.
446 ar8xxx_atu_learn_default(struct arswitch_softc *sc)
451 DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: resetting learning\n", __func__);
454 * For now, configure the aging defaults:
456 * + ARP_EN - enable "acknowledgement" of ARP frames - they are
457 * forwarded to the CPU port
458 * + LEARN_CHANGE_EN - hash table violations when learning MAC addresses
459 * will force an entry to be expired/updated and a new one to be
461 * + AGE_EN - enable address table aging
462 * + AGE_TIME - set to 5 minutes
465 val |= AR8216_ATU_CTRL_ARP_EN;
466 val |= AR8216_ATU_CTRL_LEARN_CHANGE;
467 val |= AR8216_ATU_CTRL_AGE_EN;
468 val |= 0x2b; /* 5 minutes; bits 15:0 */
470 ret = arswitch_writereg(sc->sc_dev,
475 device_printf(sc->sc_dev, "%s: writereg failed\n", __func__);
481 * XXX TODO: add another routine to configure the leaky behaviour
482 * when unknown frames are received. These must be consistent
483 * between ethernet switches.
487 * Fetch the configured switch MAC address.
490 ar8xxx_hw_get_switch_macaddr(struct arswitch_softc *sc, struct ether_addr *ea)
497 ret0 = arswitch_readreg(sc->sc_dev, AR8X16_REG_SW_MAC_ADDR0);
498 ret1 = arswitch_readreg(sc->sc_dev, AR8X16_REG_SW_MAC_ADDR1);
500 s[5] = MS(ret0, AR8X16_REG_SW_MAC_ADDR0_BYTE5);
501 s[4] = MS(ret0, AR8X16_REG_SW_MAC_ADDR0_BYTE4);
502 s[3] = MS(ret1, AR8X16_REG_SW_MAC_ADDR1_BYTE3);
503 s[2] = MS(ret1, AR8X16_REG_SW_MAC_ADDR1_BYTE2);
504 s[1] = MS(ret1, AR8X16_REG_SW_MAC_ADDR1_BYTE1);
505 s[0] = MS(ret1, AR8X16_REG_SW_MAC_ADDR1_BYTE0);
511 * Set the switch mac address.
514 ar8xxx_hw_set_switch_macaddr(struct arswitch_softc *sc,
515 const struct ether_addr *ea)
522 * XXX TODO: this attach routine does NOT free all memory, resources
526 arswitch_attach(device_t dev)
528 struct arswitch_softc *sc = device_get_softc(dev);
529 struct sysctl_ctx_list *ctx;
530 struct sysctl_oid *tree;
534 /* sc->sc_switchtype is already decided in arswitch_probe() */
536 mtx_init(&sc->sc_mtx, "arswitch", NULL, MTX_DEF);
538 strlcpy(sc->info.es_name, device_get_desc(dev),
539 sizeof(sc->info.es_name));
542 ctx = device_get_sysctl_ctx(sc->sc_dev);
543 tree = device_get_sysctl_tree(sc->sc_dev);
544 SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
545 "debug", CTLFLAG_RW, &sc->sc_debug, 0,
546 "control debugging printfs");
548 /* Allocate a 128 entry ATU table; hopefully its big enough! */
549 /* XXX TODO: make this per chip */
550 sc->atu.entries = malloc(sizeof(etherswitch_atu_entry_t) * 128,
552 if (sc->atu.entries == NULL) {
553 device_printf(sc->sc_dev, "%s: failed to allocate ATU table\n",
560 /* Default HAL methods */
561 sc->hal.arswitch_port_init = ar8xxx_port_init;
562 sc->hal.arswitch_port_vlan_setup = ar8xxx_port_vlan_setup;
563 sc->hal.arswitch_port_vlan_get = ar8xxx_port_vlan_get;
564 sc->hal.arswitch_vlan_init_hw = ar8xxx_reset_vlans;
565 sc->hal.arswitch_hw_get_switch_macaddr = ar8xxx_hw_get_switch_macaddr;
566 sc->hal.arswitch_hw_set_switch_macaddr = ar8xxx_hw_set_switch_macaddr;
568 sc->hal.arswitch_vlan_getvgroup = ar8xxx_getvgroup;
569 sc->hal.arswitch_vlan_setvgroup = ar8xxx_setvgroup;
571 sc->hal.arswitch_vlan_get_pvid = ar8xxx_get_pvid;
572 sc->hal.arswitch_vlan_set_pvid = ar8xxx_set_pvid;
574 sc->hal.arswitch_get_dot1q_vlan = ar8xxx_get_dot1q_vlan;
575 sc->hal.arswitch_set_dot1q_vlan = ar8xxx_set_dot1q_vlan;
576 sc->hal.arswitch_flush_dot1q_vlan = ar8xxx_flush_dot1q_vlan;
577 sc->hal.arswitch_purge_dot1q_vlan = ar8xxx_purge_dot1q_vlan;
578 sc->hal.arswitch_get_port_vlan = ar8xxx_get_port_vlan;
579 sc->hal.arswitch_set_port_vlan = ar8xxx_set_port_vlan;
581 sc->hal.arswitch_atu_flush = ar8xxx_atu_flush;
582 sc->hal.arswitch_atu_flush_port = ar8xxx_atu_flush_port;
583 sc->hal.arswitch_atu_learn_default = ar8xxx_atu_learn_default;
584 sc->hal.arswitch_atu_fetch_table = ar8xxx_atu_fetch_table;
586 sc->hal.arswitch_phy_read = arswitch_readphy_internal;
587 sc->hal.arswitch_phy_write = arswitch_writephy_internal;
590 * Attach switch related functions
592 if (AR8X16_IS_SWITCH(sc, AR7240))
594 else if (AR8X16_IS_SWITCH(sc, AR9340))
596 else if (AR8X16_IS_SWITCH(sc, AR8216))
598 else if (AR8X16_IS_SWITCH(sc, AR8226))
600 else if (AR8X16_IS_SWITCH(sc, AR8316))
602 else if (AR8X16_IS_SWITCH(sc, AR8327))
605 DPRINTF(sc, ARSWITCH_DBG_ANY,
606 "%s: unknown switch (%d)?\n", __func__, sc->sc_switchtype);
610 /* Common defaults. */
611 sc->info.es_nports = 5; /* XXX technically 6, but 6th not used */
613 /* XXX Defaults for externally connected AR8316 */
620 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
621 "numphys", &sc->numphys);
622 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
623 "phy4cpu", &sc->phy4cpu);
624 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
625 "is_rgmii", &sc->is_rgmii);
626 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
627 "is_gmii", &sc->is_gmii);
628 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
629 "is_mii", &sc->is_mii);
631 if (sc->numphys > AR8X16_NUM_PHYS)
632 sc->numphys = AR8X16_NUM_PHYS;
634 /* Reset the switch. */
635 if (arswitch_reset(dev)) {
636 DPRINTF(sc, ARSWITCH_DBG_ANY,
637 "%s: arswitch_reset: failed\n", __func__);
641 err = sc->hal.arswitch_hw_setup(sc);
643 DPRINTF(sc, ARSWITCH_DBG_ANY,
644 "%s: hw_setup: err=%d\n", __func__, err);
648 err = sc->hal.arswitch_hw_global_setup(sc);
650 DPRINTF(sc, ARSWITCH_DBG_ANY,
651 "%s: hw_global_setup: err=%d\n", __func__, err);
656 * Configure the default address table learning parameters for this
659 err = sc->hal.arswitch_atu_learn_default(sc);
661 DPRINTF(sc, ARSWITCH_DBG_ANY,
662 "%s: atu_learn_default: err=%d\n", __func__, err);
666 /* Initialize the switch ports. */
667 for (port = 0; port <= sc->numphys; port++) {
668 sc->hal.arswitch_port_init(sc, port);
672 * Attach the PHYs and complete the bus enumeration.
674 err = arswitch_attach_phys(sc);
676 DPRINTF(sc, ARSWITCH_DBG_ANY,
677 "%s: attach_phys: err=%d\n", __func__, err);
681 /* Default to ingress filters off. */
682 err = arswitch_set_vlan_mode(sc, 0);
684 DPRINTF(sc, ARSWITCH_DBG_ANY,
685 "%s: set_vlan_mode: err=%d\n", __func__, err);
689 bus_generic_probe(dev);
690 bus_enumerate_hinted_children(dev);
691 err = bus_generic_attach(dev);
693 DPRINTF(sc, ARSWITCH_DBG_ANY,
694 "%s: bus_generic_attach: err=%d\n", __func__, err);
698 callout_init_mtx(&sc->callout_tick, &sc->sc_mtx, 0);
708 arswitch_detach(device_t dev)
710 struct arswitch_softc *sc = device_get_softc(dev);
713 callout_drain(&sc->callout_tick);
715 for (i=0; i < sc->numphys; i++) {
716 if (sc->miibus[i] != NULL)
717 device_delete_child(dev, sc->miibus[i]);
718 if (sc->ifp[i] != NULL)
720 free(sc->ifname[i], M_DEVBUF);
723 free(sc->atu.entries, M_DEVBUF);
725 bus_generic_detach(dev);
726 mtx_destroy(&sc->sc_mtx);
732 * Convert PHY number to port number. PHY0 is connected to port 1, PHY1 to
736 arswitch_portforphy(int phy)
741 static inline struct mii_data *
742 arswitch_miiforport(struct arswitch_softc *sc, int port)
746 if (phy < 0 || phy >= sc->numphys)
748 return (device_get_softc(sc->miibus[phy]));
751 static inline struct ifnet *
752 arswitch_ifpforport(struct arswitch_softc *sc, int port)
756 if (phy < 0 || phy >= sc->numphys)
758 return (sc->ifp[phy]);
762 * Convert port status to ifmedia.
765 arswitch_update_ifmedia(int portstatus, u_int *media_status, u_int *media_active)
767 *media_active = IFM_ETHER;
768 *media_status = IFM_AVALID;
770 if ((portstatus & AR8X16_PORT_STS_LINK_UP) != 0)
771 *media_status |= IFM_ACTIVE;
773 *media_active |= IFM_NONE;
776 switch (portstatus & AR8X16_PORT_STS_SPEED_MASK) {
777 case AR8X16_PORT_STS_SPEED_10:
778 *media_active |= IFM_10_T;
780 case AR8X16_PORT_STS_SPEED_100:
781 *media_active |= IFM_100_TX;
783 case AR8X16_PORT_STS_SPEED_1000:
784 *media_active |= IFM_1000_T;
787 if ((portstatus & AR8X16_PORT_STS_DUPLEX) == 0)
788 *media_active |= IFM_FDX;
790 *media_active |= IFM_HDX;
791 if ((portstatus & AR8X16_PORT_STS_TXFLOW) != 0)
792 *media_active |= IFM_ETH_TXPAUSE;
793 if ((portstatus & AR8X16_PORT_STS_RXFLOW) != 0)
794 *media_active |= IFM_ETH_RXPAUSE;
798 * Poll the status for all PHYs. We're using the switch port status because
799 * thats a lot quicker to read than talking to all the PHYs. Care must be
800 * taken that the resulting ifmedia_active is identical to what the PHY will
801 * compute, or gratuitous link status changes will occur whenever the PHYs
802 * update function is called.
805 arswitch_miipollstat(struct arswitch_softc *sc)
808 struct mii_data *mii;
809 struct mii_softc *miisc;
813 ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
815 for (i = 0; i < sc->numphys; i++) {
816 if (sc->miibus[i] == NULL)
818 mii = device_get_softc(sc->miibus[i]);
819 /* XXX This would be nice to have abstracted out to be per-chip */
820 /* AR8327/AR8337 has a different register base */
821 if (AR8X16_IS_SWITCH(sc, AR8327))
822 portstatus = arswitch_readreg(sc->sc_dev,
823 AR8327_REG_PORT_STATUS(arswitch_portforphy(i)));
825 portstatus = arswitch_readreg(sc->sc_dev,
826 AR8X16_REG_PORT_STS(arswitch_portforphy(i)));
828 DPRINTF(sc, ARSWITCH_DBG_POLL, "p[%d]=0x%08x (%b)\n",
832 "\20\3TXMAC\4RXMAC\5TXFLOW\6RXFLOW\7"
833 "DUPLEX\11LINK_UP\12LINK_AUTO\13LINK_PAUSE");
836 * If the current status is down, but we have a link
837 * status showing up, we need to do an ATU flush.
839 if ((mii->mii_media_status & IFM_ACTIVE) == 0 &&
840 (portstatus & AR8X16_PORT_STS_LINK_UP) != 0) {
841 device_printf(sc->sc_dev, "%s: port %d: port -> UP\n",
847 * and maybe if a port goes up->down?
849 if ((mii->mii_media_status & IFM_ACTIVE) != 0 &&
850 (portstatus & AR8X16_PORT_STS_LINK_UP) == 0) {
851 device_printf(sc->sc_dev, "%s: port %d: port -> DOWN\n",
856 arswitch_update_ifmedia(portstatus, &mii->mii_media_status,
857 &mii->mii_media_active);
858 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
859 if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) !=
862 mii_phy_update(miisc, MII_POLLSTAT);
866 /* If a port went from down->up, flush the ATU */
868 sc->hal.arswitch_atu_flush(sc);
872 arswitch_tick(void *arg)
874 struct arswitch_softc *sc = arg;
876 arswitch_miipollstat(sc);
877 callout_reset(&sc->callout_tick, hz, arswitch_tick, sc);
881 arswitch_lock(device_t dev)
883 struct arswitch_softc *sc = device_get_softc(dev);
885 ARSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
890 arswitch_unlock(device_t dev)
892 struct arswitch_softc *sc = device_get_softc(dev);
894 ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
898 static etherswitch_info_t *
899 arswitch_getinfo(device_t dev)
901 struct arswitch_softc *sc = device_get_softc(dev);
907 ar8xxx_port_vlan_get(struct arswitch_softc *sc, etherswitch_port_t *p)
913 /* Retrieve the PVID. */
914 sc->hal.arswitch_vlan_get_pvid(sc, p->es_port, &p->es_pvid);
917 reg = arswitch_readreg(sc->sc_dev, AR8X16_REG_PORT_CTRL(p->es_port));
918 if (reg & AR8X16_PORT_CTRL_DOUBLE_TAG)
919 p->es_flags |= ETHERSWITCH_PORT_DOUBLE_TAG;
920 reg >>= AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT;
921 if ((reg & 0x3) == AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_ADD)
922 p->es_flags |= ETHERSWITCH_PORT_ADDTAG;
923 if ((reg & 0x3) == AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_STRIP)
924 p->es_flags |= ETHERSWITCH_PORT_STRIPTAG;
931 arswitch_is_cpuport(struct arswitch_softc *sc, int port)
934 return ((port == AR8X16_PORT_CPU) ||
935 ((AR8X16_IS_SWITCH(sc, AR8327) &&
936 port == AR8327_PORT_GMAC6)));
940 arswitch_getport(device_t dev, etherswitch_port_t *p)
942 struct arswitch_softc *sc;
943 struct mii_data *mii;
944 struct ifmediareq *ifmr;
947 sc = device_get_softc(dev);
948 /* XXX +1 is for AR8327; should make this configurable! */
949 if (p->es_port < 0 || p->es_port > sc->info.es_nports)
952 err = sc->hal.arswitch_port_vlan_get(sc, p);
956 mii = arswitch_miiforport(sc, p->es_port);
957 if (arswitch_is_cpuport(sc, p->es_port)) {
958 /* fill in fixed values for CPU port */
959 /* XXX is this valid in all cases? */
960 p->es_flags |= ETHERSWITCH_PORT_CPU;
963 ifmr->ifm_current = ifmr->ifm_active =
964 IFM_ETHER | IFM_1000_T | IFM_FDX;
966 ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID;
967 } else if (mii != NULL) {
968 err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr,
969 &mii->mii_media, SIOCGIFMEDIA);
976 if (!arswitch_is_cpuport(sc, p->es_port) &&
977 AR8X16_IS_SWITCH(sc, AR8327)) {
981 for (led = 0; led < p->es_nleds; led++)
986 /* Find the right style enum for our pattern */
987 val = arswitch_readreg(dev,
988 ar8327_led_mapping[p->es_port-1][led].reg);
989 val = (val>>ar8327_led_mapping[p->es_port-1][led].shift)&0x03;
991 for (style = 0; style < ETHERSWITCH_PORT_LED_MAX; style++)
993 if (led_pattern_table[style] == val) break;
997 if (style == ETHERSWITCH_PORT_LED_MAX)
998 style = ETHERSWITCH_PORT_LED_DEFAULT;
1000 p->es_led[led] = style;
1011 ar8xxx_port_vlan_setup(struct arswitch_softc *sc, etherswitch_port_t *p)
1019 if (p->es_pvid != 0)
1020 sc->hal.arswitch_vlan_set_pvid(sc, p->es_port, p->es_pvid);
1022 /* Mutually exclusive. */
1023 if (p->es_flags & ETHERSWITCH_PORT_ADDTAG &&
1024 p->es_flags & ETHERSWITCH_PORT_STRIPTAG) {
1025 ARSWITCH_UNLOCK(sc);
1030 if (p->es_flags & ETHERSWITCH_PORT_DOUBLE_TAG)
1031 reg |= AR8X16_PORT_CTRL_DOUBLE_TAG;
1032 if (p->es_flags & ETHERSWITCH_PORT_ADDTAG)
1033 reg |= AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_ADD <<
1034 AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT;
1035 if (p->es_flags & ETHERSWITCH_PORT_STRIPTAG)
1036 reg |= AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_STRIP <<
1037 AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT;
1039 err = arswitch_modifyreg(sc->sc_dev,
1040 AR8X16_REG_PORT_CTRL(p->es_port),
1041 0x3 << AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT |
1042 AR8X16_PORT_CTRL_DOUBLE_TAG, reg);
1044 ARSWITCH_UNLOCK(sc);
1049 arswitch_setport(device_t dev, etherswitch_port_t *p)
1052 struct arswitch_softc *sc;
1053 struct ifmedia *ifm;
1054 struct mii_data *mii;
1057 sc = device_get_softc(dev);
1058 if (p->es_port < 0 || p->es_port > sc->info.es_nports)
1062 if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
1063 err = sc->hal.arswitch_port_vlan_setup(sc, p);
1068 /* Do not allow media or led changes on CPU port. */
1069 if (arswitch_is_cpuport(sc, p->es_port))
1072 if (AR8X16_IS_SWITCH(sc, AR8327))
1074 for (i = 0; i < 3; i++)
1077 err = arswitch_setled(sc, p->es_port-1, i, p->es_led[i]);
1083 mii = arswitch_miiforport(sc, p->es_port);
1087 ifp = arswitch_ifpforport(sc, p->es_port);
1089 ifm = &mii->mii_media;
1090 return (ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA));
1094 arswitch_setled(struct arswitch_softc *sc, int phy, int led, int style)
1099 if (phy < 0 || phy > sc->numphys)
1102 if (style < 0 || style > ETHERSWITCH_PORT_LED_MAX)
1107 shift = ar8327_led_mapping[phy][led].shift;
1108 err = (arswitch_modifyreg(sc->sc_dev,
1109 ar8327_led_mapping[phy][led].reg,
1110 0x03 << shift, led_pattern_table[style] << shift));
1111 ARSWITCH_UNLOCK(sc);
1117 arswitch_statchg(device_t dev)
1119 struct arswitch_softc *sc = device_get_softc(dev);
1121 DPRINTF(sc, ARSWITCH_DBG_POLL, "%s\n", __func__);
1125 arswitch_ifmedia_upd(struct ifnet *ifp)
1127 struct arswitch_softc *sc = ifp->if_softc;
1128 struct mii_data *mii = arswitch_miiforport(sc, ifp->if_dunit);
1137 arswitch_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
1139 struct arswitch_softc *sc = ifp->if_softc;
1140 struct mii_data *mii = arswitch_miiforport(sc, ifp->if_dunit);
1142 DPRINTF(sc, ARSWITCH_DBG_POLL, "%s\n", __func__);
1147 ifmr->ifm_active = mii->mii_media_active;
1148 ifmr->ifm_status = mii->mii_media_status;
1152 arswitch_getconf(device_t dev, etherswitch_conf_t *conf)
1154 struct arswitch_softc *sc;
1157 sc = device_get_softc(dev);
1159 /* Return the VLAN mode. */
1160 conf->cmd = ETHERSWITCH_CONF_VLAN_MODE;
1161 conf->vlan_mode = sc->vlan_mode;
1163 /* Return the switch ethernet address. */
1164 ret = sc->hal.arswitch_hw_get_switch_macaddr(sc,
1165 &conf->switch_macaddr);
1167 conf->cmd |= ETHERSWITCH_CONF_SWITCH_MACADDR;
1174 arswitch_setconf(device_t dev, etherswitch_conf_t *conf)
1176 struct arswitch_softc *sc;
1179 sc = device_get_softc(dev);
1181 /* Set the VLAN mode. */
1182 if (conf->cmd & ETHERSWITCH_CONF_VLAN_MODE) {
1183 err = arswitch_set_vlan_mode(sc, conf->vlan_mode);
1188 /* TODO: Set the switch ethernet address. */
1194 arswitch_atu_flush_all(device_t dev)
1196 struct arswitch_softc *sc;
1199 sc = device_get_softc(dev);
1201 err = sc->hal.arswitch_atu_flush(sc);
1202 /* Invalidate cached ATU */
1204 ARSWITCH_UNLOCK(sc);
1209 arswitch_atu_flush_port(device_t dev, int port)
1211 struct arswitch_softc *sc;
1214 sc = device_get_softc(dev);
1216 err = sc->hal.arswitch_atu_flush_port(sc, port);
1217 /* Invalidate cached ATU */
1219 ARSWITCH_UNLOCK(sc);
1224 arswitch_atu_fetch_table(device_t dev, etherswitch_atu_table_t *table)
1226 struct arswitch_softc *sc;
1229 sc = device_get_softc(dev);
1234 err = sc->hal.arswitch_atu_fetch_table(sc, NULL, 0);
1236 /* fetch - ideally yes we'd fetch into a separate table then switch */
1237 while (err == 0 && nitems < sc->atu.size) {
1238 err = sc->hal.arswitch_atu_fetch_table(sc,
1239 &sc->atu.entries[nitems], 1);
1241 sc->atu.entries[nitems].id = nitems;
1245 sc->atu.count = nitems;
1246 ARSWITCH_UNLOCK(sc);
1248 table->es_nitems = nitems;
1254 arswitch_atu_fetch_table_entry(device_t dev, etherswitch_atu_entry_t *e)
1256 struct arswitch_softc *sc;
1259 sc = device_get_softc(dev);
1263 if (id > sc->atu.count) {
1264 ARSWITCH_UNLOCK(sc);
1268 memcpy(e, &sc->atu.entries[id], sizeof(*e));
1269 ARSWITCH_UNLOCK(sc);
1274 arswitch_getvgroup(device_t dev, etherswitch_vlangroup_t *e)
1276 struct arswitch_softc *sc = device_get_softc(dev);
1278 return (sc->hal.arswitch_vlan_getvgroup(sc, e));
1282 arswitch_setvgroup(device_t dev, etherswitch_vlangroup_t *e)
1284 struct arswitch_softc *sc = device_get_softc(dev);
1286 return (sc->hal.arswitch_vlan_setvgroup(sc, e));
1290 arswitch_readphy(device_t dev, int phy, int reg)
1292 struct arswitch_softc *sc = device_get_softc(dev);
1294 return (sc->hal.arswitch_phy_read(dev, phy, reg));
1298 arswitch_writephy(device_t dev, int phy, int reg, int val)
1300 struct arswitch_softc *sc = device_get_softc(dev);
1302 return (sc->hal.arswitch_phy_write(dev, phy, reg, val));
1305 static device_method_t arswitch_methods[] = {
1306 /* Device interface */
1307 DEVMETHOD(device_probe, arswitch_probe),
1308 DEVMETHOD(device_attach, arswitch_attach),
1309 DEVMETHOD(device_detach, arswitch_detach),
1312 DEVMETHOD(bus_add_child, device_add_child_ordered),
1315 DEVMETHOD(miibus_readreg, arswitch_readphy),
1316 DEVMETHOD(miibus_writereg, arswitch_writephy),
1317 DEVMETHOD(miibus_statchg, arswitch_statchg),
1319 /* MDIO interface */
1320 DEVMETHOD(mdio_readreg, arswitch_readphy),
1321 DEVMETHOD(mdio_writereg, arswitch_writephy),
1323 /* etherswitch interface */
1324 DEVMETHOD(etherswitch_lock, arswitch_lock),
1325 DEVMETHOD(etherswitch_unlock, arswitch_unlock),
1326 DEVMETHOD(etherswitch_getinfo, arswitch_getinfo),
1327 DEVMETHOD(etherswitch_readreg, arswitch_readreg),
1328 DEVMETHOD(etherswitch_writereg, arswitch_writereg),
1329 DEVMETHOD(etherswitch_readphyreg, arswitch_readphy),
1330 DEVMETHOD(etherswitch_writephyreg, arswitch_writephy),
1331 DEVMETHOD(etherswitch_getport, arswitch_getport),
1332 DEVMETHOD(etherswitch_setport, arswitch_setport),
1333 DEVMETHOD(etherswitch_getvgroup, arswitch_getvgroup),
1334 DEVMETHOD(etherswitch_setvgroup, arswitch_setvgroup),
1335 DEVMETHOD(etherswitch_getconf, arswitch_getconf),
1336 DEVMETHOD(etherswitch_setconf, arswitch_setconf),
1337 DEVMETHOD(etherswitch_flush_all, arswitch_atu_flush_all),
1338 DEVMETHOD(etherswitch_flush_port, arswitch_atu_flush_port),
1339 DEVMETHOD(etherswitch_fetch_table, arswitch_atu_fetch_table),
1340 DEVMETHOD(etherswitch_fetch_table_entry, arswitch_atu_fetch_table_entry),
1345 DEFINE_CLASS_0(arswitch, arswitch_driver, arswitch_methods,
1346 sizeof(struct arswitch_softc));
1347 static devclass_t arswitch_devclass;
1349 DRIVER_MODULE(arswitch, mdio, arswitch_driver, arswitch_devclass, 0, 0);
1350 DRIVER_MODULE(miibus, arswitch, miibus_driver, miibus_devclass, 0, 0);
1351 DRIVER_MODULE(mdio, arswitch, mdio_driver, mdio_devclass, 0, 0);
1352 DRIVER_MODULE(etherswitch, arswitch, etherswitch_driver, etherswitch_devclass, 0, 0);
1353 MODULE_VERSION(arswitch, 1);
1354 MODULE_DEPEND(arswitch, miibus, 1, 1, 1); /* XXX which versions? */
1355 MODULE_DEPEND(arswitch, etherswitch, 1, 1, 1); /* XXX which versions? */