diff --git a/README.md b/README.md index 6ff2e12..3d13e6a 100644 --- a/README.md +++ b/README.md @@ -303,3 +303,13 @@ Lightron Inc. WSPXG-ES3LC-IHA 0000 ``` Enjoy playing! + +## Other documents +The following documents give further documentation on specific features of +the RTL837x SoCs: +- [CPU Port](doc/CpuPort.md) +- [L2 learning](doc/l2.md) +- [Mirroring](doc/mirroring.md) +- [SFP+ ports](doc/sfp.md) +- [Trunking aka. port aggregation](doc/trunking.md) +- [VLAN](doc/vlan.md) \ No newline at end of file diff --git a/doc/trunking.md b/doc/trunking.md new file mode 100644 index 0000000..948f533 --- /dev/null +++ b/doc/trunking.md @@ -0,0 +1,25 @@ +# Trunking + +The RTL827x allows to combine multiple ports to a single logical port +(trunking). Up to 2 trunk groups can be defined. + +## Trunking control +Two registers RTL837x_TRUNK_CTRL_A (0x4f38) and RTL837x_TRUNK_CTRL_B (0x4f3c) +define the trunk groups. Each holds a bitmap of ports making up the trunk +group. + +## Trunking API +The code currently provides the following functions: +``` +void trunk_set(uint8_t group, uint16_t mask) __banked +``` + +# VLAN configuration on the Serial Console +For testing the following commands are provided on the serial console: +``` +trunk [p1] [p2]... + create or set a trunk group. Trunk-ID is 1 or 2. ports a physical ports + +trunk d + deletes the trunk group +``` diff --git a/doc/vlan.md b/doc/vlan.md new file mode 100644 index 0000000..a74dcf8 --- /dev/null +++ b/doc/vlan.md @@ -0,0 +1,74 @@ +# VLAN + +The RTL827x provides support for up to 4096 802.1Q VLANs, each port can be +assigend a PVID. + +## VLAN control +VLANs are controlled by the VLAN table. Configuration of entries is done as +for the L2 entries, apart from that the ASIC does not add entries by itself. + +Adding a VLAN entry is done by setting: + +``` +RTL837x_TBL_DATA_IN_A = 02 0v vv vv +``` +where 0x02 designates a valid entry and vvvvv is a 20bit field made of lower 10bits designating whether a +port is a member of a VLAN. The higher 10 bits are '0' for tagged ports +and '1' for untagged ports (the bit-logic definition is `v = (~members) ^ tagged ^ +members`). Ports are numbered 0-9, 9 being the CPU-port. Note that for +the RTL8372 devices, the ports are not in their physical order. + +Once RTL837x_TBL_DATA_IN_A is set, the entry is added to the table by: + +``` +RTL837X_TBL_CTRL = 0V VV TT CC +CC: TBL_WRITE | TBL_EXECUTE +VVV: VLAN-Id +TT: 0x02 (TBL_VLAN) +CC: 0x03 (TBL_WRITE | TBL_EXECUTE) +``` +The ASIC will clear bit 0 once the entry has been added. + +An entry is deleted by adding an invalid entry (00 instead of 0x02 in +RTL837x_TBL_DATA_IN_A). + +A port is assigned a PVID by setting the PVID-bits of the corresponding +register of the port. 2 ports share a register. One port uses the higher +16 bits, the other (even ports) use the lower. The base register is +RTL837x_PVID_BASE_REG (0x4e1c) and the registers go to 0x4e2c so that also +the CPU-Port may have a PVID. + +Register RTL837x_REG_INGRESS (0x4e10) allows to define the iingress rules of +a port. 2 bits define a rule and bits 0-19 are being used. A value of 00 +defines no filtering, 01 (0x01) allows only tagged packets, while 10 (0x02) +allows only untagged packets to enter a port. The default PVID is 1. + +By default, the ports transmit Ethernet frames with Realtek's proprietary +tag format. By setting bit 6 (0x40) of the respective port configuration +registers 0x1238, 0x1338, ... + +## VLAN API +The code currently provides the following functions: +``` +void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked; +void vlan_create(uint16_t vlan, uint16_t members, uint16_t tagged) __banked; +void vlan_delete(uint16_t vlan) __banked; + +``` + +# VLAN configuration on the Serial Console +For testing the following commands are provided on the serial console: +``` +vlan p[t/u]... + create or set vlan with given ID and the list of ports as members, a t + behind a port defines the port as a tagged member, the u is optional + +vlan d + deletes the VLAN + +pvid + assigns PVID to a port. ports are numbered as on the casing + +ingress [tagged|untagged|all] + Allows ingress only for the named packages at the given port +``` diff --git a/rtl837x_port.c b/rtl837x_port.c index 5cafa52..a7dd395 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -56,9 +56,7 @@ void port_ingress_filter(register uint8_t port, uint8_t type) __banked /* -pvid 6 2 2 -port_pvid_set called -R4e28-00001002 + * Define a Primary VLAN ID for a port */ void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked { @@ -78,7 +76,8 @@ void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked void vlan_delete(uint16_t vlan) __banked { print_string("\nvlan_delete called \n"); print_short(vlan); - // R5cac-07d30301 r5cac:07d30300 + REG_WRITE(RTL837x_TBL_DATA_IN_A, 0, 0, 0, 0); + REG_WRITE(RTL837X_TBL_CTRL, vlan >> 8, vlan, TBL_VLAN, TBL_WRITE | TBL_EXECUTE); } @@ -203,9 +202,9 @@ void vlan_setup(void) __banked void trunk_set(uint8_t group, uint16_t mask) __banked { if (group == 1) { - REG_WRITE(0x4f38, 0, 0, mask >> 8, mask); + REG_WRITE(RTL837x_TRUNK_CTRL_A, 0, 0, mask >> 8, mask); } else if (group == 2) { - REG_WRITE(0x4f3c, 0, 0, mask >> 8, mask); + REG_WRITE(RTL837x_TRUNK_CTRL_B, 0, 0, mask >> 8, mask); } else { print_string("\nTrunk group must be 1 or 2\n"); } diff --git a/rtl837x_regs.h b/rtl837x_regs.h index 7acfd82..3e172fe 100644 --- a/rtl837x_regs.h +++ b/rtl837x_regs.h @@ -113,6 +113,12 @@ #define RTL837x_MIRROR_CONF 0x604c #define RTL837x_MIRROR_CTRL 0x6048 +/* + * Trunking + */ +#define RTL837x_TRUNK_CTRL_A 0x4f38 +#define RTL837x_TRUNK_CTRL_B 0x4f3c + #ifdef REGDBG #define REG_SET(r, v) SFR_DATA_24 = ((v) >> 24) & 0xff; \