[Zrouter-src-freebsd] ZRouter.org: push to FreeBSD HEAD tree
zrouter-src-freebsd at zrouter.org
zrouter-src-freebsd at zrouter.org
Fri Feb 3 15:31:03 UTC 2012
details: http://zrouter.org/hg/FreeBSD/head//rev/3c0fed8eac60
changeset: 337:3c0fed8eac60
user: ray at terran.dlink.ua
date: Fri Feb 03 17:31:23 2012 +0200
description:
Update bcm5325 driver for Port Based VLAN setup
diffstat:
head/sys/dev/switch/bcm5325_switch.c | 268 ++++++++++++++++++++++++++-----
head/sys/dev/switch/bcm5325_switchreg.h | 25 +-
head/sys/dev/switch/bcm5325_switchvar.h | 8 +-
3 files changed, 246 insertions(+), 55 deletions(-)
diffs (528 lines):
diff -r 7142a751aca2 -r 3c0fed8eac60 head/sys/dev/switch/bcm5325_switch.c
--- a/head/sys/dev/switch/bcm5325_switch.c Fri Feb 03 17:30:35 2012 +0200
+++ b/head/sys/dev/switch/bcm5325_switch.c Fri Feb 03 17:31:23 2012 +0200
@@ -73,6 +73,15 @@
static int bcm5325_read(struct bcm5325_switch_softc *sc, uint32_t reg,
uint64_t *val);
+static int bcm5325_vlan_write(struct bcm5325_switch_softc *sc, uint16_t vid,
+ uint32_t tports, uint32_t uports);
+static int bcm5325_vlan_read(struct bcm5325_switch_softc *sc, uint16_t vid,
+ uint32_t *tports, uint32_t *uports);
+static int bcm5395_vlan_write(struct bcm5325_switch_softc *sc, uint16_t vid,
+ uint32_t tports, uint32_t uports);
+static int bcm5395_vlan_read(struct bcm5325_switch_softc *sc, uint16_t vid,
+ uint32_t *tports, uint32_t *uports);
+
#define PSPHY_WRITE(_sc, _reg, _val) \
MII_SW_WRITE4((_sc), ((PSEUDOPHY_ADDR << 8) | (_reg)), (_val))
#define PSPHY_READ(_sc, _reg) \
@@ -203,7 +212,7 @@
struct bcm5325_switch_softc *sc;
uint64_t reg;
uint64_t reg32;
- int i;
+// int i;
sc = device_get_softc(dev);
sc->parent = device_get_parent(dev);
@@ -213,13 +222,18 @@
reg = 0;
READ(sc, SWITCH_DEVICEID, ®);
- reg32 = reg & 0xffff;
+ reg32 = reg & 0xfffff;
if (reg32) {
+#if 1
+ /* At least BCM53115 return 0x53115 if query in 32bit mode */
+ sc->devid = reg32;
+#else
/* XXX: maybe wrong, based on known chips */
if (reg32 < 0x100)
sc->devid = reg32 + 0x5300;
else
sc->devid = reg32 + 0x50000;
+#endif
}
resource_int_value(device_get_name(dev), device_get_unit(dev),
@@ -227,33 +241,47 @@
device_printf(dev, "\t%switch model is BCM%x\n",
((resource_int_value(device_get_name(dev), device_get_unit(dev),
"devid", &sc->devid))?"S":"Hinted s"), sc->devid);
-#ifdef notyet
- switch (sc->devid) {
- case 0x5365:
- sc->mode = 0;
- break;
- case 0x5356:
- sc->mode = 0;
- break;
- case 0x53115:
- sc->mode = 0;
- break;
- case 0x5325:
- case 0x5352:
- case 0x5354:
- default:
- sc->mode = 0;
- break;
- }
-#endif
+
sc->caps = malloc(sizeof(struct switch_capability), M_DEVBUF,
M_WAITOK | M_ZERO);
if (!sc->caps)
return (ENXIO);
- sc->caps->ports = sc->ports = 6;
- sc->vlans = 16;
+ switch (sc->devid) {
+ case 0x5395:
+ case 0x53115:
+ case 0x53118:
+ sc->vlan_write = &bcm5395_vlan_write;
+ sc->vlan_read = &bcm5395_vlan_read;
+ sc->vlans = 4096;
+ break;
+ case 0x5325:
+ case 0x5352:
+ case 0x5354:
+ default:
+ sc->vlan_write = &bcm5325_vlan_write;
+ sc->vlan_read = &bcm5325_vlan_read;
+ sc->vlans = 16;
+ break;
+ }
+
+ switch (sc->devid) {
+ case 0x53118:
+ case 0x53115: /* 53118 w/o ports 6-7 */
+ sc->caps->ports = sc->ports = 9;
+ break;
+ case 0x5325:
+ case 0x5352:
+ case 0x5354:
+ case 0x5395:
+ sc->caps->ports = sc->ports = 6;
+ break;
+ default:
+ /* XXX: trick, last digit of id + 1 MII port */
+ sc->caps->ports = sc->ports = (sc->devid % 0xf) + 1;
+ break;
+ }
sc->sc_dev = dev;
#define S_C(x) SWITCH_CAPS_ ## x
@@ -311,16 +339,16 @@
/*
* XXX: Avoid default configuration, bootloader must set it or we
- * load user defined
+ * must load user defined
*/
/* set_vid(swdev, Idx, VID) */
- set_vid(dev, 0, 1);
+ //set_vid(dev, 0, 1);
/* All ports are members of VLAN0 (VID1) */
- set_vlan_ports(dev, 0, 0x01ff);
+ //set_vlan_ports(dev, 0, 0x01ff);
/* Other VLANs have no members */
- for (i = 1; i < 9; i++)
- set_vlan_ports(dev, i, 0x00);
+ //for (i = 1; i < 9; i++)
+ // set_vlan_ports(dev, i, 0x00);
return (0);
}
@@ -541,7 +569,7 @@
static int
bcm5325_vlan_write(struct bcm5325_switch_softc *sc, uint16_t vid,
- uint8_t tports, uint8_t uports)
+ uint32_t tports, uint32_t uports)
{
uint64_t reg;
int error = 0;
@@ -561,7 +589,7 @@
static int
bcm5325_vlan_read(struct bcm5325_switch_softc *sc, uint16_t vid,
- uint8_t *tports, uint8_t *uports)
+ uint32_t *tports, uint32_t *uports)
{
uint64_t reg;
int error = 0;
@@ -586,6 +614,69 @@
return (error);
}
+static int
+bcm5395_vlan_write(struct bcm5325_switch_softc *sc, uint16_t vid,
+ uint32_t tports, uint32_t uports)
+{
+ int error = 0;
+
+ error = WRITE(sc, VLAN_TABLE_ENTRY_5395,
+ (uports << VLAN_RW_UNTAG_SHIFT_5395) | tports);
+ if (error)
+ return (error);
+ error = WRITE(sc, VLAN_TABLE_INDX_5395, vid);
+ if (error)
+ return (error);
+ error = WRITE(sc, VLAN_TABLE_ACCESS_5395, VLAN_TABLE_ACCESS_5395_RUN);
+ if (error)
+ return (error);
+
+ return (error);
+}
+
+static int
+bcm5395_vlan_read(struct bcm5325_switch_softc *sc, uint16_t vid,
+ uint32_t *tports, uint32_t *uports)
+{
+ uint64_t reg, mask;
+ int error = 0;
+
+ error = WRITE(sc, VLAN_TABLE_INDX_5395, vid);
+ if (error)
+ return (error);
+ error = WRITE(sc, VLAN_TABLE_ACCESS_5395,
+ VLAN_TABLE_ACCESS_5395_RUN |VLAN_TABLE_ACCESS_5395_READ);
+ if (error)
+ return (error);
+
+ error = READ(sc, VLAN_TABLE_ENTRY_5395, ®);
+ if (error)
+ return (error);
+
+ mask = (1 << VLAN_RW_UNTAG_SHIFT_5395) - 1;
+ if (tports != NULL)
+ *tports = reg & mask;
+ if (uports != NULL)
+ *uports = (reg >> VLAN_RW_UNTAG_SHIFT_5395) & mask;
+
+ return (error);
+}
+
+static inline int
+bcmXXXX_vlan_write(struct bcm5325_switch_softc *sc, uint16_t vid,
+ uint32_t tports, uint32_t uports)
+{
+
+ return (sc->vlan_write(sc, vid, tports, uports));
+}
+
+static inline int
+bcmXXXX_vlan_read(struct bcm5325_switch_softc *sc, uint16_t vid,
+ uint32_t *tports, uint32_t *uports)
+{
+
+ return (sc->vlan_read(sc, vid, tports, uports));
+}
/*
* set_vid(dev, idx, vid)
* Define a VLAN, since BCM5325 family use only lower 4-8 bits of VID -
@@ -611,10 +702,10 @@
sc->base_vlan);
}
- error = bcm5325_vlan_read(sc, vid, NULL, NULL);
+ error = bcmXXXX_vlan_read(sc, vid, NULL, NULL);
if (error == ENOENT) {
/* Create empty valid VLAN port set */
- bcm5325_vlan_write(sc, vid, 0, 0);
+ bcmXXXX_vlan_write(sc, vid, 0, 0);
return (0);
}
@@ -638,7 +729,7 @@
set_vlan_ports(device_t dev, int idx, uint32_t memb)
{
struct bcm5325_switch_softc *sc = device_get_softc(dev);
- uint8_t umemb;
+ uint32_t umemb;
int error = 0;
printf("%s: idx=%d, memb=%08x\n", __func__, idx, memb);
@@ -648,8 +739,8 @@
if (memb & ~((1 << sc->ports) - 1))
return (EINVAL);
- bcm5325_vlan_read(sc, idx /* must be vid */, NULL, &umemb);
- error = bcm5325_vlan_write(sc, idx /* must be vid */, memb, umemb);
+ bcmXXXX_vlan_read(sc, idx /* must be vid */, NULL, &umemb);
+ error = bcmXXXX_vlan_write(sc, idx /* must be vid */, memb, umemb);
return (error);
}
@@ -658,13 +749,13 @@
get_vlan_ports(device_t dev, int idx, uint32_t *memb)
{
struct bcm5325_switch_softc *sc = device_get_softc(dev);
- uint8_t reg;
+ uint32_t reg;
int error;
if (idx > (sc->vlans - 1))
return (EINVAL);
- error = bcm5325_vlan_read(sc, idx /* must be vid */, ®, NULL);
+ error = bcmXXXX_vlan_read(sc, idx /* must be vid */, ®, NULL);
printf("%s: error=%d idx=%d, memb=%08x\n", __func__, error, idx, reg);
if (error == ENOENT) {
*memb = 0;
@@ -681,7 +772,7 @@
set_vlan_untagged_ports(device_t dev, int idx, uint32_t umemb)
{
struct bcm5325_switch_softc *sc = device_get_softc(dev);
- uint8_t memb;
+ uint32_t memb;
int error = 0;
printf("%s: idx=%d, memb=%08x\n", __func__, idx, umemb);
@@ -691,8 +782,8 @@
if (memb & ~((1 << sc->ports) - 1))
return (EINVAL);
- bcm5325_vlan_read(sc, idx /* must be vid */, &memb, NULL);
- error = bcm5325_vlan_write(sc, idx /* must be vid */, memb | umemb,
+ bcmXXXX_vlan_read(sc, idx /* must be vid */, &memb, NULL);
+ error = bcmXXXX_vlan_write(sc, idx /* must be vid */, memb | umemb,
umemb);
return (error);
@@ -702,13 +793,13 @@
get_vlan_untagged_ports(device_t dev, int idx, uint32_t *memb)
{
struct bcm5325_switch_softc *sc = device_get_softc(dev);
- uint8_t reg;
+ uint32_t reg;
int error;
if (idx > (sc->vlans - 1))
return (EINVAL);
- error = bcm5325_vlan_read(sc, idx /* must be vid */, NULL, ®);
+ error = bcmXXXX_vlan_read(sc, idx /* must be vid */, NULL, ®);
printf("%s: error=%d idx=%d, memb=%08x\n", __func__, error, idx, reg);
if (error == ENOENT) {
*memb = 0;
@@ -721,6 +812,94 @@
return (0);
}
+static int
+pbvlan_setports(device_t dev, int port, uint32_t allowed)
+{
+ struct bcm5325_switch_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ if (port > (sc->ports - 1))
+ return (EINVAL);
+
+ error = WRITE(sc, PBVLAN_ALLOWED_PORTS(port), allowed);
+ if (error)
+ return (error);
+
+ return (0);
+}
+
+static int
+pbvlan_getports(device_t dev, int port, uint32_t *allowed)
+{
+ struct bcm5325_switch_softc *sc;
+ uint64_t reg;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ if (port > (sc->ports - 1))
+ return (EINVAL);
+
+ error = READ(sc, PBVLAN_ALLOWED_PORTS(port), ®);
+ if (error)
+ return (error);
+
+ *allowed = (uint32_t)reg;
+ return (0);
+}
+
+static int
+reset_subsys(device_t dev, int subsys)
+{
+ struct bcm5325_switch_softc *sc;
+ int error, port;
+
+ sc = device_get_softc(dev);
+ error = 0;
+ switch (subsys & SWITCH_RESETSUB_MASK) {
+ case SWITCH_RESETSUB_SWITCH:
+// error = WRITE(sc, SWITCH_RESET, 0x90);
+ /* XXX: Hope it will reset any switch */
+ error = WRITE(sc, SWITCH_RESET, 0xffff);
+ if (error)
+ return (error);
+
+ pause("eswrst", hz/100);
+
+ error = WRITE(sc, SWITCH_RESET, 0x00);
+ if (error)
+ return (error);
+ break;
+ case SWITCH_RESETSUB_PORT:
+ if ((subsys & SWITCH_RESETSUB_PORT_MASK) ==
+ SWITCH_RESETSUB_ALLPORTS) {
+ /* Reset all PHYs */
+#ifdef notyet
+ for (port = 0; port < sc->ports; port ++)
+ reset_port(sc, port);
+#endif
+ } else {
+ /* Reset syngle PHY */
+ port = (subsys & SWITCH_RESETSUB_PORT_MASK) >>
+ SWITCH_RESETSUB_PORT_SHIFT;
+#ifdef notyet
+ reset_port(sc, port);
+#endif
+ }
+ break;
+ case SWITCH_RESETSUB_VLANS:
+ /* TODO */
+ break;
+ case SWITCH_RESETSUB_QOS:
+ /* TODO */
+ break;
+ }
+
+ return (error);
+}
+
static device_method_t bcm5325_switch_methods[] = {
DEVMETHOD(device_probe, bcm5325_switch_probe),
DEVMETHOD(device_attach, bcm5325_switch_attach),
@@ -730,6 +909,7 @@
DEVMETHOD(switch_get_caps, get_caps),
DEVMETHOD(switch_set_reg, set_reg),
DEVMETHOD(switch_get_reg, get_reg),
+ DEVMETHOD(switch_reset_subsys, reset_subsys),
/* MAC address table */
DEVMETHOD(switch_find_mac, find_mac_addr),
@@ -747,6 +927,10 @@
DEVMETHOD(switch_set_vlanutports, set_vlan_untagged_ports),
DEVMETHOD(switch_get_vlanutports, get_vlan_untagged_ports),
+ /* Port based VLAN */
+ DEVMETHOD(switch_pbvlan_getports, pbvlan_getports),
+ DEVMETHOD(switch_pbvlan_setports, pbvlan_setports),
+
{0, 0},
};
diff -r 7142a751aca2 -r 3c0fed8eac60 head/sys/dev/switch/bcm5325_switchreg.h
--- a/head/sys/dev/switch/bcm5325_switchreg.h Fri Feb 03 17:30:35 2012 +0200
+++ b/head/sys/dev/switch/bcm5325_switchreg.h Fri Feb 03 17:31:23 2012 +0200
@@ -97,6 +97,7 @@
#define SWITCH_MODE_MANAGED 0x01
#define PORTMII_STATUS_OVERRIDE (S1 | PAGE(0x00) | 0x0e)
+#define PORTMII_STATUS_FORCE_1000M 0x80 /* it is force? */
#define PORTMII_STATUS_REVERSE_MII 0x10
#define PORTMII_STATUS_PAUSE_CAPABLE 0x08
#define PORTMII_STATUS_FORCE_100M 0x04
@@ -178,7 +179,7 @@
#define IGMP_CPU_FWD_CTL (S1 | PAGE(0x02) | 0x26)
#define IGMP_REPLACE_DA (S6 | PAGE(0x02) | 0x27)
-#define SWITCH_DEVICEID (S2 | PAGE(0x02) | 0x30)
+#define SWITCH_DEVICEID (S4 | PAGE(0x02) | 0x30)
#define MIB_AUTOCAST_PORT (S2 | PAGE(0x03) | 0x00)
#define MIB_AUTOCAST_HDR_PNTR (S2 | PAGE(0x03) | 0x02)
@@ -265,7 +266,6 @@
#define QUEUE4_CTL_3 (S2 | PAGE(0x0A) | 0x86)
#define QUEUE4_CTL_4 (S2 | PAGE(0x0A) | 0x88)
-
/* Standard MII
PRT = PAGE10 + port
Page PRT, Address 00h-01h Switch Port Control Register
@@ -360,14 +360,8 @@
#define DIFFSERV_DSCP_PRIORITYH (S8 | PAGE(0x30) | 0x38)
#define DSCP_TO_QUEUE(_d, _q) ((_q) << (((_d) & 0x3f) * 2))
-/* BCM5395/5397/5398/53115 */
-#define ROBO_VTBL_ACCESS 0x60 /* VLAN table access: 8bit */
-#define ROBO_VTBL_INDX 0x61 /* VLAN table address index: 16bit */
-#define ROBO_VTBL_ENTRY 0x63 /* VLAN table entry: 32bit */
-#define ROBO_VTBL_ACCESS_5395 0x80 /* VLAN table access: 8bit */
-#define ROBO_VTBL_INDX_5395 0x81 /* VLAN table address index: 16bit */
-#define ROBO_VTBL_ENTRY_5395 0x83 /* VLAN table entry: 32bit */
-
+/* PAGE31, Port Based VLAN */
+#define PBVLAN_ALLOWED_PORTS(_p) (S2 | PAGE(0x31) | ((_p) * 2))
#define VLAN_GLOBAL_CTL0 (S1 | PAGE(0x34) | 0x00)
#define VLAN_GLOBAL_CTL0_1Q_ENABLE 0x80
@@ -399,12 +393,22 @@
#define VLAN_ID_MAX5350 15
#define VLAN_ID_MAX5395 4094
+#define VLAN_TABLE_ACCESS_5350 (S1 | PAGE(0x05) | 0x60)
+#define VLAN_TABLE_INDX_5350 (S2 | PAGE(0x05) | 0x61)
+#define VLAN_TABLE_ENTRY_5350 (S4 | PAGE(0x05) | 0x63)
+/* BCM5395/5397/5398/53115/53118 */
+#define VLAN_TABLE_ACCESS_5395 (S1 | PAGE(0x05) | 0x80)
+#define VLAN_TABLE_ACCESS_5395_RUN 0x80
+#define VLAN_TABLE_ACCESS_5395_READ 0x01
+#define VLAN_TABLE_INDX_5395 (S1 | PAGE(0x05) | 0x81)
+#define VLAN_TABLE_ENTRY_5395 (S4 | PAGE(0x05) | 0x83)
/* XXX: Valid for BCM535x */
#define VLAN_WRITE (S4 | PAGE(0x34) | 0x08)
#define VLAN_RW_VALID_5350 0x00100000
#define VLAN_RW_VALID_5380 0x04000000
#define VLAN_RW_VALID 0x4000
+#define VLAN_RW_UNTAG_SHIFT_5395 9
#define VLAN_RW_UNTAG_SHIFT_5380 13
#define VLAN_RW_UNTAG_SHIFT_5350 6
#define VLAN_RW_UNTAG_SHIFT 7
@@ -421,7 +425,6 @@
#define VLAN_PRIORITY_REMAP (S3 | PAGE(0x34) | 0x20)
#define VLAN_PRIORITY_REMAP_OLD_NEW(_o, _n) ((_n) << ((_o) * 3))
-
#define PORT_SUPPRESSION_CTL (S1 | PAGE(0x35) | (0x00 + (_p)))
#define PORT_SUPPRESSION_CTL_HAS_DROPS 0x80
#define PORT_SUPPRESSION_CTL_PASS_MCAST 0x40
diff -r 7142a751aca2 -r 3c0fed8eac60 head/sys/dev/switch/bcm5325_switchvar.h
--- a/head/sys/dev/switch/bcm5325_switchvar.h Fri Feb 03 17:30:35 2012 +0200
+++ b/head/sys/dev/switch/bcm5325_switchvar.h Fri Feb 03 17:31:23 2012 +0200
@@ -32,7 +32,7 @@
struct bcm5325_switch_softc {
device_t sc_dev;
device_t parent;
- device_t new_mii;
+ device_t new_mii; /* Unused */
int ports;
int vlans;
uint16_t base_vlan;
@@ -40,8 +40,12 @@
int page_reg;
int page_phy;
int devid;
- int mode;
+ int mode; /* Unused */
uint32_t sc_mii_mode;
+ int (*vlan_write) (struct bcm5325_switch_softc *, uint16_t,
+ uint32_t, uint32_t);
+ int (*vlan_read) (struct bcm5325_switch_softc *, uint16_t,
+ uint32_t *, uint32_t *);
};
#define MII_SW_READ4(_sc, _reg) \
More information about the Zrouter-src-freebsd
mailing list