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
This commit is contained in:
parent
f4b590dbf1
commit
51658e393d
@ -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
|
||||
|
249
sys/dev/etherswitch/ip17x/ip175c.c
Normal file
249
sys/dev/etherswitch/ip17x/ip175c.c
Normal file
@ -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");
|
||||
}
|
43
sys/dev/etherswitch/ip17x/ip175c.h
Normal file
43
sys/dev/etherswitch/ip17x/ip175c.h
Normal file
@ -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__ */
|
219
sys/dev/etherswitch/ip17x/ip175d.c
Normal file
219
sys/dev/etherswitch/ip17x/ip175d.c
Normal file
@ -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");
|
||||
}
|
43
sys/dev/etherswitch/ip17x/ip175d.h
Normal file
43
sys/dev/etherswitch/ip17x/ip175d.h
Normal file
@ -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__ */
|
614
sys/dev/etherswitch/ip17x/ip17x.c
Normal file
614
sys/dev/etherswitch/ip17x/ip17x.c
Normal file
@ -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? */
|
102
sys/dev/etherswitch/ip17x/ip17x_phy.c
Normal file
102
sys/dev/etherswitch/ip17x/ip17x_phy.c
Normal file
@ -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));
|
||||
}
|
38
sys/dev/etherswitch/ip17x/ip17x_phy.h
Normal file
38
sys/dev/etherswitch/ip17x/ip17x_phy.h
Normal file
@ -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__ */
|
44
sys/dev/etherswitch/ip17x/ip17x_reg.h
Normal file
44
sys/dev/etherswitch/ip17x/ip17x_reg.h
Normal file
@ -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__ */
|
95
sys/dev/etherswitch/ip17x/ip17x_var.h
Normal file
95
sys/dev/etherswitch/ip17x/ip17x_var.h
Normal file
@ -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__ */
|
167
sys/dev/etherswitch/ip17x/ip17x_vlans.c
Normal file
167
sys/dev/etherswitch/ip17x/ip17x_vlans.c
Normal file
@ -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));
|
||||
}
|
36
sys/dev/etherswitch/ip17x/ip17x_vlans.h
Normal file
36
sys/dev/etherswitch/ip17x/ip17x_vlans.h
Normal file
@ -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__ */
|
Loading…
Reference in New Issue
Block a user