From 4cef63200ff749a9c5545ef3292d0b971fa1d457 Mon Sep 17 00:00:00 2001 From: "Mark H. Spatz" Date: Sat, 7 Mar 2026 14:48:04 -0500 Subject: [PATCH 1/4] Fix "Get Configuration" on vlan.html I noticed that entering some vlan config, clicking "Update/Create", then clicking "Get Configuration" resulted in Tagged/Untagged/PVID displaying completely wrong data. It looks like the parisng in fetchVLAN() in vlan.js was just completely disconnected from the layout of the registers read by vlan_get() in rtl837x_port.c. Who knows how that happened. 1. Fix fetchVLAN() member/untag parsing: the old code read bits [9:0] as untagged and bits [10:19] as tagged, but the VLAN table register layout is members in [9:0] and untag in [19:10]. Now correctly derives tagged (member && !untag) and untagged (member && untag). 2. Add PVID to vlan.json response: PVID is stored per-port in separate PVID registers (RTL837x_PVID_BASE_REG), not in the VLAN table entry. The old code nonsensically tried to read it from bits [20:29] of the VLAN table. Add port_pvid_get() and build a pvid bitmask in send_vlan() so the JS can parse it correctly. 3. Remove auto-PVID logic from setC(): setC() is called by fetchVLAN() while it's loading existing config, and so this logic mangled the display of the existing config. Also, it doesn't make sense to auto-set the PVID for tagged members (PVID relates to untagged ingress.) --- html/vlan.js | 17 +++++++++-------- httpd/page_impl.c | 8 ++++++++ rtl837x_port.c | 11 +++++++++++ rtl837x_port.h | 1 + 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/html/vlan.js b/html/vlan.js index d783534..8a2c3b1 100644 --- a/html/vlan.js +++ b/html/vlan.js @@ -39,11 +39,6 @@ function vlanForm() { function setC(t, p, c){ document.getElementById(t+'port'+p).checked=c; - // When a tagged port is checked, automatically select the PVID port as well - const tportElem = document.getElementById('tport'+p); - if (tportElem && tportElem.checked) { - document.getElementById('pport'+p).checked=true; - } } function utClicked(t){ @@ -70,10 +65,16 @@ function fetchVLAN() { console.log("VLAN: ", JSON.stringify(s)); m = parseInt(s.members, 16); document.getElementById('vname').value = s.name; + var members = m & 0x3FF; + var untag = (m >> 10) & 0x3FF; + var pvid = parseInt(s.pvid, 16); for (let i = 1; i <= numPorts; i++) { - setC('t', i, (m>>(10+i-1))&1); - setC('u', i, (m>>(i-1))&1); - setC('p', i, (m>>(20+i-1))&1); + var bit = i - 1; + var isMember = (members >> bit) & 1; + var isUntag = (untag >> bit) & 1; + setC('t', i, isMember && !isUntag); + setC('u', i, isMember && isUntag); + setC('p', i, (pvid >> bit) & 1); } } }; diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 9769311..0618758 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -270,6 +270,14 @@ void send_vlan(uint16_t vlan) while(vlan_names[n] && vlan_names[n] != ' ') char_to_html(vlan_names[n++]); } + slen += strtox(outbuf + slen, "\",\"pvid\":\"0x"); + uint16_t pvid_mask = 0; + for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + if (port_pvid_get(i) == vlan) + pvid_mask |= (1 << i); +} + byte_to_html(pvid_mask >> 8); + byte_to_html(pvid_mask); slen += strtox(outbuf + slen, "\"}"); } diff --git a/rtl837x_port.c b/rtl837x_port.c index 4e12a6d..1a28c69 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -78,6 +78,17 @@ void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked } } +uint16_t port_pvid_get(uint8_t port) __banked +{ + uint16_t reg = RTL837x_PVID_BASE_REG + ((port >> 1) << 2); + reg_read_m(reg); + if (port & 0x1) { + return (sfr_data[1] << 4) | (sfr_data[2] >> 4); + } else { + return ((sfr_data[2] & 0x0f) << 8) | sfr_data[3]; + } +} + void vlan_delete(uint16_t vlan) __banked { diff --git a/rtl837x_port.h b/rtl837x_port.h index 480f2e8..60e2282 100644 --- a/rtl837x_port.h +++ b/rtl837x_port.h @@ -28,6 +28,7 @@ int8_t vlan_get(register uint16_t vlan) __banked; __xdata uint16_t vlan_name(register uint16_t vlan) __banked; void vlan_setup(void) __banked; void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked; +uint16_t port_pvid_get(uint8_t port) __banked; void vlan_create(void) __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; From 364d538abd30747cee0bf43f9665b31dd751e64e Mon Sep 17 00:00:00 2001 From: "Mark H. Spatz" Date: Sun, 8 Mar 2026 17:50:54 -0400 Subject: [PATCH 2/4] Fix "VLAN ID" field max value on vlan.html --- html/vlan.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html/vlan.html b/html/vlan.html index 133b84c..7962776 100644 --- a/html/vlan.html +++ b/html/vlan.html @@ -12,7 +12,7 @@
- +


From 16f4e2a1c6445e0cd89adbc4aa6d1a316aff2a3f Mon Sep 17 00:00:00 2001 From: "Mark H. Spatz" Date: Sun, 8 Mar 2026 17:52:39 -0400 Subject: [PATCH 3/4] Fix range check in vlan_get() --- rtl837x_port.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtl837x_port.c b/rtl837x_port.c index 1a28c69..79b396e 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -104,7 +104,7 @@ void vlan_delete(uint16_t vlan) __banked */ int8_t vlan_get(register uint16_t vlan) __banked { - if (vlan >= 0x3ff) // VLAN 4095 is special + if (vlan >= 0xfff) // VLAN 4095 is special return -1; REG_WRITE(RTL837X_TBL_CTRL, vlan >> 8, vlan, TBL_VLAN, TBL_EXECUTE); From 893dcd8fcfa41eeb51a046598f8789c8e3bdfdff Mon Sep 17 00:00:00 2001 From: "Mark H. Spatz" Date: Sun, 8 Mar 2026 19:49:37 -0400 Subject: [PATCH 4/4] update vlan.md --- doc/vlan.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/vlan.md b/doc/vlan.md index a74dcf8..1d3004b 100644 --- a/doc/vlan.md +++ b/doc/vlan.md @@ -33,8 +33,8 @@ 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 +register of the port. 2 ports share a register. An odd port uses bits [23:12], +an even port uses bits [11:0]. 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. @@ -51,7 +51,9 @@ registers 0x1238, 0x1338, ... 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; +uint16_t port_pvid_get(uint8_t port) __banked; +void vlan_create(void) __banked; // reads from global vlan_settings +int8_t vlan_get(register uint16_t vlan) __banked; // returns data in sfr_data void vlan_delete(uint16_t vlan) __banked; ```