/* * Initialise other global values, for the AR8316. */ static int ar8316_hw_global_setup(struct arswitch_softc *sc) { arswitch_writereg(sc->sc_dev, 0x38, AR8X16_MAGIC); /* Enable CPU port and disable mirror port. */ arswitch_writereg(sc->sc_dev, AR8X16_REG_CPU_PORT, AR8X16_CPU_PORT_EN | AR8X16_CPU_MIRROR_DIS); /* Setup TAG priority mapping. */ arswitch_writereg(sc->sc_dev, AR8X16_REG_TAG_PRIO, 0xfa50); /* Enable ARP frame acknowledge. */ arswitch_modifyreg(sc->sc_dev, AR8X16_REG_AT_CTRL, 0, AR8X16_AT_CTRL_ARP_EN); /* * Flood address table misses to all ports, and enable forwarding of * broadcasts to the cpu port. */ arswitch_writereg(sc->sc_dev, AR8X16_REG_FLOOD_MASK, AR8X16_FLOOD_MASK_BCAST_TO_CPU | 0x003f003f); /* Enable jumbo frames. */ arswitch_modifyreg(sc->sc_dev, AR8X16_REG_GLOBAL_CTRL, AR8316_GLOBAL_CTRL_MTU_MASK, 9018 + 8 + 2); /* Setup service TAG. */ arswitch_modifyreg(sc->sc_dev, AR8X16_REG_SERVICE_TAG, AR8X16_SERVICE_TAG_MASK, 0); return (0); }
/* * Initialise other global values for the AR7240. */ static int ar7240_hw_global_setup(struct arswitch_softc *sc) { /* Enable CPU port; disable mirror port */ arswitch_writereg(sc->sc_dev, AR8X16_REG_CPU_PORT, AR8X16_CPU_PORT_EN | AR8X16_CPU_MIRROR_DIS); /* Setup TAG priority mapping */ arswitch_writereg(sc->sc_dev, AR8X16_REG_TAG_PRIO, 0xfa50); /* Enable broadcast frames transmitted to the CPU */ arswitch_writereg(sc->sc_dev, AR8X16_REG_FLOOD_MASK, AR8X16_FLOOD_MASK_BCAST_TO_CPU | 0x003f003f); /* Setup MTU */ arswitch_modifyreg(sc->sc_dev, AR8X16_REG_GLOBAL_CTRL, AR7240_GLOBAL_CTRL_MTU_MASK, SM(1536, AR7240_GLOBAL_CTRL_MTU_MASK)); /* Service Tag */ arswitch_modifyreg(sc->sc_dev, AR8X16_REG_SERVICE_TAG, AR8X16_SERVICE_TAG_MASK, 0); return (0); }
/* * Initialise other global values, for the AR8327. */ static int ar8327_hw_global_setup(struct arswitch_softc *sc) { uint32_t t; /* enable CPU port and disable mirror port */ t = AR8327_FWD_CTRL0_CPU_PORT_EN | AR8327_FWD_CTRL0_MIRROR_PORT; arswitch_writereg(sc->sc_dev, AR8327_REG_FWD_CTRL0, t); /* forward multicast and broadcast frames to CPU */ t = (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_UC_FLOOD_S) | (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_MC_FLOOD_S) | (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_BC_FLOOD_S); arswitch_writereg(sc->sc_dev, AR8327_REG_FWD_CTRL1, t); /* enable jumbo frames */ /* XXX need to macro-shift the value! */ arswitch_modifyreg(sc->sc_dev, AR8327_REG_MAX_FRAME_SIZE, AR8327_MAX_FRAME_SIZE_MTU, 9018 + 8 + 2); /* Enable MIB counters */ arswitch_modifyreg(sc->sc_dev, AR8327_REG_MODULE_EN, AR8327_MODULE_EN_MIB, AR8327_MODULE_EN_MIB); return (0); }
static void ar8327_reset_vlans(struct arswitch_softc *sc) { int i; uint32_t mode, t; /* * Disable mirroring. */ arswitch_modifyreg(sc->sc_dev, AR8327_REG_FWD_CTRL0, AR8327_FWD_CTRL0_MIRROR_PORT, (0xF << AR8327_FWD_CTRL0_MIRROR_PORT_S)); /* * For now, let's default to one portgroup, just so traffic * flows. All ports can see other ports. */ for (i = 0; i < AR8327_NUM_PORTS; i++) { /* set pvid = i */ t = i << AR8327_PORT_VLAN0_DEF_SVID_S; t |= i << AR8327_PORT_VLAN0_DEF_CVID_S; arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN0(i), t); /* set egress == out_keep */ mode = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH; t = AR8327_PORT_VLAN1_PORT_VLAN_PROP; t |= mode << AR8327_PORT_VLAN1_OUT_MODE_S; arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN1(i), t); /* Set ingress = out_keep; members = 0x3f for all ports */ t = (0x3f & ~(1 << i)); /* all ports besides us */ t |= AR8327_PORT_LOOKUP_LEARN; /* in_port_only, forward */ t |= AR8X16_PORT_VLAN_MODE_PORT_ONLY << AR8327_PORT_LOOKUP_IN_MODE_S; t |= AR8X16_PORT_CTRL_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S; arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(i), t); /* * Disable port mirroring entirely. */ arswitch_modifyreg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(i), AR8327_PORT_LOOKUP_ING_MIRROR_EN, 0); arswitch_modifyreg(sc->sc_dev, AR8327_REG_PORT_HOL_CTRL1(i), AR8327_PORT_HOL_CTRL1_EG_MIRROR_EN, 0); } }
static void ar8327_port_disable_mirror(struct arswitch_softc *sc, int port) { arswitch_modifyreg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(port), AR8327_PORT_LOOKUP_ING_MIRROR_EN, 0); arswitch_modifyreg(sc->sc_dev, AR8327_REG_PORT_HOL_CTRL1(port), AR8327_PORT_HOL_CTRL1_EG_MIRROR_EN, 0); }
/* * Initialise other global values, for the AR8327. */ static int ar8327_hw_global_setup(struct arswitch_softc *sc) { uint32_t t; /* enable CPU port and disable mirror port */ t = AR8327_FWD_CTRL0_CPU_PORT_EN | AR8327_FWD_CTRL0_MIRROR_PORT; arswitch_writereg(sc->sc_dev, AR8327_REG_FWD_CTRL0, t); /* forward multicast and broadcast frames to CPU */ t = (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_UC_FLOOD_S) | (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_MC_FLOOD_S) | (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_BC_FLOOD_S); arswitch_writereg(sc->sc_dev, AR8327_REG_FWD_CTRL1, t); /* enable jumbo frames */ /* XXX need to macro-shift the value! */ arswitch_modifyreg(sc->sc_dev, AR8327_REG_MAX_FRAME_SIZE, AR8327_MAX_FRAME_SIZE_MTU, 9018 + 8 + 2); /* Enable MIB counters */ arswitch_modifyreg(sc->sc_dev, AR8327_REG_MODULE_EN, AR8327_MODULE_EN_MIB, AR8327_MODULE_EN_MIB); /* Disable EEE on all ports due to stability issues */ t = arswitch_readreg(sc->sc_dev, AR8327_REG_EEE_CTRL); t |= AR8327_EEE_CTRL_DISABLE_PHY(0) | AR8327_EEE_CTRL_DISABLE_PHY(1) | AR8327_EEE_CTRL_DISABLE_PHY(2) | AR8327_EEE_CTRL_DISABLE_PHY(3) | AR8327_EEE_CTRL_DISABLE_PHY(4); arswitch_writereg(sc->sc_dev, AR8327_REG_EEE_CTRL, t); /* Set the right number of ports */ /* GMAC0 (CPU), GMAC1..5 (PHYs), GMAC6 (CPU) */ sc->info.es_nports = 7; return (0); }
static int ar8327_vlan_set_port(struct arswitch_softc *sc, uint32_t ports, int vid) { int err, port; ARSWITCH_LOCK_ASSERT(sc, MA_OWNED); /* For port based vlans the vlanid is the same as the port index. */ port = vid & ETHERSWITCH_VID_MASK; err = arswitch_modifyreg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(port), 0x7f, /* vlan membership mask */ (ports & 0x7f)); if (err) return (err); return (0); }
/* * Initialise other global values, for the AR8316. */ static int ar8316_hw_global_setup(struct arswitch_softc *sc) { arswitch_writereg(sc->sc_dev, 0x38, 0xc000050e); /* * Flood address table misses to all ports, and enable forwarding of * broadcasts to the cpu port. */ arswitch_writereg(sc->sc_dev, AR8X16_REG_FLOOD_MASK, AR8X16_FLOOD_MASK_BCAST_TO_CPU | 0x003f003f); arswitch_modifyreg(sc->sc_dev, AR8X16_REG_GLOBAL_CTRL, AR8316_GLOBAL_CTRL_MTU_MASK, 9018 + 8 + 2); return (0); }
static void ar8327_reset_vlans(struct arswitch_softc *sc) { int i; uint32_t t; int ports; ARSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED); ARSWITCH_LOCK(sc); /* Clear the existing VLAN configuration */ memset(sc->vid, 0, sizeof(sc->vid)); /* * Disable mirroring. */ arswitch_modifyreg(sc->sc_dev, AR8327_REG_FWD_CTRL0, AR8327_FWD_CTRL0_MIRROR_PORT, (0xF << AR8327_FWD_CTRL0_MIRROR_PORT_S)); /* * XXX TODO: disable any Q-in-Q port configuration, * tagging, egress filters, etc. */ /* * For now, let's default to one portgroup, just so traffic * flows. All ports can see other ports. There are two CPU GMACs * (GMAC0, GMAC6), GMAC1..GMAC5 are external PHYs. * * (ETHERSWITCH_VLAN_PORT) */ ports = 0x7f; /* * XXX TODO: set things up correctly for vlans! */ for (i = 0; i < AR8327_NUM_PORTS; i++) { int egress, ingress; if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) { sc->vid[i] = i | ETHERSWITCH_VID_VALID; /* set egress == out_keep */ ingress = AR8X16_PORT_VLAN_MODE_PORT_ONLY; /* in_port_only, forward */ egress = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH; } else if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) { ingress = AR8X16_PORT_VLAN_MODE_SECURE; egress = AR8327_PORT_VLAN1_OUT_MODE_UNMOD; } else { /* set egress == out_keep */ ingress = AR8X16_PORT_VLAN_MODE_PORT_ONLY; /* in_port_only, forward */ egress = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH; } /* set pvid = 1; there's only one vlangroup to start with */ t = 1 << AR8327_PORT_VLAN0_DEF_SVID_S; t |= 1 << AR8327_PORT_VLAN0_DEF_CVID_S; arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN0(i), t); t = AR8327_PORT_VLAN1_PORT_VLAN_PROP; t |= egress << AR8327_PORT_VLAN1_OUT_MODE_S; arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN1(i), t); /* Ports can see other ports */ /* XXX not entirely true for dot1q? */ t = (ports & ~(1 << i)); /* all ports besides us */ t |= AR8327_PORT_LOOKUP_LEARN; t |= ingress << AR8327_PORT_LOOKUP_IN_MODE_S; t |= AR8X16_PORT_CTRL_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S; arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(i), t); } /* * Disable port mirroring entirely. */ for (i = 0; i < AR8327_NUM_PORTS; i++) { ar8327_port_disable_mirror(sc, i); } /* * If dot1q - set pvid; dot1q, etc. */ if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) { sc->vid[0] = 1; for (i = 0; i < AR8327_NUM_PORTS; i++) { /* Each port - pvid 1 */ sc->hal.arswitch_vlan_set_pvid(sc, i, sc->vid[0]); } /* Initialise vlan1 - all ports, untagged */ sc->hal.arswitch_set_dot1q_vlan(sc, ports, ports, sc->vid[0]); sc->vid[0] |= ETHERSWITCH_VID_VALID; } ARSWITCH_UNLOCK(sc); }