summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2013-05-08 20:58:41 +0000
committeradrian <adrian@FreeBSD.org>2013-05-08 20:58:41 +0000
commit51658e393de4c8043893743436fb42d312d44952 (patch)
treead86c0d0b1bd4a53c4f82bd2f68a69bfc45ee226
parentf4b590dbf115ff7838bc26c77587749c1209e80d (diff)
downloadFreeBSD-src-51658e393de4c8043893743436fb42d312d44952.zip
FreeBSD-src-51658e393de4c8043893743436fb42d312d44952.tar.gz
Bring in a basic ethernet switch driver for the IP17x series of
switches. These are notably found on some AR71xx based Mikrotik boards. Submitted by: Luiz Otavio O Souza <loos.br@gmail.com> Reviewed by: ray
-rw-r--r--sys/conf/files5
-rw-r--r--sys/dev/etherswitch/ip17x/ip175c.c249
-rw-r--r--sys/dev/etherswitch/ip17x/ip175c.h43
-rw-r--r--sys/dev/etherswitch/ip17x/ip175d.c219
-rw-r--r--sys/dev/etherswitch/ip17x/ip175d.h43
-rw-r--r--sys/dev/etherswitch/ip17x/ip17x.c614
-rw-r--r--sys/dev/etherswitch/ip17x/ip17x_phy.c102
-rw-r--r--sys/dev/etherswitch/ip17x/ip17x_phy.h38
-rw-r--r--sys/dev/etherswitch/ip17x/ip17x_reg.h44
-rw-r--r--sys/dev/etherswitch/ip17x/ip17x_var.h95
-rw-r--r--sys/dev/etherswitch/ip17x/ip17x_vlans.c167
-rw-r--r--sys/dev/etherswitch/ip17x/ip17x_vlans.h36
12 files changed, 1655 insertions, 0 deletions
diff --git a/sys/conf/files b/sys/conf/files
index c57d994..5df1236 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1331,6 +1331,11 @@ dev/etherswitch/arswitch/arswitch_8316.c optional arswitch
dev/etherswitch/arswitch/arswitch_7240.c optional arswitch
dev/etherswitch/etherswitch.c optional etherswitch
dev/etherswitch/etherswitch_if.m optional etherswitch
+dev/etherswitch/ip17x/ip17x.c optional ip17x
+dev/etherswitch/ip17x/ip175c.c optional ip17x
+dev/etherswitch/ip17x/ip175d.c optional ip17x
+dev/etherswitch/ip17x/ip17x_phy.c optional ip17x
+dev/etherswitch/ip17x/ip17x_vlans.c optional ip17x
dev/etherswitch/mdio_if.m optional miiproxy
dev/etherswitch/mdio.c optional miiproxy
dev/etherswitch/miiproxy.c optional miiproxy
diff --git a/sys/dev/etherswitch/ip17x/ip175c.c b/sys/dev/etherswitch/ip17x/ip175c.c
new file mode 100644
index 0000000..b106e29
--- /dev/null
+++ b/sys/dev/etherswitch/ip17x/ip175c.c
@@ -0,0 +1,249 @@
+/*-
+ * Copyright (c) 2013 Luiz Otavio O Souza.
+ * Copyright (c) 2011-2012 Stefan Bethke.
+ * Copyright (c) 2012 Adrian Chadd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+
+#include <dev/mii/mii.h>
+
+#include <dev/etherswitch/etherswitch.h>
+#include <dev/etherswitch/ip17x/ip17x_phy.h>
+#include <dev/etherswitch/ip17x/ip17x_reg.h>
+#include <dev/etherswitch/ip17x/ip17x_var.h>
+#include <dev/etherswitch/ip17x/ip17x_vlans.h>
+#include <dev/etherswitch/ip17x/ip175c.h>
+
+/*
+ * IP175C specific functions.
+ */
+
+/*
+ * Reset the switch.
+ */
+static int
+ip175c_reset(struct ip17x_softc *sc)
+{
+ uint32_t data;
+
+ /* Reset all the switch settings. */
+ if (ip17x_writephy(sc->sc_dev, IP175C_RESET_PHY, IP175C_RESET_REG,
+ 0x175c))
+ return (-1);
+ DELAY(2);
+
+ /* Force IP175C mode. */
+ data = ip17x_readphy(sc->sc_dev, IP175C_MODE_PHY, IP175C_MODE_REG);
+ if (data == 0x175a) {
+ if (ip17x_writephy(sc->sc_dev, IP175C_MODE_PHY, IP175C_MODE_REG,
+ 0x175c))
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+ip175c_port_vlan_setup(struct ip17x_softc *sc)
+{
+ struct ip17x_vlan *v;
+ uint32_t ports[IP175X_NUM_PORTS], reg[IP175X_NUM_PORTS/2];
+ int i, err, phy;
+
+ KASSERT(sc->cpuport == 5, ("cpuport != 5 not supported for IP175C"));
+ KASSERT(sc->numports == 6, ("numports != 6 not supported for IP175C"));
+
+ /* Build the port access masks. */
+ memset(ports, 0, sizeof(ports));
+ for (i = 0; i < sc->info.es_nports; i++) {
+ phy = sc->portphy[i];
+ v = &sc->vlan[i];
+ ports[phy] = v->ports;
+ }
+
+ /* Move the cpuport bit to its correct place. */
+ for (i = 0; i < sc->numports; i++) {
+ if (ports[i] & (1 << sc->cpuport)) {
+ ports[i] |= (1 << 7);
+ ports[i] &= ~(1 << sc->cpuport);
+ }
+ }
+
+ /* And now build the switch register data. */
+ memset(reg, 0, sizeof(reg));
+ for (i = 0; i < (sc->numports / 2); i++)
+ reg[i] = ports[i * 2] << 8 | ports[i * 2 + 1];
+
+ /* Update the switch resgisters. */
+ err = ip17x_writephy(sc->sc_dev, 29, 19, reg[0]);
+ if (err == 0)
+ err = ip17x_writephy(sc->sc_dev, 29, 20, reg[1]);
+ if (err == 0)
+ err = ip17x_updatephy(sc->sc_dev, 29, 21, 0xff00, reg[2]);
+ if (err == 0)
+ err = ip17x_updatephy(sc->sc_dev, 30, 18, 0x00ff, reg[2]);
+ return (err);
+}
+
+static int
+ip175c_dot1q_vlan_setup(struct ip17x_softc *sc)
+{
+ struct ip17x_vlan *v;
+ uint32_t data;
+ uint32_t vlans[IP17X_MAX_VLANS];
+ int i, j;
+
+ KASSERT(sc->cpuport == 5, ("cpuport != 5 not supported for IP175C"));
+ KASSERT(sc->numports == 6, ("numports != 6 not supported for IP175C"));
+
+ /* Add and strip VLAN tags. */
+ data = (sc->addtag & ~(1 << IP175X_CPU_PORT)) << 11;
+ data |= (sc->striptag & ~(1 << IP175X_CPU_PORT)) << 6;
+ if (sc->addtag & (1 << IP175X_CPU_PORT))
+ data |= (1 << 1);
+ if (sc->striptag & (1 << IP175X_CPU_PORT))
+ data |= (1 << 0);
+ if (ip17x_writephy(sc->sc_dev, 29, 23, data))
+ return (-1);
+
+ /* Set the VID_IDX_SEL to 0. */
+ if (ip17x_updatephy(sc->sc_dev, 30, 9, 0x70, 0))
+ return (-1);
+
+ /* Calculate the port masks. */
+ memset(vlans, 0, sizeof(vlans));
+ for (i = 0; i < IP17X_MAX_VLANS; i++) {
+ v = &sc->vlan[i];
+ if (v->vlanid == 0)
+ continue;
+ vlans[v->vlanid] = v->ports;
+ }
+
+ for (j = 0, i = 1; i <= IP17X_MAX_VLANS / 2; i++) {
+ data = vlans[j++] & 0x3f;
+ data |= (vlans[j++] & 0x3f) << 8;
+ if (ip17x_writephy(sc->sc_dev, 30, i, data))
+ return (-1);
+ }
+
+ /* Port default VLAN ID. */
+ for (i = 0; i < sc->numports; i++) {
+ if (i == IP175X_CPU_PORT) {
+ if (ip17x_writephy(sc->sc_dev, 29, 30, sc->pvid[i]))
+ return (-1);
+ } else {
+ if (ip17x_writephy(sc->sc_dev, 29, 24 + i, sc->pvid[i]))
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * Set the Switch configuration.
+ */
+static int
+ip175c_hw_setup(struct ip17x_softc *sc)
+{
+
+ switch (sc->vlan_mode) {
+ case ETHERSWITCH_VLAN_PORT:
+ return (ip175c_port_vlan_setup(sc));
+ break;
+ case ETHERSWITCH_VLAN_DOT1Q:
+ return (ip175c_dot1q_vlan_setup(sc));
+ break;
+ }
+ return (-1);
+}
+
+/*
+ * Set the switch VLAN mode.
+ */
+static int
+ip175c_set_vlan_mode(struct ip17x_softc *sc, uint32_t mode)
+{
+
+ switch (mode) {
+ case ETHERSWITCH_VLAN_DOT1Q:
+ /* Enable VLAN tag processing. */
+ ip17x_updatephy(sc->sc_dev, 30, 9, 0x80, 0x80);
+ sc->vlan_mode = mode;
+ break;
+ case ETHERSWITCH_VLAN_PORT:
+ default:
+ /* Disable VLAN tag processing. */
+ ip17x_updatephy(sc->sc_dev, 30, 9, 0x80, 0);
+ sc->vlan_mode = ETHERSWITCH_VLAN_PORT;
+ break;
+ };
+
+ /* Reset vlans. */
+ ip17x_reset_vlans(sc, sc->vlan_mode);
+
+ /* Update switch configuration. */
+ ip175c_hw_setup(sc);
+
+ return (0);
+}
+
+/*
+ * Get the switch VLAN mode.
+ */
+static int
+ip175c_get_vlan_mode(struct ip17x_softc *sc)
+{
+
+ return (sc->vlan_mode);
+}
+
+void
+ip175c_attach(struct ip17x_softc *sc)
+{
+
+ sc->hal.ip17x_reset = ip175c_reset;
+ sc->hal.ip17x_hw_setup = ip175c_hw_setup;
+ sc->hal.ip17x_get_vlan_mode = ip175c_get_vlan_mode;
+ sc->hal.ip17x_set_vlan_mode = ip175c_set_vlan_mode;
+
+ /* Defaults for IP175C. */
+ sc->cpuport = IP175X_CPU_PORT;
+ sc->numports = IP175X_NUM_PORTS;
+ sc->info.es_vlan_caps = ETHERSWITCH_VLAN_PORT | ETHERSWITCH_VLAN_DOT1Q;
+
+ device_printf(sc->sc_dev, "type: IP175C\n");
+}
diff --git a/sys/dev/etherswitch/ip17x/ip175c.h b/sys/dev/etherswitch/ip17x/ip175c.h
new file mode 100644
index 0000000..8abb4b6
--- /dev/null
+++ b/sys/dev/etherswitch/ip17x/ip175c.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2013 Luiz Otavio O Souza.
+ * Copyright (c) 2011-2012 Stefan Bethke.
+ * Copyright (c) 2012 Adrian Chadd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __IP175C_H__
+#define __IP175C_H__
+
+#define IP175C_MODE_PHY 29
+#define IP175C_MODE_REG 31
+#define IP175C_RESET_PHY 30
+#define IP175C_RESET_REG 0
+
+#define IP175C_LAST_VLAN 15
+
+void ip175c_attach(struct ip17x_softc *sc);
+
+#endif /* __IP175C_H__ */
diff --git a/sys/dev/etherswitch/ip17x/ip175d.c b/sys/dev/etherswitch/ip17x/ip175d.c
new file mode 100644
index 0000000..8bc2843
--- /dev/null
+++ b/sys/dev/etherswitch/ip17x/ip175d.c
@@ -0,0 +1,219 @@
+/*-
+ * Copyright (c) 2013 Luiz Otavio O Souza.
+ * Copyright (c) 2011-2012 Stefan Bethke.
+ * Copyright (c) 2012 Adrian Chadd.
+ * Copyright (C) 2008 Patrick Horn.
+ * Copyright (C) 2008, 2010 Martin Mares.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+
+#include <dev/mii/mii.h>
+
+#include <dev/etherswitch/etherswitch.h>
+#include <dev/etherswitch/ip17x/ip17x_phy.h>
+#include <dev/etherswitch/ip17x/ip17x_reg.h>
+#include <dev/etherswitch/ip17x/ip17x_var.h>
+#include <dev/etherswitch/ip17x/ip17x_vlans.h>
+#include <dev/etherswitch/ip17x/ip175d.h>
+
+/*
+ * IP175D specific functions.
+ */
+
+/*
+ * Reset the switch to default state.
+ */
+static int
+ip175d_reset(struct ip17x_softc *sc)
+{
+
+ /* Reset all the switch settings. */
+ ip17x_writephy(sc->sc_dev, IP175D_RESET_PHY, IP175D_RESET_REG, 0x175d);
+ DELAY(2);
+
+ /* Disable the special tagging mode. */
+ ip17x_updatephy(sc->sc_dev, 21, 22, 0x3, 0x0);
+
+ /* Set 802.1q protocol type. */
+ ip17x_writephy(sc->sc_dev, 22, 3, 0x8100);
+
+ return (0);
+}
+
+/*
+ * Set the Switch configuration.
+ */
+static int
+ip175d_hw_setup(struct ip17x_softc *sc)
+{
+ struct ip17x_vlan *v;
+ uint32_t ports[IP17X_MAX_VLANS];
+ uint32_t addtag[IP17X_MAX_VLANS];
+ uint32_t striptag[IP17X_MAX_VLANS];
+ uint32_t vlan_mask;
+ int i, j;
+
+ vlan_mask = 0;
+ for (i = 0; i < IP17X_MAX_VLANS; i++) {
+
+ ports[i] = 0;
+ addtag[i] = 0;
+ striptag[i] = 0;
+
+ v = &sc->vlan[i];
+ if (v->vlanid == 0 || sc->vlan_mode == 0) {
+ /* Vlangroup disabled. Reset the filter. */
+ ip17x_writephy(sc->sc_dev, 22, 14 + i, i + 1);
+ ports[i] = 0x3f;
+ continue;
+ }
+
+ vlan_mask |= (1 << i);
+ ports[i] = v->ports;
+
+ /* Setup the filter, write the VLAN id. */
+ ip17x_writephy(sc->sc_dev, 22, 14 + i, v->vlanid);
+
+ for (j = 0; j < MII_NPHY; j++) {
+ if ((ports[i] & (1 << j)) == 0)
+ continue;
+ if (sc->addtag & (1 << j))
+ addtag[i] |= (1 << j);
+ if (sc->striptag & (1 << j))
+ striptag[i] |= (1 << j);
+ }
+ }
+
+ /* Write the port masks, tag adds and removals. */
+ for (i = 0; i < IP17X_MAX_VLANS / 2; i++) {
+ ip17x_writephy(sc->sc_dev, 23, i,
+ ports[2 * i] | (ports[2 * i + 1] << 8));
+ ip17x_writephy(sc->sc_dev, 23, i + 8,
+ addtag[2 * i] | (addtag[2 * i + 1] << 8));
+ ip17x_writephy(sc->sc_dev, 23, i + 16,
+ striptag[2 * i] | (striptag[2 * i + 1] << 8));
+ }
+
+ /* Write the in use vlan mask. */
+ ip17x_writephy(sc->sc_dev, 22, 10, vlan_mask);
+
+ /* Write the PVID of each port. */
+ for (i = 0; i < sc->numports; i++)
+ ip17x_writephy(sc->sc_dev, 22, 4 + i, sc->pvid[i]);
+
+ return (0);
+}
+
+/*
+ * Set the switch VLAN mode.
+ */
+static int
+ip175d_set_vlan_mode(struct ip17x_softc *sc, uint32_t mode)
+{
+
+ switch (mode) {
+ case ETHERSWITCH_VLAN_DOT1Q:
+ /*
+ * VLAN classification rules: tag-based VLANs,
+ * use VID to classify, drop packets that cannot
+ * be classified.
+ */
+ ip17x_updatephy(sc->sc_dev, 22, 0, 0x3fff, 0x003f);
+ sc->vlan_mode = mode;
+ break;
+ case ETHERSWITCH_VLAN_PORT:
+ sc->vlan_mode = mode;
+ /* fallthrough */
+ default:
+ /*
+ * VLAN classification rules: everything off &
+ * clear table.
+ */
+ ip17x_updatephy(sc->sc_dev, 22, 0, 0xbfff, 0x8000);
+ sc->vlan_mode = 0;
+ break;
+ };
+
+ if (sc->vlan_mode != 0) {
+ /*
+ * Ingress rules: CFI=1 dropped, null VID is untagged, VID=1 passed,
+ * VID=0xfff discarded, admin both tagged and untagged, ingress
+ * filters enabled.
+ */
+ ip17x_updatephy(sc->sc_dev, 22, 1, 0x0fff, 0x0c3f);
+
+ /* Egress rules: IGMP processing off, keep VLAN header off. */
+ ip17x_updatephy(sc->sc_dev, 22, 2, 0x0fff, 0x0000);
+ } else {
+ ip17x_updatephy(sc->sc_dev, 22, 1, 0x0fff, 0x043f);
+ ip17x_updatephy(sc->sc_dev, 22, 2, 0x0fff, 0x0020);
+ }
+
+ /* Reset vlans. */
+ ip17x_reset_vlans(sc, sc->vlan_mode);
+
+ /* Update switch configuration. */
+ ip175d_hw_setup(sc);
+
+ return (0);
+}
+
+/*
+ * Get the switch VLAN mode.
+ */
+static int
+ip175d_get_vlan_mode(struct ip17x_softc *sc)
+{
+
+ return (sc->vlan_mode);
+}
+
+void
+ip175d_attach(struct ip17x_softc *sc)
+{
+
+ sc->hal.ip17x_reset = ip175d_reset;
+ sc->hal.ip17x_hw_setup = ip175d_hw_setup;
+ sc->hal.ip17x_get_vlan_mode = ip175d_get_vlan_mode;
+ sc->hal.ip17x_set_vlan_mode = ip175d_set_vlan_mode;
+
+ /* Defaults for IP175C. */
+ sc->cpuport = IP175X_CPU_PORT;
+ sc->numports = IP175X_NUM_PORTS;
+ sc->info.es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q;
+
+ device_printf(sc->sc_dev, "type: IP175D\n");
+}
diff --git a/sys/dev/etherswitch/ip17x/ip175d.h b/sys/dev/etherswitch/ip17x/ip175d.h
new file mode 100644
index 0000000..d8a3033
--- /dev/null
+++ b/sys/dev/etherswitch/ip17x/ip175d.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2013 Luiz Otavio O Souza.
+ * Copyright (c) 2011-2012 Stefan Bethke.
+ * Copyright (c) 2012 Adrian Chadd.
+ * Copyright (C) 2008 Patrick Horn.
+ * Copyright (C) 2008, 2010 Martin Mares.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __IP175D_H__
+#define __IP175D_H__
+
+#define IP175D_ID_PHY 20
+#define IP175D_ID_REG 0
+#define IP175D_RESET_PHY 20
+#define IP175D_RESET_REG 2
+
+void ip175d_attach(struct ip17x_softc *sc);
+
+#endif /* __IP175D_H__ */
diff --git a/sys/dev/etherswitch/ip17x/ip17x.c b/sys/dev/etherswitch/ip17x/ip17x.c
new file mode 100644
index 0000000..5ac0554
--- /dev/null
+++ b/sys/dev/etherswitch/ip17x/ip17x.c
@@ -0,0 +1,614 @@
+/*-
+ * Copyright (c) 2013 Luiz Otavio O Souza.
+ * Copyright (c) 2011-2012 Stefan Bethke.
+ * Copyright (c) 2012 Adrian Chadd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/errno.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#include <machine/bus.h>
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include <dev/etherswitch/mdio.h>
+
+#include <dev/etherswitch/etherswitch.h>
+#include <dev/etherswitch/ip17x/ip17x_phy.h>
+#include <dev/etherswitch/ip17x/ip17x_reg.h>
+#include <dev/etherswitch/ip17x/ip17x_var.h>
+#include <dev/etherswitch/ip17x/ip17x_vlans.h>
+#include <dev/etherswitch/ip17x/ip175c.h>
+#include <dev/etherswitch/ip17x/ip175d.h>
+
+#include "mdio_if.h"
+#include "miibus_if.h"
+#include "etherswitch_if.h"
+
+MALLOC_DECLARE(M_IP17X);
+MALLOC_DEFINE(M_IP17X, "ip17x", "ip17x data structures");
+
+static void ip17x_tick(void *);
+static int ip17x_ifmedia_upd(struct ifnet *);
+static void ip17x_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+
+static int
+ip17x_probe(device_t dev)
+{
+ struct ip17x_softc *sc;
+ uint32_t oui, model, phy_id1, phy_id2;
+
+ sc = device_get_softc(dev);
+
+ /* Read ID from PHY 0. */
+ phy_id1 = MDIO_READREG(device_get_parent(dev), 0, MII_PHYIDR1);
+ phy_id2 = MDIO_READREG(device_get_parent(dev), 0, MII_PHYIDR2);
+
+ oui = MII_OUI(phy_id1, phy_id2),
+ model = MII_MODEL(phy_id2);
+ /* We only care about IC+ devices. */
+ if (oui != IP17X_OUI) {
+ device_printf(dev,
+ "Unsupported IC+ switch. Unknown OUI: %#x\n", oui);
+ return (ENXIO);
+ }
+
+ switch (model) {
+ case IP17X_IP175A:
+ sc->sc_switchtype = IP17X_SWITCH_IP175A;
+ break;
+ case IP17X_IP175C:
+ sc->sc_switchtype = IP17X_SWITCH_IP175C;
+ break;
+ default:
+ device_printf(dev, "Unsupported IC+ switch model: %#x\n",
+ model);
+ return (ENXIO);
+ }
+
+ /* IP175D has a specific ID register. */
+ model = MDIO_READREG(device_get_parent(dev), IP175D_ID_PHY,
+ IP175D_ID_REG);
+ if (model == 0x175d)
+ sc->sc_switchtype = IP17X_SWITCH_IP175D;
+ else {
+ /* IP178 has more PHYs. Try it. */
+ model = MDIO_READREG(device_get_parent(dev), 5, MII_PHYIDR1);
+ if (phy_id1 == model)
+ sc->sc_switchtype = IP17X_SWITCH_IP178C;
+ }
+
+ device_set_desc_copy(dev, "IC+ IP17x switch driver");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+ip17x_attach_phys(struct ip17x_softc *sc)
+{
+ int err, phy, port;
+ char name[IFNAMSIZ];
+
+ port = err = 0;
+
+ /* PHYs need an interface, so we generate a dummy one */
+ snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->sc_dev));
+ for (phy = 0; phy < MII_NPHY; phy++) {
+ if (((1 << phy) & sc->phymask) == 0)
+ continue;
+ sc->phyport[phy] = port;
+ sc->portphy[port] = phy;
+ sc->ifp[port] = if_alloc(IFT_ETHER);
+ sc->ifp[port]->if_softc = sc;
+ sc->ifp[port]->if_flags |= IFF_UP | IFF_BROADCAST |
+ IFF_DRV_RUNNING | IFF_SIMPLEX;
+ sc->ifname[port] = malloc(strlen(name)+1, M_IP17X, M_WAITOK);
+ bcopy(name, sc->ifname[port], strlen(name)+1);
+ if_initname(sc->ifp[port], sc->ifname[port], port);
+ sc->miibus[port] = malloc(sizeof(device_t), M_IP17X,
+ M_WAITOK | M_ZERO);
+ err = mii_attach(sc->sc_dev, sc->miibus[port], sc->ifp[port],
+ ip17x_ifmedia_upd, ip17x_ifmedia_sts, \
+ BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0);
+ DPRINTF(sc->sc_dev, "%s attached to pseudo interface %s\n",
+ device_get_nameunit(*sc->miibus[port]),
+ sc->ifp[port]->if_xname);
+ if (err != 0) {
+ device_printf(sc->sc_dev,
+ "attaching PHY %d failed\n",
+ phy);
+ break;
+ }
+ sc->info.es_nports = port + 1;
+ if (++port >= sc->numports)
+ break;
+ }
+ return (err);
+}
+
+static int
+ip17x_attach(device_t dev)
+{
+ struct ip17x_softc *sc;
+ int err;
+
+ sc = device_get_softc(dev);
+
+ sc->sc_dev = dev;
+ mtx_init(&sc->sc_mtx, "ip17x", NULL, MTX_DEF);
+ strlcpy(sc->info.es_name, device_get_desc(dev),
+ sizeof(sc->info.es_name));
+
+ /* XXX Defaults */
+ sc->phymask = 0x0f;
+ sc->media = 100;
+
+ (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
+ "phymask", &sc->phymask);
+
+ /* Number of vlans supported by the switch. */
+ sc->info.es_nvlangroups = IP17X_MAX_VLANS;
+
+ /* Attach the switch related functions. */
+ if (IP17X_IS_SWITCH(sc, IP175C))
+ ip175c_attach(sc);
+ else if (IP17X_IS_SWITCH(sc, IP175D))
+ ip175d_attach(sc);
+ else
+ /* We don't have support to all the models yet :-/ */
+ return (ENXIO);
+
+ /* Always attach the cpu port. */
+ sc->phymask |= (1 << sc->cpuport);
+
+ sc->ifp = malloc(sizeof(struct ifnet *) * sc->numports, M_IP17X,
+ M_WAITOK | M_ZERO);
+ sc->pvid = malloc(sizeof(uint32_t) * sc->numports, M_IP17X,
+ M_WAITOK | M_ZERO);
+ sc->ifname = malloc(sizeof(char *) * sc->numports, M_IP17X,
+ M_WAITOK | M_ZERO);
+ sc->miibus = malloc(sizeof(device_t *) * sc->numports, M_IP17X,
+ M_WAITOK | M_ZERO);
+ sc->portphy = malloc(sizeof(int) * sc->numports, M_IP17X,
+ M_WAITOK | M_ZERO);
+
+ /* Initialize the switch. */
+ sc->hal.ip17x_reset(sc);
+
+ /*
+ * Attach the PHYs and complete the bus enumeration.
+ */
+ err = ip17x_attach_phys(sc);
+ if (err != 0)
+ return (err);
+
+ /*
+ * Set the switch to port based vlans or disabled (if not supported
+ * on this model).
+ */
+ sc->hal.ip17x_set_vlan_mode(sc, ETHERSWITCH_VLAN_PORT);
+
+ bus_generic_probe(dev);
+ bus_enumerate_hinted_children(dev);
+ err = bus_generic_attach(dev);
+ if (err != 0)
+ return (err);
+
+ callout_init(&sc->callout_tick, 0);
+
+ ip17x_tick(sc);
+
+ return (0);
+}
+
+static int
+ip17x_detach(device_t dev)
+{
+ struct ip17x_softc *sc;
+ int i, port;
+
+ sc = device_get_softc(dev);
+ callout_drain(&sc->callout_tick);
+
+ for (i=0; i < MII_NPHY; i++) {
+ if (((1 << i) & sc->phymask) == 0)
+ continue;
+ port = sc->phyport[i];
+ if (sc->miibus[port] != NULL)
+ device_delete_child(dev, (*sc->miibus[port]));
+ if (sc->ifp[port] != NULL)
+ if_free(sc->ifp[port]);
+ free(sc->ifname[port], M_IP17X);
+ free(sc->miibus[port], M_IP17X);
+ }
+
+ free(sc->portphy, M_IP17X);
+ free(sc->miibus, M_IP17X);
+ free(sc->ifname, M_IP17X);
+ free(sc->pvid, M_IP17X);
+ free(sc->ifp, M_IP17X);
+
+ /* Reset the switch. */
+ sc->hal.ip17x_reset(sc);
+
+ bus_generic_detach(dev);
+ mtx_destroy(&sc->sc_mtx);
+
+ return (0);
+}
+
+static inline struct mii_data *
+ip17x_miiforport(struct ip17x_softc *sc, int port)
+{
+
+ if (port < 0 || port > sc->numports)
+ return (NULL);
+ return (device_get_softc(*sc->miibus[port]));
+}
+
+static inline struct ifnet *
+ip17x_ifpforport(struct ip17x_softc *sc, int port)
+{
+
+ if (port < 0 || port > sc->numports)
+ return (NULL);
+ return (sc->ifp[port]);
+}
+
+/*
+ * Poll the status for all PHYs.
+ */
+static void
+ip17x_miipollstat(struct ip17x_softc *sc)
+{
+ struct mii_softc *miisc;
+ struct mii_data *mii;
+ int i, port;
+
+ IP17X_LOCK_ASSERT(sc, MA_NOTOWNED);
+
+ for (i = 0; i < MII_NPHY; i++) {
+ if (((1 << i) & sc->phymask) == 0)
+ continue;
+ port = sc->phyport[i];
+ if ((*sc->miibus[port]) == NULL)
+ continue;
+ mii = device_get_softc(*sc->miibus[port]);
+ LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
+ if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) !=
+ miisc->mii_inst)
+ continue;
+ ukphy_status(miisc);
+ mii_phy_update(miisc, MII_POLLSTAT);
+ }
+ }
+}
+
+static void
+ip17x_tick(void *arg)
+{
+ struct ip17x_softc *sc;
+
+ sc = arg;
+ ip17x_miipollstat(sc);
+ callout_reset(&sc->callout_tick, hz, ip17x_tick, sc);
+}
+
+static void
+ip17x_lock(device_t dev)
+{
+ struct ip17x_softc *sc;
+
+ sc = device_get_softc(dev);
+ IP17X_LOCK_ASSERT(sc, MA_NOTOWNED);
+ IP17X_LOCK(sc);
+}
+
+static void
+ip17x_unlock(device_t dev)
+{
+ struct ip17x_softc *sc;
+
+ sc = device_get_softc(dev);
+ IP17X_LOCK_ASSERT(sc, MA_OWNED);
+ IP17X_UNLOCK(sc);
+}
+
+static etherswitch_info_t *
+ip17x_getinfo(device_t dev)
+{
+ struct ip17x_softc *sc;
+
+ sc = device_get_softc(dev);
+ return (&sc->info);
+}
+
+static int
+ip17x_getport(device_t dev, etherswitch_port_t *p)
+{
+ struct ip17x_softc *sc;
+ struct ifmediareq *ifmr;
+ struct mii_data *mii;
+ int err, phy;
+
+ sc = device_get_softc(dev);
+ if (p->es_port < 0 || p->es_port >= sc->numports)
+ return (ENXIO);
+
+ phy = sc->portphy[p->es_port];
+
+ /* Retrieve the PVID. */
+ p->es_pvid = sc->pvid[phy];
+
+ /* Port flags. */
+ if (sc->addtag & (1 << phy))
+ p->es_flags |= ETHERSWITCH_PORT_ADDTAG;
+ if (sc->striptag & (1 << phy))
+ p->es_flags |= ETHERSWITCH_PORT_STRIPTAG;
+
+ ifmr = &p->es_ifmr;
+
+ /* No media settings ? */
+ if (p->es_ifmr.ifm_count == 0)
+ return (0);
+
+ mii = ip17x_miiforport(sc, p->es_port);
+ if (mii == NULL)
+ return (ENXIO);
+ if (phy == sc->cpuport) {
+ /* fill in fixed values for CPU port */
+ p->es_flags |= ETHERSWITCH_PORT_CPU;
+ ifmr->ifm_count = 0;
+ if (sc->media == 100)
+ ifmr->ifm_current = ifmr->ifm_active =
+ IFM_ETHER | IFM_100_TX | IFM_FDX;
+ else
+ ifmr->ifm_current = ifmr->ifm_active =
+ IFM_ETHER | IFM_1000_T | IFM_FDX;
+ ifmr->ifm_mask = 0;
+ ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID;
+ } else {
+ err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr,
+ &mii->mii_media, SIOCGIFMEDIA);
+ if (err)
+ return (err);
+ }
+ return (0);
+}
+
+static int
+ip17x_setport(device_t dev, etherswitch_port_t *p)
+{
+ struct ip17x_softc *sc;
+ struct ifmedia *ifm;
+ struct ifnet *ifp;
+ struct mii_data *mii;
+ int phy;
+
+ sc = device_get_softc(dev);
+ if (p->es_port < 0 || p->es_port >= sc->numports)
+ return (ENXIO);
+
+ phy = sc->portphy[p->es_port];
+ ifp = ip17x_ifpforport(sc, p->es_port);
+ mii = ip17x_miiforport(sc, p->es_port);
+ if (ifp == NULL || mii == NULL)
+ return (ENXIO);
+
+ /* Port flags. */
+ if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
+
+ /* Set the PVID. */
+ if (p->es_pvid != 0) {
+ if (IP17X_IS_SWITCH(sc, IP175C) &&
+ p->es_pvid > IP175C_LAST_VLAN)
+ return (ENXIO);
+ sc->pvid[phy] = p->es_pvid;
+ }
+
+ /* Mutually exclusive. */
+ if (p->es_flags & ETHERSWITCH_PORT_ADDTAG &&
+ p->es_flags & ETHERSWITCH_PORT_STRIPTAG)
+ return (EINVAL);
+
+ /* Reset the settings for this port. */
+ sc->addtag &= ~(1 << phy);
+ sc->striptag &= ~(1 << phy);
+
+ /* And then set it to the new value. */
+ if (p->es_flags & ETHERSWITCH_PORT_ADDTAG)
+ sc->addtag |= (1 << phy);
+ if (p->es_flags & ETHERSWITCH_PORT_STRIPTAG)
+ sc->striptag |= (1 << phy);
+ }
+
+ /* Update the switch configuration. */
+ if (sc->hal.ip17x_hw_setup(sc))
+ return (ENXIO);
+
+ /* Do not allow media changes on CPU port. */
+ if (phy == sc->cpuport)
+ return (0);
+
+ /* No media settings ? */
+ if (p->es_ifmr.ifm_count == 0)
+ return (0);
+
+ ifm = &mii->mii_media;
+ return (ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA));
+}
+
+static void
+ip17x_statchg(device_t dev)
+{
+
+ DPRINTF(dev, "%s\n", __func__);
+}
+
+static int
+ip17x_ifmedia_upd(struct ifnet *ifp)
+{
+ struct ip17x_softc *sc;
+ struct mii_data *mii;
+
+ DPRINTF(sc->sc_dev, "%s\n", __func__);
+ sc = ifp->if_softc;
+ mii = ip17x_miiforport(sc, ifp->if_dunit);
+ if (mii == NULL)
+ return (ENXIO);
+ mii_mediachg(mii);
+ return (0);
+}
+
+static void
+ip17x_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct ip17x_softc *sc;
+ struct mii_data *mii;
+
+ DPRINTF(sc->sc_dev, "%s\n", __func__);
+
+ sc = ifp->if_softc;
+ mii = ip17x_miiforport(sc, ifp->if_dunit);
+ if (mii == NULL)
+ return;
+ mii_pollstat(mii);
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
+}
+
+static int
+ip17x_readreg(device_t dev, int addr)
+{
+ struct ip17x_softc *sc;
+
+ sc = device_get_softc(dev);
+ IP17X_LOCK_ASSERT(sc, MA_OWNED);
+
+ /* Not supported. */
+ return (0);
+}
+
+static int
+ip17x_writereg(device_t dev, int addr, int value)
+{
+ struct ip17x_softc *sc;
+
+ sc = device_get_softc(dev);
+ IP17X_LOCK_ASSERT(sc, MA_OWNED);
+
+ /* Not supported. */
+ return (0);
+}
+
+static int
+ip17x_getconf(device_t dev, etherswitch_conf_t *conf)
+{
+ struct ip17x_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ /* Return the VLAN mode. */
+ conf->cmd = ETHERSWITCH_CONF_VLAN_MODE;
+ conf->vlan_mode = sc->hal.ip17x_get_vlan_mode(sc);
+
+ return (0);
+}
+
+static int
+ip17x_setconf(device_t dev, etherswitch_conf_t *conf)
+{
+ struct ip17x_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ /* Set the VLAN mode. */
+ if (conf->cmd & ETHERSWITCH_CONF_VLAN_MODE)
+ sc->hal.ip17x_set_vlan_mode(sc, conf->vlan_mode);
+
+ return (0);
+}
+
+static device_method_t ip17x_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ip17x_probe),
+ DEVMETHOD(device_attach, ip17x_attach),
+ DEVMETHOD(device_detach, ip17x_detach),
+
+ /* bus interface */
+ DEVMETHOD(bus_add_child, device_add_child_ordered),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, ip17x_readphy),
+ DEVMETHOD(miibus_writereg, ip17x_writephy),
+ DEVMETHOD(miibus_statchg, ip17x_statchg),
+
+ /* MDIO interface */
+ DEVMETHOD(mdio_readreg, ip17x_readphy),
+ DEVMETHOD(mdio_writereg, ip17x_writephy),
+
+ /* etherswitch interface */
+ DEVMETHOD(etherswitch_lock, ip17x_lock),
+ DEVMETHOD(etherswitch_unlock, ip17x_unlock),
+ DEVMETHOD(etherswitch_getinfo, ip17x_getinfo),
+ DEVMETHOD(etherswitch_readreg, ip17x_readreg),
+ DEVMETHOD(etherswitch_writereg, ip17x_writereg),
+ DEVMETHOD(etherswitch_readphyreg, ip17x_readphy),
+ DEVMETHOD(etherswitch_writephyreg, ip17x_writephy),
+ DEVMETHOD(etherswitch_getport, ip17x_getport),
+ DEVMETHOD(etherswitch_setport, ip17x_setport),
+ DEVMETHOD(etherswitch_getvgroup, ip17x_getvgroup),
+ DEVMETHOD(etherswitch_setvgroup, ip17x_setvgroup),
+ DEVMETHOD(etherswitch_getconf, ip17x_getconf),
+ DEVMETHOD(etherswitch_setconf, ip17x_setconf),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(ip17x, ip17x_driver, ip17x_methods,
+ sizeof(struct ip17x_softc));
+static devclass_t ip17x_devclass;
+
+DRIVER_MODULE(ip17x, mdio, ip17x_driver, ip17x_devclass, 0, 0);
+DRIVER_MODULE(miibus, ip17x, miibus_driver, miibus_devclass, 0, 0);
+DRIVER_MODULE(mdio, ip17x, mdio_driver, mdio_devclass, 0, 0);
+DRIVER_MODULE(etherswitch, ip17x, etherswitch_driver, etherswitch_devclass, 0, 0);
+MODULE_VERSION(ip17x, 1);
+MODULE_DEPEND(ip17x, miibus, 1, 1, 1); /* XXX which versions? */
+MODULE_DEPEND(ip17x, etherswitch, 1, 1, 1); /* XXX which versions? */
diff --git a/sys/dev/etherswitch/ip17x/ip17x_phy.c b/sys/dev/etherswitch/ip17x/ip17x_phy.c
new file mode 100644
index 0000000..067b8ba
--- /dev/null
+++ b/sys/dev/etherswitch/ip17x/ip17x_phy.c
@@ -0,0 +1,102 @@
+/*-
+ * Copyright (c) 2013 Luiz Otavio O Souza.
+ * Copyright (c) 2011-2012 Stefan Bethke.
+ * Copyright (c) 2012 Adrian Chadd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/errno.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+
+#include <dev/mii/mii.h>
+
+#include <dev/etherswitch/etherswitch.h>
+#include <dev/etherswitch/ip17x/ip17x_phy.h>
+#include <dev/etherswitch/ip17x/ip17x_reg.h>
+#include <dev/etherswitch/ip17x/ip17x_var.h>
+
+#include "mdio_if.h"
+#include "miibus_if.h"
+#include "etherswitch_if.h"
+
+int
+ip17x_readphy(device_t dev, int phy, int reg)
+{
+ struct ip17x_softc *sc;
+ int data;
+
+ sc = device_get_softc(dev);
+ IP17X_LOCK_ASSERT(sc, MA_NOTOWNED);
+
+ if (phy < 0 || phy >= 32)
+ return (ENXIO);
+ if (reg < 0 || reg >= 32)
+ return (ENXIO);
+
+ IP17X_LOCK(sc);
+ data = MDIO_READREG(device_get_parent(dev), phy, reg);
+ IP17X_UNLOCK(sc);
+
+ return (data);
+}
+
+int
+ip17x_writephy(device_t dev, int phy, int reg, int data)
+{
+ struct ip17x_softc *sc;
+ int err;
+
+ sc = device_get_softc(dev);
+ IP17X_LOCK_ASSERT(sc, MA_NOTOWNED);
+
+ if (phy < 0 || phy >= 32)
+ return (ENXIO);
+ if (reg < 0 || reg >= 32)
+ return (ENXIO);
+
+ IP17X_LOCK(sc);
+ err = MDIO_WRITEREG(device_get_parent(dev), phy, reg, data);
+ IP17X_UNLOCK(sc);
+
+ return (err);
+}
+
+int
+ip17x_updatephy(device_t dev, int phy, int reg, int mask, int value)
+{
+ int val;
+
+ val = ip17x_readphy(dev, phy, reg);
+ val &= ~mask;
+ val |= value;
+ return (ip17x_writephy(dev, phy, reg, val));
+}
diff --git a/sys/dev/etherswitch/ip17x/ip17x_phy.h b/sys/dev/etherswitch/ip17x/ip17x_phy.h
new file mode 100644
index 0000000..e2638ae
--- /dev/null
+++ b/sys/dev/etherswitch/ip17x/ip17x_phy.h
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 2013 Luiz Otavio O Souza.
+ * Copyright (c) 2011-2012 Stefan Bethke.
+ * Copyright (c) 2012 Adrian Chadd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __IP17X_PHY_H__
+#define __IP17X_PHY_H__
+
+int ip17x_readphy(device_t, int, int);
+int ip17x_writephy(device_t, int, int, int);
+int ip17x_updatephy(device_t, int, int, int, int);
+
+#endif /* __IP17X_PHY_H__ */
diff --git a/sys/dev/etherswitch/ip17x/ip17x_reg.h b/sys/dev/etherswitch/ip17x/ip17x_reg.h
new file mode 100644
index 0000000..09b1196
--- /dev/null
+++ b/sys/dev/etherswitch/ip17x/ip17x_reg.h
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 2013 Luiz Otavio O Souza.
+ * Copyright (c) 2011-2012 Stefan Bethke.
+ * Copyright (c) 2012 Adrian Chadd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __IP17X_REG_H__
+#define __IP17X_REG_H__
+
+/* IP175X */
+#define IP17X_OUI 0x9c3
+#define IP17X_IP175A 0x05
+#define IP17X_IP175C 0x18
+
+#define IP17X_MAX_VLANS 16
+
+#define IP175X_CPU_PORT 5
+#define IP175X_NUM_PORTS 6
+
+#endif /* __IP17X_REG_H__ */
diff --git a/sys/dev/etherswitch/ip17x/ip17x_var.h b/sys/dev/etherswitch/ip17x/ip17x_var.h
new file mode 100644
index 0000000..2259a65
--- /dev/null
+++ b/sys/dev/etherswitch/ip17x/ip17x_var.h
@@ -0,0 +1,95 @@
+/*-
+ * Copyright (c) 2013 Luiz Otavio O Souza.
+ * Copyright (c) 2011-2012 Stefan Bethke.
+ * Copyright (c) 2012 Adrian Chadd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __IP17X_VAR_H__
+#define __IP17X_VAR_H__
+
+typedef enum {
+ IP17X_SWITCH_NONE,
+ IP17X_SWITCH_IP175A,
+ IP17X_SWITCH_IP175C,
+ IP17X_SWITCH_IP175D,
+ IP17X_SWITCH_IP178C,
+} ip17x_switch_type;
+
+struct ip17x_vlan {
+ uint32_t ports;
+ int vlanid;
+};
+
+struct ip17x_softc {
+ device_t sc_dev;
+ int media; /* cpu port media */
+ int cpuport; /* which PHY is connected to the CPU */
+ int phymask; /* PHYs we manage */
+ int phyport[MII_NPHY];
+ int numports; /* number of ports */
+ int *portphy;
+ char **ifname;
+ device_t **miibus;
+ etherswitch_info_t info;
+ ip17x_switch_type sc_switchtype;
+ struct callout callout_tick;
+ struct ifnet **ifp;
+ struct mtx sc_mtx; /* serialize access to softc */
+
+ struct ip17x_vlan vlan[IP17X_MAX_VLANS];
+ uint32_t *pvid; /* PVID */
+ uint32_t addtag; /* per port add tag flag */
+ uint32_t striptag; /* per port strip tag flag */
+ uint32_t vlan_mode; /* VLAN mode */
+
+ struct {
+ int (* ip17x_reset) (struct ip17x_softc *);
+ int (* ip17x_hw_setup) (struct ip17x_softc *);
+ int (* ip17x_get_vlan_mode) (struct ip17x_softc *);
+ int (* ip17x_set_vlan_mode) (struct ip17x_softc *, uint32_t);
+ } hal;
+};
+
+#define IP17X_IS_SWITCH(_sc, _type) \
+ (!!((_sc)->sc_switchtype == IP17X_SWITCH_ ## _type))
+
+#define IP17X_LOCK(_sc) \
+ mtx_lock(&(_sc)->sc_mtx)
+#define IP17X_UNLOCK(_sc) \
+ mtx_unlock(&(_sc)->sc_mtx)
+#define IP17X_LOCK_ASSERT(_sc, _what) \
+ mtx_assert(&(_sc)->sc_mtx, (_what))
+#define IP17X_TRYLOCK(_sc) \
+ mtx_trylock(&(_sc)->sc_mtx)
+
+#if defined(DEBUG)
+#define DPRINTF(dev, args...) device_printf(dev, args)
+#else
+#define DPRINTF(dev, args...)
+#endif
+
+#endif /* __IP17X_VAR_H__ */
diff --git a/sys/dev/etherswitch/ip17x/ip17x_vlans.c b/sys/dev/etherswitch/ip17x/ip17x_vlans.c
new file mode 100644
index 0000000..80bfc8b
--- /dev/null
+++ b/sys/dev/etherswitch/ip17x/ip17x_vlans.c
@@ -0,0 +1,167 @@
+/*-
+ * Copyright (c) 2013 Luiz Otavio O Souza.
+ * Copyright (c) 2011-2012 Stefan Bethke.
+ * Copyright (c) 2012 Adrian Chadd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/errno.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+
+#include <dev/mii/mii.h>
+
+#include <dev/etherswitch/etherswitch.h>
+#include <dev/etherswitch/ip17x/ip17x_phy.h>
+#include <dev/etherswitch/ip17x/ip17x_reg.h>
+#include <dev/etherswitch/ip17x/ip17x_var.h>
+#include <dev/etherswitch/ip17x/ip17x_vlans.h>
+#include <dev/etherswitch/ip17x/ip175c.h>
+
+#include "mdio_if.h"
+#include "miibus_if.h"
+#include "etherswitch_if.h"
+
+/*
+ * Reset vlans to default state.
+ */
+int
+ip17x_reset_vlans(struct ip17x_softc *sc, uint32_t vlan_mode)
+{
+ struct ip17x_vlan *v;
+ int i, j, phy;
+
+ /* Do not add or strip vlan tags on any port. */
+ sc->addtag = 0;
+ sc->striptag = 0;
+
+ /* Reset all vlan data. */
+ memset(sc->vlan, 0, sizeof(sc->vlan));
+ memset(sc->pvid, 0, sizeof(uint32_t) * sc->numports);
+
+ if (vlan_mode == ETHERSWITCH_VLAN_PORT) {
+
+ /* Initialize port based vlans. */
+ for (i = 0, phy = 0; phy < MII_NPHY; phy++) {
+ if (((1 << phy) & sc->phymask) == 0)
+ continue;
+ v = &sc->vlan[i];
+ v->vlanid = i++;
+ v->ports = (1 << sc->cpuport);
+ for (j = 0; j < MII_NPHY; j++) {
+ if (((1 << j) & sc->phymask) == 0)
+ continue;
+ v->ports |= (1 << j);
+ }
+ }
+
+ } else if (vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
+
+ /*
+ * Setup vlan 1 as PVID for all switch ports. Add all ports as
+ * members of vlan 1.
+ */
+ v = &sc->vlan[0];
+ v->vlanid = 1;
+ /* Set PVID for everyone. */
+ for (i = 0; i < sc->numports; i++)
+ sc->pvid[i] = v->vlanid;
+ for (i = 0; i < MII_NPHY; i++) {
+ if ((sc->phymask & (1 << i)) == 0)
+ continue;
+ v->ports |= (1 << i);
+ }
+ }
+
+ return (0);
+}
+
+int
+ip17x_getvgroup(device_t dev, etherswitch_vlangroup_t *vg)
+{
+ struct ip17x_softc *sc;
+ uint32_t port;
+ int i;
+
+ sc = device_get_softc(dev);
+
+ /* Vlan ID. */
+ vg->es_vid = sc->vlan[vg->es_vlangroup].vlanid;
+
+ /* Member Ports. */
+ vg->es_member_ports = 0;
+ for (i = 0; i < MII_NPHY; i++) {
+ if ((sc->phymask & (1 << i)) == 0)
+ continue;
+ if ((sc->vlan[vg->es_vlangroup].ports & (1 << i)) == 0)
+ continue;
+ port = sc->phyport[i];
+ vg->es_member_ports |= (1 << port);
+ }
+
+ /* Not supported. */
+ vg->es_untagged_ports = vg->es_member_ports;
+ vg->es_fid = 0;
+
+ return (0);
+}
+
+int
+ip17x_setvgroup(device_t dev, etherswitch_vlangroup_t *vg)
+{
+ struct ip17x_softc *sc;
+ uint32_t phy;
+ int i;
+
+ sc = device_get_softc(dev);
+
+ /* Check VLAN mode. */
+ if (sc->vlan_mode == 0)
+ return (EINVAL);
+
+ /* IP175C don't support VLAN IDs > 15. */
+ if (IP17X_IS_SWITCH(sc, IP175C) && vg->es_vid > IP175C_LAST_VLAN)
+ return (EINVAL);
+
+ /* Vlan ID. */
+ sc->vlan[vg->es_vlangroup].vlanid = vg->es_vid;
+
+ /* Member Ports. */
+ sc->vlan[vg->es_vlangroup].ports = 0;
+ for (i = 0; i < sc->numports; i++) {
+ if ((vg->es_member_ports & (1 << i)) == 0)
+ continue;
+ phy = sc->portphy[i];
+ sc->vlan[vg->es_vlangroup].ports |= (1 << phy);
+ }
+
+ return (sc->hal.ip17x_hw_setup(sc));
+}
diff --git a/sys/dev/etherswitch/ip17x/ip17x_vlans.h b/sys/dev/etherswitch/ip17x/ip17x_vlans.h
new file mode 100644
index 0000000..705926a
--- /dev/null
+++ b/sys/dev/etherswitch/ip17x/ip17x_vlans.h
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2013 Luiz Otavio O Souza.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __IP17X_VLANS_H__
+#define __IP17X_VLANS_H__
+
+int ip17x_reset_vlans(struct ip17x_softc *, uint32_t);
+int ip17x_getvgroup(device_t, etherswitch_vlangroup_t *);
+int ip17x_setvgroup(device_t, etherswitch_vlangroup_t *);
+
+#endif /* __IP17X_VLANS_H__ */
OpenPOWER on IntegriCloud