From fcd1f85eb65867806aac919e72b3a8c5ec6d061d Mon Sep 17 00:00:00 2001 From: logicog Date: Fri, 25 Jul 2025 22:50:27 +0200 Subject: [PATCH] Add trunking support and initial L2 setup --- rtl837x_port.c | 174 +++++++++++++++++++++++++++++++++---------------- rtl837x_port.h | 3 + rtl837x_regs.h | 9 +++ 3 files changed, 130 insertions(+), 56 deletions(-) diff --git a/rtl837x_port.c b/rtl837x_port.c index 0d1a7aa..5cafa52 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -21,12 +21,14 @@ extern __xdata uint8_t nSFPPorts; extern __xdata uint8_t sfr_data[4]; extern __xdata uint8_t cpuPort; +extern __xdata uint8_t isRTL8373; + __xdata uint32_t l2_head; void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked { - print_string("\r\nport_mirror_set called \r\n"); + print_string("\nport_mirror_set called \n"); REG_WRITE(RTL837x_MIRROR_CONF, rx_pmask >> 8, rx_pmask, tx_pmask >> 8, tx_pmask); REG_WRITE(RTL837x_MIRROR_CTRL, 0, 0, 0, (port << 1) | 0x1); @@ -35,15 +37,33 @@ void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata u void port_mirror_del(void) __banked { - print_string("\r\nport_mirror_del called \r\n"); + print_string("\nport_mirror_del called \n"); REG_SET(RTL837x_MIRROR_CTRL, 0); } +void port_ingress_filter(register uint8_t port, uint8_t type) __banked +{ + if (type & 0x1) + reg_bit_set(RTL837x_REG_INGRESS, port << 1); + else + reg_bit_clear(RTL837x_REG_INGRESS, port << 1); + if (type & 0x2) + reg_bit_set(RTL837x_REG_INGRESS, (port << 1) + 1); + else + reg_bit_clear(RTL837x_REG_INGRESS, (port << 1) + 1); +} + + +/* +pvid 6 2 2 +port_pvid_set called +R4e28-00001002 +*/ void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked { // r4e1c:00001001 R4e1c-000017d0 r6738:00000000 R6738-00000000 (no filtering) - print_string("\r\nport_pvid_set called \r\n"); + print_string("\nport_pvid_set called \n"); uint16_t reg = RTL837x_PVID_BASE_REG + ((port >> 1) << 2); reg_read_m(reg); @@ -57,7 +77,7 @@ void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked void vlan_delete(uint16_t vlan) __banked { - print_string("\r\nvlan_delete called \r\n"); print_short(vlan); + print_string("\nvlan_delete called \n"); print_short(vlan); // R5cac-07d30301 r5cac:07d30300 } @@ -67,39 +87,27 @@ void vlan_delete(uint16_t vlan) __banked */ void vlan_create(register uint16_t vlan, register uint16_t members, register uint16_t tagged) __banked { - /* First line: - 7-9: Untagged: 1-1, Not-Member: 1-0 - 0111111111 - 1111000000 - 9 port 0 + // For now, the CPU-port is always a tagged member: + members |= 0x0200; // Set 10th bit + tagged |= 0x0200; + print_string("\nvlan_create called\nvlan: "); print_short(vlan); + print_string(", members: "); print_short(members); + print_string(", tagged: "); print_short(tagged); write_char('\n'); - 1-3: Untagged: 1-1 - 0111111111 - 1000000111 + uint16_t a = (~members) ^ tagged ^ members; + // On RTL8372, port-bits 0-2 must be 0, although they are not members + if (!isRTL8373) { + a &= 0x1f8; + tagged &= 0x3f8; + } - 1-3: Tagged: 0-1 - 0111111000 - 1000000111 - - 7-9: Tagged: 0-1 - 0000111111 - 1111000000 - In 1-0 -> 1-1 FIRST Bit: XOR, Second bit stays - In 1-1 -> 0-1 - In 0-1 // Not allowed - In 0-0 -> 1-0 - */ - // R5cb8-02 07e207 R5cac-07d20303 - print_string("\r\nvlan_create called: "); print_short(vlan); write_char(' '); print_short(members); write_char(':'); print_short(tagged); - - uint16_t a = members ^ tagged; // Initialize VLAN table with VLAN 1 - REG_WRITE(RTL837x_TBL_DATA_IN_A, 0x02, (a >> 6) & 0x0f, (a << 2) | (tagged >> 8), tagged); + REG_WRITE(RTL837x_TBL_DATA_IN_A, 0x02, (a >> 6) & 0x0f, (a << 2) | (members >> 8), members); REG_WRITE(RTL837X_TBL_CTRL, vlan >> 8, vlan, TBL_VLAN, TBL_WRITE | TBL_EXECUTE); do { reg_read_m(RTL837X_TBL_CTRL); } while (sfr_data[3] & TBL_EXECUTE); - print_string("\r\nvlan_create done \r\n"); + print_string("\nvlan_create done \n"); } @@ -112,22 +120,25 @@ void vlan_create(register uint16_t vlan, register uint16_t members, register uin */ void vlan_setup(void) __banked { - print_string("\r\nvlan_setup called \r\n"); + print_string("\nvlan_setup called \n"); - // Initialize VLAN table with VLAN 1 - REG_SET(RTL837x_TBL_DATA_IN_A, 0x0007ffff); + // Initialize VLAN table for VLAN 1, by disabling that entry + if (isRTL8373) { + REG_SET(RTL837x_TBL_DATA_IN_A, 0x0007ffff); + } else { + REG_SET(RTL837x_TBL_DATA_IN_A, 0x0007e3f8); + } REG_SET(RTL837X_TBL_CTRL, 0x00010303); do { reg_read_m(RTL837X_TBL_CTRL); } while (sfr_data[3] & TBL_EXECUTE); // Set PVID 1 for every port. TODO: Skip unused ports! - for (uint8_t i = minPort; i <= maxPort + 1; i++) { // Do this also for the CPU port (+1) + for (uint8_t i = minPort; i <= maxPort + 1; i++) { // Do this also for the CPU port (+1) uint16_t reg = RTL837x_PVID_BASE_REG + ((i >> 1) << 2); #ifdef DEBUG - print_byte(i); write_char(':'); write_char(' '); - print_short(reg); write_char(' '); write_char('B'); write_char('>'); - print_sfr_data(); + print_byte(i); write_char(':'); write_char(' '); print_short(reg); write_char('='); + print_short(reg); write_char(' '); #endif reg_read_m(reg); if (i & 0x1) { @@ -143,39 +154,61 @@ void vlan_setup(void) __banked // EGRESS filtering for port: removal of additional VLAN tag reg_bit_clear(0x6738, i << 1); reg_bit_clear(0x6738, (i << 1) + 1); - if (i != cpuPort) - reg_bit_set(0x4e18, i); - else - reg_bit_clear(0x4e18, i); + reg_bit_set(0x4e18, i); + #ifdef DEBUG - print_string("\r\n"); + print_string("\n"); #endif } + + // Ingress filtering. 2 bits per port: allow tagged (01) / untagged (10) and all (00) + REG_SET(RTL837x_REG_INGRESS, 0); // No filtering for all ports + // Enable 4k VLAN REG_SET(0x4e14, 4); REG_SET(0x4e30, 0); REG_SET(0x4e34, 0); // Enable VLAN 1: Ports 0-9, i.e. including the CPU port are untagged members - REG_SET(RTL837x_TBL_DATA_IN_A, 0x0207ffff); // 02: Entry valid, 7ffff: membership + if (isRTL8373) { + REG_SET(RTL837x_TBL_DATA_IN_A, 0x0207ffff); // 02: Entry valid, 7ffff: membership + } else { + REG_SET(RTL837x_TBL_DATA_IN_A, 0x0207e3f8); + } REG_SET(RTL837X_TBL_CTRL, 0x00010303); // Write VLAN 1 do { reg_read_m(RTL837X_TBL_CTRL); } while (sfr_data[3] & TBL_EXECUTE); // Configure trunking - REG_SET(0x4f4c, 0x0000007e); + if (isRTL8373) { + REG_SET(0x4f4c, 0x0000007e); // Removes RTL VLAN-Tags + REG_SET(0x4f48, 0x0000007e); // Adds 802.1Q VLAN-Tags to tagged ports + } #ifdef DEBUG - print_string("\r\nvlan_setup, REG 0x6738: "); print_reg(0x6738); - print_string("\r\nvlan_setup, REG 0x4e18: "); print_reg(0x4e18); - print_string("\r\nvlan_setup, REG 0x4e14: "); print_reg(0x4e14); - print_string("\r\nvlan_setup, REG 0x4e30: "); print_reg(0x4e30); - print_string("\r\nvlan_setup, REG 0x4e34: "); print_reg(0x4e34); - print_string("\r\nvlan_setup, REG 0x4f4c: "); print_reg(0x4f4c); + print_string("\nvlan_setup, REG 0x6738: "); print_reg(0x6738); + print_string("\nvlan_setup, REG 0x4e18: "); print_reg(0x4e18); + print_string("\nvlan_setup, REG 0x4e14: "); print_reg(0x4e14); + print_string("\nvlan_setup, REG 0x4e30: "); print_reg(0x4e30); + print_string("\nvlan_setup, REG 0x4e34: "); print_reg(0x4e34); + print_string("\nvlan_setup, REG 0x4f48: "); print_reg(0x4f48); + print_string("\nvlan_setup, REG 0x4f4c: "); print_reg(0x4f4c); #endif - print_string("\r\nvlan_setup done \r\n"); + print_string("\nvlan_setup done \n"); +} + + +void trunk_set(uint8_t group, uint16_t mask) __banked +{ + if (group == 1) { + REG_WRITE(0x4f38, 0, 0, mask >> 8, mask); + } else if (group == 2) { + REG_WRITE(0x4f3c, 0, 0, mask >> 8, mask); + } else { + print_string("\nTrunk group must be 1 or 2\n"); + } } @@ -187,7 +220,7 @@ uint8_t port_l2_forget(void) __banked // r53dc:00000000 R53dc-00000000 r53d4:000001ff r53d4:000001ff R53d4-000101ff r53d4:000001ff reg_read_m(0x53dc); if (sfr_data[0] || sfr_data[1] ||sfr_data[2] ||sfr_data[3]) { - print_string("List busy\r\n"); + print_string("List busy\n"); return -1; } REG_WRITE(0x53dc, sfr_data[0], sfr_data[1], sfr_data[2], sfr_data[3]); @@ -208,7 +241,7 @@ void port_l2_learned(void) __banked do { reg_read_m(RTL837X_TBL_CTRL); } while (sfr_data[3] & 0x01); - print_string("\r\n\tMAC\t\tVLAN\ttype\tport\r\n"); + print_string("\n\tMAC\t\tVLAN\ttype\tport\n"); __xdata uint16_t entry = 0x0000; __xdata uint16_t first_entry = 0xffff; // Table does not have that many entries @@ -264,14 +297,43 @@ void port_l2_learned(void) __banked write_char(' '); print_sfr_data(); write_char(' '); print_byte(other); #endif - print_string("\r\n"); + print_string("\n"); } } +/* + * Basic L2 configuration such as time to forget an entry + */ +void port_l2_setup() __banked +{ + print_string("\nport_l2_setup called\n"); + REG_SET(0x53dc, 0x00000000); + if(isRTL8373) { + REG_SET(0x53d4, 0x000101ff); + } else { + REG_SET(0x53d4, 0x000001f8); + } + for (uint8_t i = minPort; i <= maxPort; i++) { + uint16_t reg = 0x5384 + (i << 2); + REG_SET(reg, 0x00001040); + + reg = 0x50c0 + (i << 2); + if(isRTL8373) { + REG_SET(reg, 0x3ff); + } else { + REG_SET(reg, 0x3f8); + } + } + reg_bit_set(0x4f80, 0); + + print_string("\nport_l2_setup done\n"); +} + + void port_stats_print(void) __banked { - print_string("\r\n Port\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\r\n"); + print_string("\n Port\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\n"); for (uint8_t i = minPort; i <= maxPort; i++) { write_char('1' + i); write_char('\t'); phy_read(i, 0x1f, 0xa610); // p001f.a610:2058 @@ -344,6 +406,6 @@ void port_stats_print(void) __banked reg_read_m(RTL837X_STAT_GET); } while (sfr_data[3] & 0x1); print_reg(RTL837X_STAT_V_LOW); write_char('\t'); - print_string("\r\n"); + print_string("\n"); } } diff --git a/rtl837x_port.h b/rtl837x_port.h index 3657363..b968d98 100644 --- a/rtl837x_port.h +++ b/rtl837x_port.h @@ -10,4 +10,7 @@ void vlan_create(uint16_t vlan, uint16_t members, uint16_t tagged) __banked; void vlan_delete(uint16_t vlan) __banked; void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked; void port_mirror_del(void) __banked; +void port_ingress_filter(register uint8_t port, uint8_t type) __banked; +void port_l2_setup() __banked; +void trunk_set(uint8_t group, uint16_t mask) __banked; #endif diff --git a/rtl837x_regs.h b/rtl837x_regs.h index 857b7c3..7acfd82 100644 --- a/rtl837x_regs.h +++ b/rtl837x_regs.h @@ -98,6 +98,15 @@ #define RTL837x_L2_TBL_CTRL 0x53d4 #define RTL837x_PVID_BASE_REG 0x4e1c +/* + * Egress / ingress filtering + */ +// 2 bits per port: allow tagged (01) / untagged (10) and all (00) +#define RTL837x_REG_INGRESS 0x4e10 +#define INGR_ALLOW_TAGGED 1 +#define INGR_ALLOW_UNTAGGED 2 +#define INGR_ALLOW_ALL 0 + /* * Mirroring */