From 32b55396708a926d68a77f4cdfb67b1df6ed0d10 Mon Sep 17 00:00:00 2001 From: logicog Date: Tue, 4 Nov 2025 18:54:45 +0100 Subject: [PATCH 01/20] Do not show non-ascii Transceiver field in SFP module description --- cmd_parser.c | 17 +++++++++-------- rtl837x_common.h | 1 + rtlplayground.c | 3 +++ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/cmd_parser.c b/cmd_parser.c index 3794f2e..8c0e099 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -627,18 +627,19 @@ void cmd_parser(void) __banked print_string("\nRESET\n\n"); reset_chip(); } else if (cmd_compare(0, "sfp")) { - uint8_t rate = sfp_read_reg(0, 12); - print_string("\nRate: "); print_byte(rate); + print_string("\nSlot 0 - Rate: "); print_byte(sfp_read_reg(0, 12)); print_string(" Encoding: "); print_byte(sfp_read_reg(0, 11)); print_string("\n"); - for (uint8_t i = 20; i < 60; i++) { - uint8_t c = sfp_read_reg(0, i); - if (c) - write_char(c); - } + sfp_print_info(0); +#if NSFP == 2 + print_string("\nSlot 1 - Rate: "); print_byte(sfp_read_reg(1, 12)); + print_string(" Encoding: "); print_byte(sfp_read_reg(1, 11)); + print_string("\n"); + sfp_print_info(1); +#endif } else if (cmd_compare(0, "stat")) { port_stats_print(); - } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'r') { + } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'r') { print_string("\nPRINT SECURITY REGISTERS\n"); // The following will only show something else than 0xff if it was programmed for a managed switch flash_region.addr = 0x0001000; diff --git a/rtl837x_common.h b/rtl837x_common.h index 06e4a23..5377eb2 100644 --- a/rtl837x_common.h +++ b/rtl837x_common.h @@ -106,5 +106,6 @@ void print_string_x(__xdata char *p); uint8_t read_flash(uint8_t bank, __code uint8_t *addr); void get_random_32(void); void read_reg_timer(uint32_t * tmr); +void sfp_print_info(uint8_t sfp); #endif diff --git a/rtlplayground.c b/rtlplayground.c index 073ca78..b3c9410 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -906,7 +906,10 @@ static inline uint8_t sfp_rate_to_sds_config(register uint8_t rate) void sfp_print_info(uint8_t sfp) { + // This loops over the Vendor-name, Vendor OUI, Vendor PN and Vendor rev ASCII fields for (uint8_t i = 20; i < 60; i++) { + if (i >= 36 && i < 40) // Skip Non-ASCII codes + continue; uint8_t c = sfp_read_reg(sfp, i); if (c) write_char(c); From e9b8ab5b7967f6f8603a5f75866cf7f5a7471a28 Mon Sep 17 00:00:00 2001 From: logicog Date: Tue, 4 Nov 2025 20:05:41 +0100 Subject: [PATCH 02/20] Correct handling of SFP ports in stat command This fixes handling of the SFP ports in the stat command. The output of the command now is for physical ports, which however are not shown in sequence. --- rtl837x_port.c | 93 +++++++++++++++++++++++++++----------------------- rtl837x_regs.h | 3 +- 2 files changed, 52 insertions(+), 44 deletions(-) diff --git a/rtl837x_port.c b/rtl837x_port.c index 26c5dd1..c8cd374 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -382,54 +382,61 @@ void port_stats_print(void) __banked { 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 - if (i <= maxPort - nSFPPorts) { + if (!isRTL8373) { + write_char('0' + log_to_phys_port[i]); write_char('\t'); + } else { + write_char('1' + i); write_char('\t'); + } + + if (!IS_SFP(i)) { + phy_read(i, 0x1f, 0xa610); if (SFR_DATA_8 == 0x20) print_string("On\t"); else print_string("Off\t"); + } else { // An SFP Module + if (i != 3) { + reg_read_m(RTL837X_REG_GPIO_00_31_INPUT); + if (!(sfr_data[0] & 0x40)) { + print_string("SFP OK\t"); + } else { + print_string("NO SFP\t"); + } + } else { + reg_read_m(RTL837X_REG_GPIO_32_63_INPUT); + if (!(sfr_data[1] & 0x04)) { + print_string("SFP OK\t"); + } else { + print_string("NO SFP\t"); + } + } + } + + if (i < 8) reg_read_m(RTL837X_REG_LINKS); - uint8_t b = sfr_data[3 - (i >> 1)]; - b = (i & 1) ? b >> 4 : b & 0xf; - switch (b) { - case 0: - print_string("Down\t"); - break; - case 1: - print_string("100M\t"); - break; - case 2: - print_string("1000M\t"); - break; - case 5: - print_string("2.5G\t"); - break; - default: - print_string("Up\t"); - break; - } - } else { // An SFP Module TODO: This is for 1 module devices - reg_read_m(RTL837X_REG_GPIO_00_31_INPUT); - if (!(sfr_data[0] & 0x40)) { - print_string("SFP OK\t"); - } else { - print_string("NO SFP\t"); - } - reg_read_m(RTL837X_REG_GPIO_32_63_INPUT); - if (sfr_data[3] & 0x20) { - print_string("Down\t"); - } else { - uint8_t rate = sfp_read_reg(0, 12); - if (rate == 0xd) - print_string("1000BX\t"); - else if (rate == 0x1f) - print_string("2500G\t"); - else if (rate > 0x65 && rate < 0x70) - print_string("10G\t"); - else - print_string("Up\t"); - } + else + reg_read_m(RTL837X_REG_LINKS_89); + uint8_t b = sfr_data[3 - ((i & 7) >> 1)]; + b = (i & 1) ? b >> 4 : b & 0xf; + switch (b) { + case 0: + print_string("Down\t"); + break; + case 1: + print_string("100M\t"); + break; + case 2: + print_string("1000M\t"); + break; + case 4: + print_string("10G\t"); + break; + case 5: + print_string("2.5G\t"); + break; + default: + print_string("Up\t"); + break; } STAT_GET(0x2f, i); print_reg(RTL837X_STAT_V_LOW); write_char('\t'); diff --git a/rtl837x_regs.h b/rtl837x_regs.h index fb4b6b9..0888271 100644 --- a/rtl837x_regs.h +++ b/rtl837x_regs.h @@ -31,7 +31,8 @@ #define SDS_10GR 0x1a #define SDS_OFF 0x1f -#define RTL837X_REG_LINKS 0x63f0 +#define RTL837X_REG_LINKS 0x63f0 +#define RTL837X_REG_LINKS_89 0x63f4 /* Each nibble encodes the link state of a port. Port 0 appears to be the CPU port The RTL8372 serves ports 4-7, port 3 is the RTL8221 From 101b4937e10eba6c03702381fcb0215f71b5b07e Mon Sep 17 00:00:00 2001 From: logicog Date: Tue, 4 Nov 2025 20:44:37 +0100 Subject: [PATCH 03/20] Fix link change handling The RTL8272/3 use 2 32 bit registers to indicate the MAC link speed, the second register is used for ports 8 and 9, where 9 is the CPU port. Use both registers. --- rtlplayground.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/rtlplayground.c b/rtlplayground.c index b3c9410..0bc5f27 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -101,6 +101,7 @@ __code uint16_t bit_mask[16] = { __xdata uint8_t was_offline; __xdata uint8_t linkbits_last[4]; +__xdata uint8_t linkbits_last_p89; __xdata uint8_t sfp_pins_last; @@ -1009,17 +1010,25 @@ void idle(void) #endif } + // Check for Link changes + reg_read_m(RTL837X_REG_LINKS_89); + __xdata uint8_t linkbits_p89 = sfr_data[3]; + reg_read_m(RTL837X_REG_LINKS); - if (!isRTL8373 && cmp_4(sfr_data, linkbits_last)) { + if (cmp_4(sfr_data, linkbits_last) || (linkbits_p89 != linkbits_last_p89)) { print_string("\n\n"); - if (nSFPPorts != 2) { + linkbits_last_p89 = linkbits_p89; + if (!isRTL8373 && nSFPPorts != 2) { uint8_t p5 = sfr_data[2] >> 4; uint8_t p5_last = linkbits_last[2] >> 4; cpy_4(linkbits_last, sfr_data); + // Handle link change of the RTL8221 PHY, adjust SDS mode if (p5_last != p5) { if (p5 == 0x5) // 2.5GBit Mode sds_config(0, SDS_HISGMII); @@ -1032,7 +1041,6 @@ void idle(void) } // Check for changes with SFP modules - handle_sfp(); /* Button pressed on KL-8xhm-x2: @@ -1723,7 +1731,7 @@ void bootloader(void) // Set default for SFP pins so we can start up a module already inserted sfp_pins_last = 0x33; // signal LOS and no module inserted (for both slots, even if only 1 present) // We have not detected any link - linkbits_last[0] = linkbits_last[1] = linkbits_last[2] = linkbits_last[3] = 0; + linkbits_last[0] = linkbits_last[1] = linkbits_last[2] = linkbits_last[3] = linkbits_last_p89 = 0; print_string("Detecting CPU: "); isRTL8373 = 0; From 636981c3b82ac17c1dc5f7f410a5d363e2aa3dee Mon Sep 17 00:00:00 2001 From: logicog Date: Thu, 6 Nov 2025 06:24:40 +0100 Subject: [PATCH 04/20] Detect 2nd SFP-slot RX-Los on KP-9000-6XHML-2X --- rtlplayground.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/rtlplayground.c b/rtlplayground.c index 0bc5f27..fe2b2cf 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -950,7 +950,7 @@ void handle_sfp(void) sfp_pins_last |= 0x02; print_string("\n\n"); } - +#if NSFP == 2 reg_read_m(RTL837X_REG_GPIO_32_63_INPUT); if ((sfp_pins_last & 0x10) && (!(sfr_data[1] & 0x04))) { sfp_pins_last &= ~0x10; @@ -969,6 +969,17 @@ void handle_sfp(void) sfp_pins_last |= 0x10; print_string("\n\n"); } + + reg_read_m(RTL837X_REG_GPIO_00_31_INPUT); + if ((sfp_pins_last & 0x20) && (!(sfr_data[2] & 0x08))) { + sfp_pins_last &= ~0x20; + print_string("\n\n"); + } + if ((!(sfp_pins_last & 0x20)) && (sfr_data[2] & 0x08)) { + sfp_pins_last |= 0x20; + print_string("\n\n"); + } +#endif } @@ -1021,7 +1032,7 @@ void idle(void) print_byte(sfr_data[2]); print_byte(sfr_data[3]); print_string(", was "); print_byte(linkbits_last_p89); print_byte(linkbits_last[0]); print_byte(linkbits_last[1]); - print_byte(linkbits_last[2]); print_byte(linkbits_last[3]); + print_byte(linkbits_last[2]); print_byte(linkbits_last[3]); print_string(">\n"); linkbits_last_p89 = linkbits_p89; if (!isRTL8373 && nSFPPorts != 2) { From ab6a66a223d30e56b6ea8d28d81198b3267d2b33 Mon Sep 17 00:00:00 2001 From: logicog Date: Mon, 8 Dec 2025 08:34:32 +0100 Subject: [PATCH 05/20] Add support for 2nd SFP port in stats --- httpd/page_impl.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 21c4b38..da342d5 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -343,30 +343,30 @@ void send_status(void) itoa_html(i + 1); if (IS_SFP(i)) { - slen += strtox(outbuf + slen, ",\"isSFP\":1,\"enabled\":"); - bool_to_html(!((sfp_pins_last >> (i == maxPort ? 0 : 4)) & 1)); - - slen += strtox(outbuf + slen, ",\"link\":"); - uint8_t rate = sfp_read_reg(i == maxPort ? 0 : 1, 12); - if (rate == 0xd) - char_to_html('2'); // 1000BX - else if (rate == 0x1f) - char_to_html('5'); // 2G5 - else if (rate > 0x65 && rate < 0x70) - char_to_html('4'); // 10G "4" is not a valid value for port LINK speed - else - char_to_html('1'); // 100M ??? + slen += strtox(outbuf + slen, ",\"isSFP\":1,\"enabled\":"); + if (i != 3) { + reg_read_m(RTL837X_REG_GPIO_00_31_INPUT); + bool_to_html(!(sfr_data[0] & 0x40)); + } else { + reg_read_m(RTL837X_REG_GPIO_32_63_INPUT); + bool_to_html(!(sfr_data[1] & 0x04)); + } } else { - slen += strtox(outbuf + slen, ",\"isSFP\":0,\"enabled\":"); + slen += strtox(outbuf + slen, ",\"isSFP\":0,\"enabled\":"); phy_read(i, 0x1f, 0xa610); bool_to_html(SFR_DATA_8 == 0x20); - - slen += strtox(outbuf + slen, ",\"link\":"); - reg_read_m(RTL837X_REG_LINKS); - uint8_t b = sfr_data[3 - (i >> 1)]; - b = (i & 1) ? b >> 4 : b & 0xf; - char_to_html('0' + b); } + + slen += strtox(outbuf + slen, ",\"link\":"); + + if (i < 8) + reg_read_m(RTL837X_REG_LINKS); + else + reg_read_m(RTL837X_REG_LINKS_89); + uint8_t b = sfr_data[3 - ((i & 7) >> 1)]; + b = (i & 1) ? b >> 4 : b & 0xf; + char_to_html('0' + b); + STAT_GET(STAT_COUNTER_TX_PKTS, i); slen += strtox(outbuf + slen, ",\"txG\":\"0x"); reg_to_html(RTL837X_STAT_V_HIGH); From 3c869e927a7180a32aed038bbc59cfb931cfe34d Mon Sep 17 00:00:00 2001 From: logicog Date: Mon, 8 Dec 2025 08:34:43 +0100 Subject: [PATCH 06/20] Add support for 10G 500M and 5G speed display This adds the speed status display of other link speeds: 100M 500M 1000M: Green 2nd LED 2.5G, 5G, 10G: Orange 2nd LED --- html/main.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/html/main.js b/html/main.js index eac133e..5d5246e 100644 --- a/html/main.js +++ b/html/main.js @@ -2,7 +2,7 @@ var txG = new BigInt64Array(10); var txB = new BigInt64Array(10); var rxG = new BigInt64Array(10); var rxB = new BigInt64Array(10); -const linkS = ["Disabled", "No Link", "100M", "1000M", "NO", "NO", "2.5G"]; +const linkS = ["Disabled", "No Link", "100M", "1000M", "500M", "10G", "2.5G", "5G"]; var pState = new Int8Array(10); var pIsSFP = new Int8Array(10); var numPorts = 0; @@ -40,9 +40,9 @@ function update() { } else { psvg.style.opacity = 1.0; pState[n] = p.link; - if (p.link == 5) { + if (p.link == 4 || p.link == 5 || p.link == 6) { leds[0].style.fill = "green"; leds[1].style.fill = "orange"; - } else if (p.link == 2) { + } else if (p.link == 1 || p.link == 2 || p.link == 3) { leds[0].style.fill = "green"; leds[1].style.fill = "green"; } else { leds[0].style.fill = "black"; leds[1].style.fill = "black"; From 06fbf85bceb5e09004898147840612ee54ff265a Mon Sep 17 00:00:00 2001 From: logicog Date: Mon, 8 Dec 2025 12:24:20 +0100 Subject: [PATCH 07/20] Add SFP information in send_basic_info() --- httpd/page_impl.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/httpd/page_impl.c b/httpd/page_impl.c index da342d5..fef1e46 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -139,6 +139,20 @@ void reg_to_html(register uint16_t reg) sfr_data_to_html(); } + +void send_sfp_info(uint8_t sfp) +{ + // This loops over the Vendor-name, Vendor OUI, Vendor PN and Vendor rev ASCII fields + for (uint8_t i = 20; i < 60; i++) { + if (i >= 36 && i < 40) // Skip Non-ASCII codes + continue; + uint8_t c = sfp_read_reg(sfp, i); + if (c && c != 0xa0) // a0 is the byte read from a non-existant I2C EEPROM + char_to_html(c); + } +} + + void send_basic_info(void) { slen = strtox(outbuf, HTTP_RESPONCE_JSON); @@ -167,7 +181,16 @@ void send_basic_info(void) byte_to_html(uip_ethaddr.addr[5]); slen += strtox(outbuf + slen, "\",\"sw_ver\":\""); slen += strtox(outbuf + slen, VERSION_SW); - slen += strtox(outbuf + slen, "\",\"hw_ver\":\"SWGT024-V2.0\"}"); + slen += strtox(outbuf + slen, "\",\"hw_ver\":\"SWGT024-V2.0\""); + slen += strtox(outbuf + slen, ",\"sfp_slot_0\":\""); + send_sfp_info(0); + char_to_html('"'); +#if NSFP == 2 + slen += strtox(outbuf + slen, ",\"sfp_slot_1\":\""); + send_sfp_info(1); + char_to_html('"'); +#endif + char_to_html('}'); } From d75ad636f9dc0c44952ebdd2dcde7052cf1ab77c Mon Sep 17 00:00:00 2001 From: logicog Date: Wed, 10 Dec 2025 15:24:13 +0100 Subject: [PATCH 08/20] Use machine structure --- Makefile | 2 +- cmd_parser.c | 47 +++++++----------------- httpd/page_impl.c | 48 +++++++++--------------- rtl837x_common.h | 10 +---- rtl837x_flash.c | 2 +- rtl837x_igmp.c | 18 +++------ rtl837x_port.c | 70 +++++++++++------------------------ rtl837x_stp.c | 13 +++---- rtlplayground.c | 93 +++++++++++++++++++++-------------------------- 9 files changed, 109 insertions(+), 194 deletions(-) diff --git a/Makefile b/Makefile index f6987b9..abf61de 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ all: create_build_dir $(VERSION_HEADER) $(SUBDIRS) $(BUILDDIR)rtlplayground.bin create_build_dir: mkdir -p $(BUILDDIR) -SRCS = rtlplayground.c rtl837x_flash.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c rtl837x_stp.c +SRCS = rtlplayground.c rtl837x_flash.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c rtl837x_stp.c machine.c OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel} OBJS += uip/$(BUILDDIR)/timer.rel uip/$(BUILDDIR)/uip-fw.rel uip/$(BUILDDIR)/uip-neighbor.rel uip/$(BUILDDIR)/uip-split.rel uip/$(BUILDDIR)/uip.rel uip/$(BUILDDIR)/uip_arp.rel uip/$(BUILDDIR)/uiplib.rel httpd/$(BUILDDIR)/httpd.rel httpd/$(BUILDDIR)/page_impl.rel diff --git a/cmd_parser.c b/cmd_parser.c index 8c0e099..5707612 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -15,13 +15,12 @@ #include "uip/uip.h" #include "version.h" +#include "machine.h" + #pragma codeseg BANK1 #pragma constseg BANK1 -extern __xdata uint8_t minPort; -extern __xdata uint8_t maxPort; -extern __xdata uint8_t nSFPPorts; -extern __xdata uint8_t isRTL8373; +extern __code struct machine machine; extern __xdata uint16_t mpos; extern __xdata uint8_t stpEnabled; extern __code uint8_t log_to_phys_port[9]; @@ -63,11 +62,6 @@ __xdata signed char cmd_words_b[N_WORDS]; __xdata uint8_t cmd_history[CMD_HISTORY_SIZE]; __xdata uint16_t cmd_history_ptr; -// Maps the physical port (starting from 0) to the logical port -__code uint8_t phys_to_log_port[6] = { - 4, 5, 6, 7, 3, 8 -}; - inline uint8_t isletter(uint8_t l) { @@ -205,10 +199,7 @@ void parse_lag(void) print_string(" member ports: "); for (uint8_t j = 0; j < 10; j++) { if (members & 1) { - if (!isRTL8373) - write_char('0' + log_to_phys_port[j]); - else - write_char('1' + j); + write_char('0' + machine.log_to_phys_port[j]); write_char(' '); } members >>= 1; @@ -233,12 +224,11 @@ void parse_lag(void) port = cmd_buffer[cmd_words_b[w]] - '1'; if (isnumber(cmd_buffer[cmd_words_b[w] + 1])) port = (port + 1) * 10 + cmd_buffer[cmd_words_b[w] + 1] - '1'; - if (!isRTL8373) - port = phys_to_log_port[port]; + port = machine.phys_to_log_port[port]; } else { goto err; } - if (port > maxPort) + if (port > machine.max_port) goto err; members |= ((uint16_t)1) << port; w++; @@ -321,12 +311,11 @@ void parse_vlan(void) if (cmd_buffer[cmd_words_b[w] + 2] == 't') tagged |= ((uint16_t)1) << port; } else { - if (!isRTL8373) - port = phys_to_log_port[port]; + port = machine.phys_to_log_port[port]; if (cmd_buffer[cmd_words_b[w] + 1] == 't') tagged |= ((uint16_t)1) << port; } - if (port > maxPort) + if (port > machine.max_port) goto err; members |= ((uint16_t)1) << port; } @@ -359,10 +348,7 @@ void parse_mirror(void) print_string("NOT Enabled: "); } print_string("Mirroring port: "); - if (!isRTL8373) - write_char('0' + log_to_phys_port[mPort >> 1]); - else - write_char('0' + (mPort >> 1) + 1); + write_char('0' + machine.log_to_phys_port[mPort >> 1]); reg_read_m(RTL837x_MIRROR_CONF); uint16_t m = sfr_data[0]; m = (m << 8) | sfr_data[1]; @@ -387,8 +373,7 @@ void parse_mirror(void) mirroring_port = cmd_buffer[cmd_words_b[1]] - '1'; if (isnumber(cmd_buffer[cmd_words_b[1] + 1])) mirroring_port = (mirroring_port + 1) * 10 + cmd_buffer[cmd_words_b[1] + 1] - '1'; - if (!isRTL8373) - mirroring_port = phys_to_log_port[mirroring_port]; + mirroring_port = machine.phys_to_log_port[mirroring_port]; uint8_t w = 2; while (cmd_words_b[w] > 0) { @@ -397,8 +382,7 @@ void parse_mirror(void) port = cmd_buffer[cmd_words_b[w]] - '1'; if (isnumber(cmd_buffer[cmd_words_b[w] + 1])) { port = (port + 1) * 10 + cmd_buffer[cmd_words_b[w] + 1] - '1'; - if (!isRTL8373) - port = phys_to_log_port[port]; + port = machine.phys_to_log_port[port]; if (cmd_buffer[cmd_words_b[w] + 2] == 'r') rx_pmask |= ((uint16_t)1) << port; else if (cmd_buffer[cmd_words_b[w] + 2] == 't') @@ -408,8 +392,7 @@ void parse_mirror(void) tx_pmask |= ((uint16_t)1) << port; } } else { - if (!isRTL8373) - port = phys_to_log_port[port]; + port = machine.phys_to_log_port[port]; if (cmd_buffer[cmd_words_b[w] + 1] == 'r') rx_pmask |= ((uint16_t)1) << port; else if (cmd_buffer[cmd_words_b[w] + 1] == 't') @@ -743,8 +726,7 @@ void cmd_parser(void) __banked __xdata uint16_t pvid; uint8_t port; port = cmd_buffer[cmd_words_b[1]] - '1'; - if (!isRTL8373) - port = phys_to_log_port[port]; + port = machine.phys_to_log_port[port]; if (!atoi_short(&pvid, cmd_words_b[2])) port_pvid_set(port, pvid); } else if (cmd_compare(0, "vlan")) { @@ -771,8 +753,7 @@ void cmd_parser(void) __banked int8_t port = -1; if (cmd_words_b[3] > 0) { port = cmd_buffer[cmd_words_b[2]] - '1'; - if (!isRTL8373) - port = phys_to_log_port[port]; + port = machine.phys_to_log_port[port]; } if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) { if (port >= 0) diff --git a/httpd/page_impl.c b/httpd/page_impl.c index fef1e46..6ef1ccd 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -10,11 +10,13 @@ #include #include "../phy.h" #include "../version.h" +#include "../machine.h" #include "page_impl.h" #pragma codeseg BANK1 #pragma constseg BANK1 +extern __code const struct machine machine; extern __xdata uint8_t outbuf[TCP_OUTBUF_SIZE]; extern __xdata uint16_t slen; extern __xdata uint16_t cont_len; @@ -22,15 +24,8 @@ extern __xdata uint32_t cont_addr; extern __code uint8_t * __code hex; extern __xdata uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask; extern __code struct uip_eth_addr uip_ethaddr; -extern __code uint8_t log_to_phys_port[9]; -extern __code uint8_t phys_to_log_port[6]; -extern __xdata uint8_t minPort; -extern __xdata uint8_t maxPort; -extern __xdata uint8_t nSFPPorts; extern __xdata uint8_t sfr_data[4]; -extern __xdata uint8_t cpuPort; -extern __xdata uint8_t isRTL8373; extern __xdata uint8_t sfp_pins_last; extern __xdata uint8_t vlan_names[VLAN_NAMES_SIZE]; @@ -185,11 +180,11 @@ void send_basic_info(void) slen += strtox(outbuf + slen, ",\"sfp_slot_0\":\""); send_sfp_info(0); char_to_html('"'); -#if NSFP == 2 - slen += strtox(outbuf + slen, ",\"sfp_slot_1\":\""); - send_sfp_info(1); - char_to_html('"'); -#endif + if (machine.n_sfp == 2) { + slen += strtox(outbuf + slen, ",\"sfp_slot_1\":\""); + send_sfp_info(1); + char_to_html('"'); + } char_to_html('}'); } @@ -221,7 +216,7 @@ void send_counters(char port) print_string("sending counters\n"); port--; - uint8_t i = isRTL8373 ? port - 1: phys_to_log_port[port]; + uint8_t i = machine.phys_to_log_port[port]; slen += strtox(outbuf + slen, "{\"portNum\":"); itoa_html(i + 1); for (uint8_t j = 0; j < 0x3f; j++) { @@ -249,10 +244,7 @@ void send_mirror(void) } else { slen += strtox(outbuf + slen, "{\"enabled\":0,\"mPort\":"); } - if (!isRTL8373) - itoa_html(log_to_phys_port[mPort >> 1]); - else - itoa_html((mPort >> 1) + 1); + itoa_html(machine.log_to_phys_port[mPort >> 1]); reg_read_m(RTL837x_MIRROR_CONF); uint16_t m = sfr_data[0]; @@ -309,14 +301,11 @@ void send_eee(void) uint8_t eee_ablty = sfr_data[3]; char_to_html('['); - for (uint8_t i = minPort; i <= maxPort; i++) { + for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { slen += strtox(outbuf + slen, "{\"portNum\":"); - if (!isRTL8373) - itoa_html(log_to_phys_port[i]); - else - itoa_html(i + 1); + itoa_html(machine.log_to_phys_port[i]); - if (IS_SFP(i)) { + if (machine.is_sfp[i]) { slen += strtox(outbuf + slen, ",\"isSFP\":1"); } else { slen += strtox(outbuf + slen, ",\"isSFP\":0,\"eee\":\""); @@ -344,7 +333,7 @@ void send_eee(void) bool_to_html(eee_ablty & (1 << i)); } char_to_html('}'); - if (i < maxPort) + if (i < machine.max_port) char_to_html(','); else char_to_html(']'); @@ -358,14 +347,11 @@ void send_status(void) print_string("sending status\n"); char_to_html('['); - for (uint8_t i = minPort; i <= maxPort; i++) { + for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { slen += strtox(outbuf + slen, "{\"portNum\":"); - if (!isRTL8373) - itoa_html(log_to_phys_port[i]); - else - itoa_html(i + 1); + itoa_html(machine.log_to_phys_port[i]); - if (IS_SFP(i)) { + if (machine.is_sfp[i]) { slen += strtox(outbuf + slen, ",\"isSFP\":1,\"enabled\":"); if (i != 3) { reg_read_m(RTL837X_REG_GPIO_00_31_INPUT); @@ -408,7 +394,7 @@ void send_status(void) STAT_GET(STAT_COUNTER_ERR_PKTS, i); reg_to_html(RTL837X_STAT_V_HIGH); // 32bit RX packet errors slen += strtox(outbuf + slen, "\"}"); - if (i < maxPort) + if (i < machine.max_port) char_to_html(','); else char_to_html(']'); diff --git a/rtl837x_common.h b/rtl837x_common.h index 5377eb2..016a85d 100644 --- a/rtl837x_common.h +++ b/rtl837x_common.h @@ -4,13 +4,13 @@ #include "uip/uip-conf.h" #include -// This has to be set to the number of SFP+ ports, i.e. 1 or 2 -#define NSFP 2 // SCL and SDA pin numbers for SFP cage 0 and SFP cage 1 #define SCL_PIN 3 #define SDA_PIN_0 4 #define SDA_PIN_1 3 +#define CPU_PORT 9 + // Define Port-masks for 9-port devices and 6-port devices #define PMASK_9 0x1ff #define PMASK_6 0x1f8 @@ -41,12 +41,6 @@ // This is the standard size of an Ethernet frame header #define ETHER_HEADER_SIZE 14 -#if NSFP == 1 -#define IS_SFP(port) (i == maxPort) -#else -#define IS_SFP(port) (i == maxPort || i == 3) -#endif - #define CONFIG_START 0x70000 #define CONFIG_LEN 0x1000 #define CODE0_SIZE 0x4000 diff --git a/rtl837x_flash.c b/rtl837x_flash.c index 4df0604..7020e02 100644 --- a/rtl837x_flash.c +++ b/rtl837x_flash.c @@ -283,7 +283,7 @@ void flash_read_bulk(__xdata uint8_t *dst) } -void flash_read_security() +void flash_read_security(void) { while (flash_read_status() & 0x1); diff --git a/rtl837x_igmp.c b/rtl837x_igmp.c index 032efca..d1ca647 100644 --- a/rtl837x_igmp.c +++ b/rtl837x_igmp.c @@ -11,12 +11,9 @@ #include "rtl837x_sfr.h" #include "rtl837x_regs.h" #include "rtl837x_igmp.h" +#include "machine.h" -extern __xdata uint8_t minPort; -extern __xdata uint8_t maxPort; -extern __xdata uint8_t nSFPPorts; -extern __xdata uint8_t cpuPort; -extern __xdata uint8_t isRTL8373; +extern __code struct machine machine; void igmp_setup(void) __banked { @@ -24,19 +21,16 @@ void igmp_setup(void) __banked // For now, forward all unkown MC pkts (2 bits per port. 00: flood via floodmask, 01: drop, 10: trap, 11: to rport) REG_SET(RTL837X_MC_LOOKUPMISS_ACTIONS, 0x00000000); //0x4f78 + // Define ports where unknown MC addresses are flooded to: - if (isRTL8373) { - REG_SET(RTL837X_MC_FLOODMASK, PMASK_9); // R5368-000001f8 - } else { - REG_SET(RTL837X_MC_FLOODMASK, PMASK_6); - } + REG_SET(RTL837X_MC_FLOODMASK, machine.isRTL8373 ? PMASK_9 : PMASK_6); // Enable lookup of IPv4 MC addresses in table reg_bit_set(RTL837X_L2_CTRL, 3); // 0x5350 // Configure per-port IGMP configuration, bits 0-10 enable MC protocol snooping, // bits 16-24 configure max MC group used by that port. For now all protocols are flooded (01) - for (i = minPort; i <= maxPort; i++) + for (i = machine.min_port; i <= machine.max_port; i++) REG_SET(RTL837X_IGMP_PORT_CFG + (i << 2), 0x00ff7c15); } @@ -52,6 +46,6 @@ void igmp_enable(void) __banked // Configure per-port IGMP configuration, bits 0-10 enable MC protocol snooping, // bits 16-24 configure max MC group used by that port. Trap to CPU (10) - for (i = minPort; i <= maxPort; i++) + for (i = machine.min_port; i <= machine.max_port; i++) REG_SET(RTL837X_IGMP_PORT_CFG + (i << 2), 0x00ff7c2a); // 0x00ff7000: Handling by ASIC (00) } diff --git a/rtl837x_port.c b/rtl837x_port.c index c8cd374..1665cd1 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -13,40 +13,20 @@ #include "rtl837x_port.h" #include "rtl837x_phy.h" #include "phy.h" +#include "machine.h" #pragma codeseg BANK1 #pragma constseg BANK1 extern __code uint8_t * __code hex; extern __code uint16_t bit_mask[16]; -extern __xdata uint8_t minPort; -extern __xdata uint8_t maxPort; -extern __xdata uint8_t nSFPPorts; +extern __code struct machine machine; extern __xdata uint8_t sfr_data[4]; -extern __xdata uint8_t cpuPort; extern __xdata uint16_t vlan_ptr; extern __xdata uint8_t vlan_names[VLAN_NAMES_SIZE]; -extern __xdata uint8_t isRTL8373; - __xdata uint32_t l2_head; -// The mapping of logical to physical ports on the RTL8372 -// Port 6 is always an SFP+ port. Port 5 may be RTL8221 or SFP+ -__code uint8_t log_to_phys_port[9] = { - 0, 0, 0, 5, 1, 2, 3, 4, 6 -}; - -#if NSFP == 2 -__code uint8_t is_sfp[9] = { - 0, 0, 0, 1, 0, 0, 0, 0, 1 -}; -#else -__code uint8_t is_sfp[9] = { - 0, 0, 0, 0, 0, 0, 0, 0, 1 -}; -#endif - void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked { print_string("\nport_mirror_set called \n"); @@ -153,7 +133,7 @@ void vlan_create(register uint16_t vlan, register uint16_t members, register uin uint16_t a = (~members) ^ tagged ^ members; // On RTL8372, port-bits 0-2 must be 0, although they are not members - if (!isRTL8373) { + if (!machine.isRTL8373) { a &= 0x1f8; tagged &= 0x3f8; } @@ -184,7 +164,7 @@ void vlan_setup(void) __banked vlan_names[0] = 0; // Initialize VLAN table for VLAN 1, by disabling that entry - if (isRTL8373) { + if (machine.isRTL8373) { REG_SET(RTL837x_TBL_DATA_IN_A, 0x0007ffff); } else { REG_SET(RTL837x_TBL_DATA_IN_A, 0x0007e3f8); @@ -195,7 +175,7 @@ void vlan_setup(void) __banked } 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 = machine.min_port; i <= machine.max_port + 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('='); @@ -231,7 +211,7 @@ void vlan_setup(void) __banked REG_SET(RTL837X_VLAN_L2_LRN_DIS_1, 0); // Enable VLAN 1: Ports 0-9, i.e. including the CPU port are untagged members - if (isRTL8373) { + if (machine.isRTL8373) { REG_SET(RTL837x_TBL_DATA_IN_A, 0x0207ffff); // 02: Entry valid, 7ffff: membership } else { REG_SET(RTL837x_TBL_DATA_IN_A, 0x0207e3f8); @@ -266,11 +246,7 @@ uint8_t port_l2_forget(void) __banked REG_SET(RTL837x_L2_TBL_FLUSH_CNF, 0x0); // Flush L2 table for all ports by setting the ports and the flush-exec bit (bit 16) - if (isRTL8373) { - REG_SET(RTL837x_L2_TBL_FLUSH_CTRL, L2_TBL_FLUSH_EXEC | PMASK_9); - } else { - REG_SET(RTL837x_L2_TBL_FLUSH_CTRL, L2_TBL_FLUSH_EXEC | PMASK_6); - } + REG_SET(RTL837x_L2_TBL_FLUSH_CTRL, machine.isRTL8373 ? L2_TBL_FLUSH_EXEC | PMASK_9 : L2_TBL_FLUSH_EXEC | PMASK_6); // Wait for flush completed do { @@ -358,14 +334,14 @@ void port_l2_setup(void) __banked port_l2_forget(); - for (uint8_t i = minPort; i <= maxPort; i++) { + for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { // Limit the number of automatically learned MAC-Entries per port to 0x1040 uint16_t reg = RTL837X_L2_LRN_PORT_CONSTRAINT + (i << 2); REG_SET(reg, 0x00001040); // All ports may communicate with each other and CPU-Port reg = RTL837X_PORT_ISOLATION_BASE + (i << 2); - if(isRTL8373) { + if(machine.isRTL8373) { REG_SET(reg, PMASK_9 | PMASK_CPU); } else { REG_SET(reg, PMASK_6 | PMASK_CPU); @@ -381,14 +357,10 @@ void port_l2_setup(void) __banked void port_stats_print(void) __banked { print_string("\n Port\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\n"); - for (uint8_t i = minPort; i <= maxPort; i++) { - if (!isRTL8373) { - write_char('0' + log_to_phys_port[i]); write_char('\t'); - } else { - write_char('1' + i); write_char('\t'); - } + for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + write_char('0' + machine.log_to_phys_port[i]); write_char('\t'); - if (!IS_SFP(i)) { + if (!machine.is_sfp[i]) { phy_read(i, 0x1f, 0xa610); if (SFR_DATA_8 == 0x20) print_string("On\t"); @@ -456,14 +428,14 @@ void port_stats_print(void) __banked void port_isolate(register uint8_t port, __xdata uint16_t pmask) { - if (port <= maxPort) + if (port <= machine.max_port) REG_SET(RTL837X_PORT_ISOLATION_BASE + (port << 2), pmask); } uint16_t port_isolation_get(register uint8_t port) { - if (port > maxPort) + if (port > machine.max_port) return 0; reg_read_m(RTL837X_PORT_ISOLATION_BASE + (port << 2)); @@ -473,7 +445,7 @@ uint16_t port_isolation_get(register uint8_t port) void port_eee_enable(uint8_t port) __banked { - if (is_sfp[port]) + if (machine.is_sfp[port]) return; REG_SET(RTL8373_EEE_CTRL_BASE + (port << 2), EEE_100 | EEE_1000 | EEE_2G5); @@ -487,7 +459,7 @@ void port_eee_enable(uint8_t port) __banked void port_eee_disable(uint8_t port) __banked { - if (is_sfp[port]) + if (machine.is_sfp[port]) return; print_string("EEE off for "); print_byte(port); write_char('\n'); @@ -502,9 +474,9 @@ void port_eee_disable(uint8_t port) __banked void port_eee_status(uint8_t port) __banked { - print_string("Port: "); write_char('0' + log_to_phys_port[port]); + print_string("Port: "); write_char('0' + machine.log_to_phys_port[port]); print_string(": "); - if (is_sfp[port]) { + if (machine.is_sfp[port]) { print_string("SFP\n"); return; } @@ -557,7 +529,7 @@ void port_eee_status(uint8_t port) __banked void port_eee_enable_all(void) __banked { - for (uint8_t i = minPort; i <= maxPort; i++) { + for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { port_eee_enable(i); } } @@ -565,7 +537,7 @@ void port_eee_enable_all(void) __banked void port_eee_disable_all(void) __banked { - for (uint8_t i = minPort; i <= maxPort; i++) { + for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { port_eee_disable(i); } } @@ -573,7 +545,7 @@ void port_eee_disable_all(void) __banked void port_eee_status_all(void) __banked { - for (uint8_t i = minPort; i <= maxPort; i++) { + for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { port_eee_status(i); } } diff --git a/rtl837x_stp.c b/rtl837x_stp.c index 2e6c08a..54207e4 100644 --- a/rtl837x_stp.c +++ b/rtl837x_stp.c @@ -12,12 +12,9 @@ #include "rtl837x_regs.h" #include "rtl837x_stp.h" #include "uip.h" +#include "machine.h" -extern __xdata uint8_t minPort; -extern __xdata uint8_t maxPort; -extern __xdata uint8_t nSFPPorts; -extern __xdata uint8_t cpuPort; -extern __xdata uint8_t isRTL8373; +extern __code struct machine machine; extern __xdata uint8_t sfr_data[4]; extern __code struct uip_eth_addr uip_ethaddr; @@ -203,7 +200,7 @@ void stp_cnf_send(uint8_t port) void stp_timers(void) __banked { - for (uint8_t i = minPort; i <= maxPort; i++) { + for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { port_hello[i]--; if (!port_hello[i]) { port_hello[i] = TIME_HELLO; @@ -219,7 +216,7 @@ void stp_setup(void) __banked { print_string("Enabling STP: "); sfr_data[0] = sfr_data[1] = sfr_data[2] = sfr_data[3] = 0; - for (uint8_t i = minPort; i <= maxPort; i++) { + for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { // Set STP port state to blocking // States are: 00 disable, 01 blocking, 10 learning, 11 forwarding uint8_t bit_mask = 0b01 << ( (i << 1) & 0x7); @@ -241,7 +238,7 @@ void stp_setup(void) __banked void stp_off(void) __banked { sfr_data[0] = sfr_data[1] = sfr_data[2] = sfr_data[3] = 0; - for (uint8_t i = minPort; i <= maxPort; i++) { + for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { // Set STP port state to forwarding // States are: 00 disable, 01 blocking, 10 learning, 11 forwarding uint8_t bit_mask = 0b11 << ( (i << 1) & 0x7); diff --git a/rtlplayground.c b/rtlplayground.c index fe2b2cf..150032d 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -15,6 +15,9 @@ #include "uip/uipopt.h" #include "uip/uip.h" #include "uip/uip_arp.h" +#include "machine.h" + +extern __code struct machine machine; extern __xdata uint16_t crc_value; __xdata uint8_t crc_testbytes[10]; @@ -56,8 +59,6 @@ __code struct uip_eth_addr uip_ethaddr = {{ 0x1c, 0x2a, 0xa3, 0x23, 0x00, 0x02 } __code uint8_t gatewayIP[] = { 192, 168, 2, 22}; __code uint8_t netmask[] = { 255, 255, 255, 0}; -__xdata uint8_t isRTL8373; - volatile __xdata uint32_t ticks; volatile __xdata uint8_t sec_counter; volatile __xdata uint16_t sleep_ticks; @@ -87,10 +88,6 @@ __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2]; __xdata uint16_t rx_packet_vlan; __xdata uint8_t tx_seq; -__xdata uint8_t minPort; -__xdata uint8_t maxPort; -__xdata uint8_t nSFPPorts; -__xdata uint8_t cpuPort; __xdata uint8_t stpEnabled; __code uint16_t bit_mask[16] = { @@ -633,7 +630,7 @@ void sds_config_mac(uint8_t sds, uint8_t mode) case 2: sfr_mask_data(1, 0xfc, 0x02 << 2); } - if (isRTL8373) // Set 3rd SERDES Mode to 0x2 for RTL8224 + if (machine.isRTL8373) // Set 3rd SERDES Mode to 0x2 for RTL8224 sfr_mask_data(1, 0xfc, 0x02 << 2); else sfr_data[2] &= 0x03; @@ -950,36 +947,36 @@ void handle_sfp(void) sfp_pins_last |= 0x02; print_string("\n\n"); } -#if NSFP == 2 - reg_read_m(RTL837X_REG_GPIO_32_63_INPUT); - if ((sfp_pins_last & 0x10) && (!(sfr_data[1] & 0x04))) { - sfp_pins_last &= ~0x10; - print_string("\n "); - // Read Reg 11: Encoding, see SFF-8472 and SFF-8024 - // Read Reg 12: Signalling rate (including overhead) in 100Mbit: 0xd: 1Gbit, 0x67:10Gbit - delay(100); // Delay, because some modules need time to wake up - uint8_t rate = sfp_read_reg(1, 12); - print_string("Rate: "); print_byte(rate); // Normally 1, but 0 for DAC, can be ignored? - print_string(" Encoding: "); print_byte(sfp_read_reg(1, 11)); - print_string("\n"); - sfp_print_info(1); - sds_config(0, sfp_rate_to_sds_config(rate)); - } - if ((!(sfp_pins_last & 0x10)) && (sfr_data[1] & 0x04)) { - sfp_pins_last |= 0x10; - print_string("\n\n"); - } + if (machine.n_sfp == 2) { + reg_read_m(RTL837X_REG_GPIO_32_63_INPUT); + if ((sfp_pins_last & 0x10) && (!(sfr_data[1] & 0x04))) { + sfp_pins_last &= ~0x10; + print_string("\n "); + // Read Reg 11: Encoding, see SFF-8472 and SFF-8024 + // Read Reg 12: Signalling rate (including overhead) in 100Mbit: 0xd: 1Gbit, 0x67:10Gbit + delay(100); // Delay, because some modules need time to wake up + uint8_t rate = sfp_read_reg(1, 12); + print_string("Rate: "); print_byte(rate); // Normally 1, but 0 for DAC, can be ignored? + print_string(" Encoding: "); print_byte(sfp_read_reg(1, 11)); + print_string("\n"); + sfp_print_info(1); + sds_config(0, sfp_rate_to_sds_config(rate)); + } + if ((!(sfp_pins_last & 0x10)) && (sfr_data[1] & 0x04)) { + sfp_pins_last |= 0x10; + print_string("\n\n"); + } - reg_read_m(RTL837X_REG_GPIO_00_31_INPUT); - if ((sfp_pins_last & 0x20) && (!(sfr_data[2] & 0x08))) { - sfp_pins_last &= ~0x20; - print_string("\n\n"); + reg_read_m(RTL837X_REG_GPIO_00_31_INPUT); + if ((sfp_pins_last & 0x20) && (!(sfr_data[2] & 0x08))) { + sfp_pins_last &= ~0x20; + print_string("\n\n"); + } + if ((!(sfp_pins_last & 0x20)) && (sfr_data[2] & 0x08)) { + sfp_pins_last |= 0x20; + print_string("\n\n"); + } } - if ((!(sfp_pins_last & 0x20)) && (sfr_data[2] & 0x08)) { - sfp_pins_last |= 0x20; - print_string("\n\n"); - } -#endif } @@ -1035,7 +1032,7 @@ void idle(void) print_byte(linkbits_last[2]); print_byte(linkbits_last[3]); print_string(">\n"); linkbits_last_p89 = linkbits_p89; - if (!isRTL8373 && nSFPPorts != 2) { + if (!machine.isRTL8373 && machine.n_sfp != 2) { uint8_t p5 = sfr_data[2] >> 4; uint8_t p5_last = linkbits_last[2] >> 4; cpy_4(linkbits_last, sfr_data); @@ -1420,7 +1417,7 @@ void led_config(void) reg_bit_clear(0x65dc, 0x1b); // Set bits 1b/1d of 0x7f8c: r7f8c:30000000 R7f8c-30000000 r7f8c:30000000 R7f8c-38000000 - if (nSFPPorts == 2) { + if (machine.n_sfp == 2) { reg_bit_set(RTL837X_PIN_MUX_0, 0x1b); // R7f8c-28000000 reg_bit_clear(RTL837X_PIN_MUX_0, 0x1c); // R7f8c-28000000 reg_bit_set(RTL837X_PIN_MUX_0, 0x1d); // R7f8c-28000000 @@ -1481,10 +1478,6 @@ void rtl8373_revision(void) void rtl8373_init(void) { print_string("\nrtl8373_init called\n"); - minPort = 0; - maxPort = 8; - cpuPort = 9; - nSFPPorts = 1; // r6330:00015555 R6330-00005555 r6330:00005555 R6330-00005555 REG_SET(0x6330, 0x00005555); @@ -1584,21 +1577,17 @@ void rtl8373_init(void) void rtl8372_init(void) { print_string("\nrtl8372_init called\n"); - minPort = 3; - maxPort = 8; - cpuPort = 9; - nSFPPorts = NSFP; // r6330:00015555 R6330-00005555 r6330:00005555 R6330-00005555 REG_SET(0x6330, 0x00005555); - if (nSFPPorts == 2) { + if (machine.n_sfp == 2) { print_string("Configuring 2nd SFP+ port\n"); REG_SET(0x6330, 0x00005515); } // r6334:00000000 R6334-000001f8 RTL8373: r6334:00000000 R6334-000000ff reg_read_m(0x6334); // Also in sdsMode_set - if (nSFPPorts == 2) { + if (machine.n_sfp == 2) { sfr_mask_data(0, 0, 0xf0); } else { sfr_mask_data(1, 0, 0x01); // Set bits 3-8, On RTL8373+8224 set bits 0-7 @@ -1643,7 +1632,7 @@ void rtl8372_init(void) // [...] /// uint16_t reg = 0x1238 + 0x300; // Port base register for the bits we set - for (char i = minPort; i <= maxPort; i++) { + for (char i = machine.min_port; i <= machine.max_port; i++) { // Bit 7 (0x40) enables replacement of the RTL-VLAN tag with an 802.1Q VLAN tag REG_SET(reg, 0xe77); reg += 0x100; @@ -1745,14 +1734,16 @@ void bootloader(void) linkbits_last[0] = linkbits_last[1] = linkbits_last[2] = linkbits_last[3] = linkbits_last_p89 = 0; print_string("Detecting CPU: "); - isRTL8373 = 0; reg_read_m(0x4); if (sfr_data[1] == 0x73) { // Register was 0x83730000 print_string("RTL8373\n"); - isRTL8373 = 1; + if (!machine.isRTL8373) + print_string("INCORRECT MACHINE!"); rtl8224_enable(); // Power on the RTL8224 } else { print_string("RTL8372\n"); + if (machine.isRTL8373) + print_string("INCORRECT MACHINE!"); } // Print SW version @@ -1774,7 +1765,7 @@ void bootloader(void) uip_ipaddr(&uip_netmask, netmask[0], netmask[1], netmask[2], netmask[3]); REG_SET(0x7f94, 0x0); - if (isRTL8373) + if (machine.isRTL8373) rtl8373_init(); else rtl8372_init(); From 45d4fc19c49533b686e30571f43c8e7335f1130e Mon Sep 17 00:00:00 2001 From: logicog Date: Wed, 10 Dec 2025 17:39:19 +0100 Subject: [PATCH 09/20] Add machine definitions --- machine.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ machine.h | 40 ++++++++++++++++++++++++++++++++++ rtl837x_port.c | 22 ++++++------------- 3 files changed, 104 insertions(+), 16 deletions(-) create mode 100644 machine.c create mode 100644 machine.h diff --git a/machine.c b/machine.c new file mode 100644 index 0000000..597ec18 --- /dev/null +++ b/machine.c @@ -0,0 +1,58 @@ +#include "machine.h" + +#ifdef MACHINE_KL_9000_6XHML_X2 +__code const struct machine machine = { + .machine_name = "keepLink KL-9000-6XHML-X2", + .isRTL8373 = 0, + .min_port = 3, + .max_port = 8, + .n_sfp = 2, + .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, + .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, + .is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1}, + .sfp_port[0].pin_detect = 45, + .sfp_port[0].pin_los = 21, + .sfp_port[0].sds = 1, + .sfp_port[0].i2c = 1, + .sfp_port[1].pin_detect = 1, + .sfp_port[1].pin_los = 58, + .sfp_port[1].sds = 0, + .sfp_port[1].i2c = 0, + .reset_pin = 49, +}; + +#elif MACHINE_SWGT024_V2_0 +__code const struct machine machine = { + .machine_name = "SWGT024 V2.0", + .isRTL8373 = 0, + .min_port = 3, + .max_port = 8, + .n_sfp = 2, + .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, + .phys_to_log_port = {4, 6, 5, 7, 3, 8, 0, 0, 0}, + .is_sfp= {0, 0, 0, 2, 0, 0, 0, 0, 1}, + .sfp_port[0].pin_detect = 1, + .sfp_port[0].pin_los = 58, + .sfp_port[0].sds = 1, + .sfp_port[0].i2c = 1, + .sfp_port[1].pin_detect = 45, + .sfp_port[1].pin_los = 21, + .sfp_port[1].sds = 0, + .sfp_port[1].i2c = 0, +}; +#elif DEFAULT_8C_1SFP +__code const struct machine machine = { + .machine_name = "9-Port Switch", + .isRTL8373 = 1, + .min_port = 0, + .max_port = 8, + .n_sfp = 1, + .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, + .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, + .is_sfp= {0, 0, 0, 0, 0, 0, 0, 0, 1}, + .sfp_port[0].pin_detect = 1, + .sfp_port[0].pin_los = 58, + .sfp_port[0].sds = 1, +}; + +#endif diff --git a/machine.h b/machine.h new file mode 100644 index 0000000..a5400a4 --- /dev/null +++ b/machine.h @@ -0,0 +1,40 @@ +#ifndef _MACHINE_H_ +#define _MACHINE_H_ + +#include + +/* + * Select your machine type below + */ +#define MACHINE_KL_9000_6XHML_X2 +// #define MACHINE_SWGT024_V2_0 +// #define MACHINE_HORACO_ZX_SG4T2 + +// #define DEFAULT_8C_1SFP + +// #define DEFAULT_5C_1SFP + +struct sfp_port +{ + uint8_t pin_detect; // gpio number 0-63, 0xFF = don't have it? + uint8_t pin_los; // gpio number 0-63, 0xFF = don't have it? + uint8_t sds; + uint8_t i2c; +}; + +typedef struct machine { + char machine_name[30]; + uint8_t isRTL8373; + uint8_t min_port; + uint8_t max_port; + uint8_t n_sfp; + uint8_t log_to_phys_port[9]; + uint8_t phys_to_log_port[9]; // Starts at 0 for port 1 + uint8_t is_sfp[9]; // 0 for non-SFP ports 1 or 2 for the I2C port number + // sfp_port[0] is the first SFP-port from the left on the device, sfp_port[1] the next if present + struct sfp_port sfp_port[2]; + int8_t reset_pin; +}; + +#endif + diff --git a/rtl837x_port.c b/rtl837x_port.c index 1665cd1..bb96983 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -164,11 +164,8 @@ void vlan_setup(void) __banked vlan_names[0] = 0; // Initialize VLAN table for VLAN 1, by disabling that entry - if (machine.isRTL8373) { - REG_SET(RTL837x_TBL_DATA_IN_A, 0x0007ffff); - } else { - REG_SET(RTL837x_TBL_DATA_IN_A, 0x0007e3f8); - } + REG_SET(RTL837x_TBL_DATA_IN_A, machine.isRTL8373? 0x0007ffff : 0x0007e3f8); + REG_SET(RTL837X_TBL_CTRL, 0x00010303); do { reg_read_m(RTL837X_TBL_CTRL); @@ -211,11 +208,8 @@ void vlan_setup(void) __banked REG_SET(RTL837X_VLAN_L2_LRN_DIS_1, 0); // Enable VLAN 1: Ports 0-9, i.e. including the CPU port are untagged members - if (machine.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_DATA_IN_A, machine.isRTL8373? 0x0207ffff : 0x0207e3f8); // 02: Entry valid, 7...: membership + REG_SET(RTL837X_TBL_CTRL, 0x00010303); // Write VLAN 1 do { reg_read_m(RTL837X_TBL_CTRL); @@ -246,7 +240,7 @@ uint8_t port_l2_forget(void) __banked REG_SET(RTL837x_L2_TBL_FLUSH_CNF, 0x0); // Flush L2 table for all ports by setting the ports and the flush-exec bit (bit 16) - REG_SET(RTL837x_L2_TBL_FLUSH_CTRL, machine.isRTL8373 ? L2_TBL_FLUSH_EXEC | PMASK_9 : L2_TBL_FLUSH_EXEC | PMASK_6); + REG_SET(RTL837x_L2_TBL_FLUSH_CTRL, L2_TBL_FLUSH_EXEC | (machine.isRTL8373 ? PMASK_9 : PMASK_6)); // Wait for flush completed do { @@ -341,11 +335,7 @@ void port_l2_setup(void) __banked // All ports may communicate with each other and CPU-Port reg = RTL837X_PORT_ISOLATION_BASE + (i << 2); - if(machine.isRTL8373) { - REG_SET(reg, PMASK_9 | PMASK_CPU); - } else { - REG_SET(reg, PMASK_6 | PMASK_CPU); - } + REG_SET(reg, PMASK_CPU | (machine.isRTL8373? PMASK_9 : PMASK_6)); } // When maximim entries learned, then simply flood the packet reg_bit_set(RTL837X_L2_LRN_PORT_CONSTRT_ACT, 0); From edfb86bff46627d1eeb52581ca110ce411230be7 Mon Sep 17 00:00:00 2001 From: logicog Date: Fri, 12 Dec 2025 09:02:16 +0100 Subject: [PATCH 10/20] Use SFP pin definitions and I2C ports for SFP modules --- cmd_parser.c | 14 +++---- rtl837x_common.h | 2 + rtlplayground.c | 99 +++++++++++++++++++----------------------------- 3 files changed, 48 insertions(+), 67 deletions(-) diff --git a/cmd_parser.c b/cmd_parser.c index 5707612..92529ad 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -610,16 +610,16 @@ void cmd_parser(void) __banked print_string("\nRESET\n\n"); reset_chip(); } else if (cmd_compare(0, "sfp")) { - print_string("\nSlot 0 - Rate: "); print_byte(sfp_read_reg(0, 12)); + print_string("\nSlot 1 - Rate: "); print_byte(sfp_read_reg(0, 12)); print_string(" Encoding: "); print_byte(sfp_read_reg(0, 11)); print_string("\n"); sfp_print_info(0); -#if NSFP == 2 - print_string("\nSlot 1 - Rate: "); print_byte(sfp_read_reg(1, 12)); - print_string(" Encoding: "); print_byte(sfp_read_reg(1, 11)); - print_string("\n"); - sfp_print_info(1); -#endif + if (machine.n_sfp == 2) { + print_string("\nSlot 2 - Rate: "); print_byte(sfp_read_reg(1, 12)); + print_string(" Encoding: "); print_byte(sfp_read_reg(1, 11)); + print_string("\n"); + sfp_print_info(1); + } } else if (cmd_compare(0, "stat")) { port_stats_print(); } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'r') { diff --git a/rtl837x_common.h b/rtl837x_common.h index 016a85d..7b03e09 100644 --- a/rtl837x_common.h +++ b/rtl837x_common.h @@ -3,6 +3,7 @@ #include "uip/uip-conf.h" #include +#include // SCL and SDA pin numbers for SFP cage 0 and SFP cage 1 #define SCL_PIN 3 @@ -101,5 +102,6 @@ uint8_t read_flash(uint8_t bank, __code uint8_t *addr); void get_random_32(void); void read_reg_timer(uint32_t * tmr); void sfp_print_info(uint8_t sfp); +bool gpio_pin_test(uint8_t pin); #endif diff --git a/rtlplayground.c b/rtlplayground.c index 150032d..f3376b4 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -17,7 +17,7 @@ #include "uip/uip_arp.h" #include "machine.h" -extern __code struct machine machine; +extern __code const struct machine machine; extern __xdata uint16_t crc_value; __xdata uint8_t crc_testbytes[10]; @@ -674,9 +674,6 @@ void sds_config(uint8_t sds, uint8_t mode) uint8_t page = 0; uint16_t v = 0; - print_string("\nTrying to set SDS mode to 0x"); - print_byte(mode); - print_string("\n"); switch (mode) { case SDS_SGMII: @@ -747,7 +744,7 @@ void sds_config(uint8_t sds, uint8_t mode) */ uint8_t sfp_read_reg(uint8_t slot, uint8_t reg) { - if (slot == 0) { + if (machine.sfp_port[slot].i2c == 0) { reg_read_m(RTL837X_REG_I2C_CTRL); sfr_mask_data(1, 0xfc, SCL_PIN << 5 | SDA_PIN_0 << 2); reg_write_m(RTL837X_REG_I2C_CTRL); @@ -916,65 +913,47 @@ void sfp_print_info(uint8_t sfp) } +bool gpio_pin_test(uint8_t pin) +{ + reg_read_m(RTL837X_REG_GPIO_00_31_INPUT + (pin > 31 ? 4 : 0)); + return sfr_data[(pin >> 3) & 3] & (1 << (7 - (pin & 7))); +} + + void handle_sfp(void) { - reg_read_m(RTL837X_REG_GPIO_00_31_INPUT); - if ((sfp_pins_last & 0x1) && (!(sfr_data[0] & 0x40))) { - sfp_pins_last &= ~0x01; - print_string("\n "); - // Read Reg 11: Encoding, see SFF-8472 and SFF-8024 - // Read Reg 12: Signalling rate (including overhead) in 100Mbit: 0xd: 1Gbit, 0x67:10Gbit - delay(100); // Delay, because some modules need time to wake up - uint8_t rate = sfp_read_reg(0, 12); - print_string("Rate: "); print_byte(rate); // Normally 1, but 0 for DAC, can be ignored? - print_string(" Encoding: "); print_byte(sfp_read_reg(0, 11)); - print_string("\n"); - print_string("\n"); - sfp_print_info(0); - sds_config(1, sfp_rate_to_sds_config(rate)); - } - if ((!(sfp_pins_last & 0x1)) && (sfr_data[0] & 0x40)) { - sfp_pins_last |= 0x01; - print_string("\n\n"); - } - - reg_read_m(RTL837X_REG_GPIO_32_63_INPUT); - if ((sfp_pins_last & 0x2) && (!(sfr_data[3] & 0x20))) { - sfp_pins_last &= ~0x02; - print_string("\n\n"); - } - if ((!(sfp_pins_last & 0x2)) && (sfr_data[3] & 0x20)) { - sfp_pins_last |= 0x02; - print_string("\n\n"); - } - if (machine.n_sfp == 2) { - reg_read_m(RTL837X_REG_GPIO_32_63_INPUT); - if ((sfp_pins_last & 0x10) && (!(sfr_data[1] & 0x04))) { - sfp_pins_last &= ~0x10; - print_string("\n "); - // Read Reg 11: Encoding, see SFF-8472 and SFF-8024 - // Read Reg 12: Signalling rate (including overhead) in 100Mbit: 0xd: 1Gbit, 0x67:10Gbit - delay(100); // Delay, because some modules need time to wake up - uint8_t rate = sfp_read_reg(1, 12); - print_string("Rate: "); print_byte(rate); // Normally 1, but 0 for DAC, can be ignored? - print_string(" Encoding: "); print_byte(sfp_read_reg(1, 11)); - print_string("\n"); - sfp_print_info(1); - sds_config(0, sfp_rate_to_sds_config(rate)); - } - if ((!(sfp_pins_last & 0x10)) && (sfr_data[1] & 0x04)) { - sfp_pins_last |= 0x10; - print_string("\n\n"); + for (uint8_t sfp = 0; sfp < machine.n_sfp; sfp++) { + if (!gpio_pin_test(machine.sfp_port[sfp].pin_detect)) { + if (sfp_pins_last & (0x1 << (sfp << 2))) { + sfp_pins_last &= ~(0x01 << (sfp << 2)); + print_string("\n Slot: "); write_char('1' + sfp); + // Read Reg 11: Encoding, see SFF-8472 and SFF-8024 + // Read Reg 12: Signalling rate (including overhead) in 100Mbit: 0xd: 1Gbit, 0x67:10Gbit + delay(100); // Delay, because some modules need time to wake up + uint8_t rate = sfp_read_reg(sfp, 12); + print_string(" Rate: "); print_byte(rate); // Normally 1, but 0 for DAC, can be ignored? + print_string(" Encoding: "); print_byte(sfp_read_reg(sfp, 11)); + print_string(" Module: "); sfp_print_info(sfp); + print_string("\n"); + sds_config(machine.sfp_port[sfp].sds, sfp_rate_to_sds_config(rate)); + } + } else { + if (!(sfp_pins_last & (0x1 << (sfp << 2)))) { + sfp_pins_last |= 0x01 << (sfp << 2); + print_string("\n Slot: "); write_char('1' + sfp); write_char('\n'); + } } - reg_read_m(RTL837X_REG_GPIO_00_31_INPUT); - if ((sfp_pins_last & 0x20) && (!(sfr_data[2] & 0x08))) { - sfp_pins_last &= ~0x20; - print_string("\n\n"); - } - if ((!(sfp_pins_last & 0x20)) && (sfr_data[2] & 0x08)) { - sfp_pins_last |= 0x20; - print_string("\n\n"); + if (!gpio_pin_test(machine.sfp_port[sfp].pin_los)) { + if (sfp_pins_last & (0x2 << (sfp << 2))) { // 0x2 0x08 + sfp_pins_last &= ~(0x02 << (sfp << 2)); + print_string("\n Slot: "); write_char('1' + sfp); write_char('\n'); + } + } else { + if (!(sfp_pins_last & 0x2 << (sfp << 2))) { + sfp_pins_last |= 0x02 << (sfp << 2); + print_string("\n Slot: "); write_char('1' + sfp); write_char('\n'); + } } } } From a453ec72dca95e1c352c5cf89bd93c992e9b5b6e Mon Sep 17 00:00:00 2001 From: logicog Date: Fri, 12 Dec 2025 18:32:03 +0100 Subject: [PATCH 11/20] Use cached GPIO state --- httpd/page_impl.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 6ef1ccd..725ccd0 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -353,13 +353,7 @@ void send_status(void) if (machine.is_sfp[i]) { slen += strtox(outbuf + slen, ",\"isSFP\":1,\"enabled\":"); - if (i != 3) { - reg_read_m(RTL837X_REG_GPIO_00_31_INPUT); - bool_to_html(!(sfr_data[0] & 0x40)); - } else { - reg_read_m(RTL837X_REG_GPIO_32_63_INPUT); - bool_to_html(!(sfr_data[1] & 0x04)); - } + bool_to_html(!(sfp_pins_last & (0x1 << ((machine.is_sfp[i] - 1) << 2)))); } else { slen += strtox(outbuf + slen, ",\"isSFP\":0,\"enabled\":"); phy_read(i, 0x1f, 0xa610); From 1cdc8d2cf7007e79a8e5f1250ef4524e3590b52f Mon Sep 17 00:00:00 2001 From: logicog Date: Fri, 12 Dec 2025 22:05:42 +0100 Subject: [PATCH 12/20] De-Magic switch init --- rtl837x_regs.h | 26 ++++-- rtlplayground.c | 219 ++++++++++++++++++++---------------------------- 2 files changed, 111 insertions(+), 134 deletions(-) diff --git a/rtl837x_regs.h b/rtl837x_regs.h index 0888271..156d23f 100644 --- a/rtl837x_regs.h +++ b/rtl837x_regs.h @@ -1,18 +1,30 @@ #ifndef _RTL837X_REGS_H_ #define _RTL837X_REGS_H_ -#define RTL837X_REG_HW_CONF 0x6040 +#define RTL837X_REG_CHIP_INFO 0x000c +#define RTL837X_REG_RESET 0x0024 +#define RESET_SOC_BIT 0 +#define RESET_NIC_BIT 2 + +#define RTL837X_REG_HW_CONF 0x6040 // Bits 4 & 5: CLOCK DIVIDER from 125MHz for Timer -#define RTL837X_REG_LED_MODE 0x6520 +#define RTL837X_REG_LED_MODE 0x6520 // Defines the LED Mode for steering the Port LEDS and the System LED // BIT 17 set: LED solid on // Bytes 0/1 hold the LED mode, e.g. serial, RTL8231? // Blink rate is defined by setAsicRegBits(0x6520,0xe00000,rate); +#define RTL837X_REG_LED_GLB_IO_EN 0x65DC +#define RTL837X_REG_LED3_0_SET1 0x6528 +#define RTL837X_REG_LED3_2_SET0 0x6544 +#define RTL837X_REG_LED1_0_SET0 0x6548 -#define RTL837X_REG_SMI_CTRL 0x6454 -#define RTL837X_REG_RESET 0x0024 -// Writing 0x01 into this register causes a reset of the entire SoC +// SMI control +#define RTL837X_REG_SMI_PORT0_5_ADDR 0x644C +#define RTL837X_REG_SMI_PORT6_9_ADDR 0x6450 +#define RTL837X_REG_SMI_CTRL 0x6454 +#define RTL837X_REG_SMI_MAC_TYPE 0x6330 +#define RTL837X_REG_SMI_PORT_POLLING 0x6334 #define RTL837X_REG_SEC_COUNTER 0x06f4 #define RTL837X_REG_SEC_COUNTER2 0x06f8 @@ -47,6 +59,7 @@ #define RTL837X_PIN_MUX_0 0x7f8c #define RTL837X_PIN_MUX_1 0x7f90 +#define RTL837X_PIN_MUX_2 0x7f94 // Output Registers #define RTL837X_REG_GPIO_00_31_OUTPUT 0x3c @@ -178,6 +191,9 @@ #define RTL837X_RMA0_CONF 0x4ecc #define RTL837X_RMA_CONF 0x4f1c #define RTL837X_MSTP_STATES 0x5310 +#define RTL837X_REG_LED_RLDP_1 0x65F8 +#define RTL837X_REG_LED_RLDP_2 0x65FC +#define RTL837X_REG_LED_RLDP_3 0x65FC /* * EEE diff --git a/rtlplayground.c b/rtlplayground.c index f3376b4..2d983f3 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -1321,46 +1321,35 @@ void led_config_9xh(void) reg_bit_set(0x65d8, 0x1d); // r6520:0021fdb0 R6520-0021e7b0 r6520:0021e7b0 R6520-0021e6b0 - reg_read_m(0x6520); + reg_read_m(RTL837X_REG_LED_MODE); sfr_mask_data(1, 0x1f, 0x6); sfr_mask_data(0, 0xe0, 0xa0); - reg_write_m(0x6520); + reg_write_m(RTL837X_REG_LED_MODE); - // r65f8:00000018 R65f8-0000001b - reg_read_m(0x65f8); + // Disable RLDP (Realtek Loop Detection Protocol) LEDs on loop detection + reg_read_m(RTL837X_REG_LED_RLDP_1); sfr_mask_data(0, 0, 0x3); - reg_write_m(0x65f8); + reg_write_m(RTL837X_REG_LED_RLDP_1); + // Configure LED group for RLDP per port + REG_SET(RTL837X_REG_LED_RLDP_2, 0xffffffff); // Ports 0-7 + REG_SET(RTL837X_REG_LED_RLDP_3, 0x0000000f); // Port 8 - // R65fc-ffffffff - REG_SET(0x65fc, 0xffffffff); + reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 29); + reg_bit_clear(RTL837X_REG_LED_GLB_IO_EN, 27); - // Set bits 0-3 of 0x6600 to 0xf - // r6600:00000000 R6600-0000000f - reg_read_m(0x6600); - sfr_mask_data(0, 0, 0x0f); - reg_write_m(0x6600); + // GPIO 27 is LED + reg_bit_set(RTL837X_PIN_MUX_0, 27); - // Set bit 0x1d of 0x65dc, clear bit 1b: r65dc:5fffff00 R65dc-7fffff00 r65dc:7fffff00 R65dc-77ffff00 - reg_bit_set(0x65dc, 0x1d); - reg_bit_clear(0x65dc, 0x1b); - - // r7f8c:30000000 R7f8c-30000000 r7f8c:30000000 R7f8c-38000000 - reg_bit_set(RTL837X_PIN_MUX_0, 0x1b); - - // R6548-0041017f - REG_SET(0x6548, 0x0041017f); + // Configure LED_SET_0, ledid 0/1 + REG_SET(RTL837X_REG_LED1_0_SET0, 0x0041017f); // Configure LED_SET_0 ledid 2 - // r6544:01411000 R6544-01410044 - reg_read_m(0x6544); - sfr_data[2] = 0x00; - sfr_data[3] = 0x44; - reg_write_m(0x6544); + REG_SET(RTL837X_REG_LED3_2_SET0, 0x01410044); // r6528:00000000 R6528-0000000f - reg_read_m(0x6528); + reg_read_m(RTL837X_REG_LED3_0_SET1); sfr_mask_data(0, 0x0f, 0x0f); - reg_write_m(0x6528); + reg_write_m(RTL837X_REG_LED3_0_SET1); } @@ -1375,82 +1364,56 @@ void led_config(void) sfr_data[3] = 0xb0; reg_write_m(RTL837X_REG_LED_MODE); - // Clear bits 0,1 of 0x65f8 -// r65f8:00000018 R65f8-00000018 - reg_read_m(0x65f8); + // Disable RLDP (Realtek Loop Detection Protocol) LEDs on loop detection + reg_read_m(RTL837X_REG_LED_RLDP_1); sfr_mask_data(0, 0x03, 0); - reg_write_m(0x65f8); + reg_write_m(RTL837X_REG_LED_RLDP_1); + // Configure LED group for RLDP per port + REG_SET(RTL837X_REG_LED_RLDP_2, 0xffffffff); // Ports 0-7 + REG_SET(RTL837X_REG_LED_RLDP_3, 0x0000000f); // Port 8 - // Set 0x65fc to 0xfffff000 - // R65fc-fffff000 - REG_SET(0x65fc, 0xfffff000); + reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 29); + reg_bit_clear(RTL837X_REG_LED_GLB_IO_EN, 27); - // Set bits 0-3 of 0x6600 to 0xf - // r6600:00000000 R6600-0000000f - reg_read_m(0x6600); - sfr_mask_data(0, 0, 0x0f); - reg_write_m(0x6600); - - // Set bit 0x1d of 0x65dc, clear bit 1b: r65dc:5fffff00 R65dc-7fffff00 r65dc:7fffff00 R65dc-77ffff00 - reg_bit_set(0x65dc, 0x1d); - reg_bit_clear(0x65dc, 0x1b); - - // Set bits 1b/1d of 0x7f8c: r7f8c:30000000 R7f8c-30000000 r7f8c:30000000 R7f8c-38000000 + // Configure GPIO for LEDs 27-29 if (machine.n_sfp == 2) { - reg_bit_set(RTL837X_PIN_MUX_0, 0x1b); // R7f8c-28000000 - reg_bit_clear(RTL837X_PIN_MUX_0, 0x1c); // R7f8c-28000000 - reg_bit_set(RTL837X_PIN_MUX_0, 0x1d); // R7f8c-28000000 + reg_bit_set(RTL837X_PIN_MUX_0, 27); + reg_bit_clear(RTL837X_PIN_MUX_0, 28); + reg_bit_set(RTL837X_PIN_MUX_0, 29); } else { - reg_bit_set(RTL837X_PIN_MUX_0, 0x1d); - reg_bit_set(RTL837X_PIN_MUX_0, 0x1c); - reg_bit_set(RTL837X_PIN_MUX_0, 0x1b); + reg_bit_set(RTL837X_PIN_MUX_0, 27); + reg_bit_set(RTL837X_PIN_MUX_0, 28); + reg_bit_set(RTL837X_PIN_MUX_0, 29); } // LED setup // r6520:0021fdb0 R6520-0021e7b0 r6520:0021e7b0 R6520-0021e6b0 r65f8:00000018 R65f8-00000018 R65fc-fffff000 r6600:00000000 R6600-0000000f r65dc:5fffff00 R65dc-7fffff00 r65dc:7fffff00 R65dc-77ffff00 - // r7f8c:30000000 R7f8c-30000000 r7f8c:30000000 R7f8c-38000000 R6548-00410175 r6544:01411000 R6544-01410044 r6528:00000000 R6528-00000011 r6450:000020e6 R6450-000000e6 r644c:0a418820 R644c-0a400820 + // r7f8c:30000000 R7f8c-30000000 r7f8c:30000000 R7f8c-38000000 R6548-00410175 r6544:01411000 R6544-01410044 r6528:00000000 R6528-00000011 // Configure LED_SET_0, ledid 0/1 - // R6548-00410175 - REG_SET(0x6548, 0x00410175); + REG_SET(RTL837X_REG_LED1_0_SET0, 0x00410175); - // Configure LED_SET_0 ledid 2 - // 6544:01411000 R6544-01410044 - reg_read_m(0x6544); - sfr_data[2] = 0x00; - sfr_data[3] = 0x44; - reg_write_m(0x6544); + // Configure led-sets 2 and 3 + REG_SET(RTL837X_REG_LED3_2_SET0, 0x01410044); // Further configure LED_SET_0 // r6528:00000000 R6528-00000011 - reg_read_m(0x6528); + reg_read_m(RTL837X_REG_LED3_0_SET1); sfr_data[3] = 0x11; - reg_write_m(0x6528); - - reg_read_m(0x6450); - sfr_mask_data(1, 0x7c, 0); - reg_write_m(0x6450); - - // SDS bits f-13 set to 0: r644c:0a418820 R644c-0a400820 - reg_read_m(0x644c); - sfr_mask_data(2, 0x0f, 0); - sfr_mask_data(1, 0x80, 0); - reg_write_m(0x644c); + reg_write_m(RTL837X_REG_LED3_0_SET1); } void rtl8373_revision(void) { - // r000c:00300000 R000c-003a0000 r000c:203a6818 r000c:203a6818 R000c-20306818 - - reg_read_m(0x000c); + reg_read_m(RTL837X_REG_CHIP_INFO); sfr_mask_data(2, 0x0a, 0x0a); // Enable reading version - reg_write_m(0x000c); + reg_write_m(RTL837X_REG_CHIP_INFO); delay(50); - reg_read_m(0x000c); + reg_read_m(RTL837X_REG_CHIP_INFO); print_string("CPU revision: "); print_byte(sfr_data[2]); print_byte(sfr_data[2]); write_char('\n'); sfr_mask_data(2, 0x0a, 0x00); // Enable reading version - reg_write_m(0x000c); + reg_write_m(RTL837X_REG_CHIP_INFO); } @@ -1458,23 +1421,6 @@ void rtl8373_init(void) { print_string("\nrtl8373_init called\n"); - // r6330:00015555 R6330-00005555 r6330:00005555 R6330-00005555 - REG_SET(0x6330, 0x00005555); - - // r6334:00000000 R6334-000001f8 RTL8373: r6334:00000000 R6334-000000ff - reg_read_m(0x6334); // Also in sdsMode_set - sfr_mask_data(0, 0, 0xff); - reg_write_m(0x6334); - - // Enable MDC - // r6454:00000000 R6454-00007000 RTL837X_REG_SMI_CTRL - reg_read_m(RTL837X_REG_SMI_CTRL); - sfr_mask_data(1, 0, 0x70); // Set bits 0xc-0xe to enable MDC for SMI0-SMI2 - reg_write_m(RTL837X_REG_SMI_CTRL); - delay(50); - - rtl8373_revision(); - led_config_9xh(); sds_init(); // Disable all SERDES for configuration @@ -1528,10 +1474,12 @@ void rtl8373_init(void) // r0b7c:000000d8 R0b7c-000000f8 r6040:00000030 R6040-00000031 reg_bit_set(0xb7c, 5); - - // R7124-00001050 R7128-00001050 R712c-00001050 R7130-00001050 R7134-00001050 R7138-00001050 R713c-00001050 R7140-00001050 R7144-00001050 R7148-00001050 - REG_SET(0x7124, 0x1050); REG_SET(0x7128, 0x1050); REG_SET(0x712c, 0x1050); REG_SET(0x7130, 0x1050); REG_SET(0x7134, 0x1050); REG_SET(0x7138, 0x1050); REG_SET(0x713c, 0x1050); - REG_SET(0x7140, 0x1050); REG_SET(0x7144, 0x1050); REG_SET(0x7148, 0x1050); + // R7124-00001050 R7128-00001050 R712c-00001050 R7130-00001050 R7134-00001050 R7138-00001050 + // R713c-00001050 R7140-00001050 R7144-00001050 R7148-00001050 + REG_SET(0x7124, 0x1050); REG_SET(0x7128, 0x1050); REG_SET(0x712c, 0x1050); + REG_SET(0x7130, 0x1050); REG_SET(0x7134, 0x1050); REG_SET(0x7138, 0x1050); + REG_SET(0x713c, 0x1050); REG_SET(0x7140, 0x1050); REG_SET(0x7144, 0x1050); + REG_SET(0x7148, 0x1050); reg_bit_set(RTL837X_REG_HW_CONF, 0); @@ -1548,7 +1496,6 @@ void rtl8373_init(void) sfr_mask_data(2, 0x10, 0x1f); reg_write_m(0x632c); - REG_SET(0x7f94, 0); print_string("\nrtl8373_init done\n"); } @@ -1557,31 +1504,20 @@ void rtl8372_init(void) { print_string("\nrtl8372_init called\n"); - // r6330:00015555 R6330-00005555 r6330:00005555 R6330-00005555 - REG_SET(0x6330, 0x00005555); - if (machine.n_sfp == 2) { - print_string("Configuring 2nd SFP+ port\n"); - REG_SET(0x6330, 0x00005515); - } - - // r6334:00000000 R6334-000001f8 RTL8373: r6334:00000000 R6334-000000ff - reg_read_m(0x6334); // Also in sdsMode_set - if (machine.n_sfp == 2) { - sfr_mask_data(0, 0, 0xf0); - } else { - sfr_mask_data(1, 0, 0x01); // Set bits 3-8, On RTL8373+8224 set bits 0-7 - sfr_mask_data(0, 0, 0xf8); - } - reg_write_m(0x6334); - - // Enable MDC - // r6454:00000000 R6454-00007000 RTL837X_REG_SMI_CTRL - reg_read_m(RTL837X_REG_SMI_CTRL); - sfr_mask_data(1, 0, 0x70); // Set bits 0xc-0xe to enable MDC for SMI0-SMI2 - reg_write_m(RTL837X_REG_SMI_CTRL); - delay(50); - led_config(); + + // Change I2C addresses for SMI of the non-existent PHYs + // r6450:000020e6 R6450-000000e6 + reg_read_m(RTL837X_REG_SMI_PORT6_9_ADDR); + sfr_mask_data(1, 0x7c, 0); + reg_write_m(RTL837X_REG_SMI_PORT6_9_ADDR); + + // r644c:0a418820 R644c-0a400820 + reg_read_m(RTL837X_REG_SMI_PORT0_5_ADDR); + sfr_mask_data(2, 0x0f, 0); + sfr_mask_data(1, 0x80, 0); + reg_write_m(RTL837X_REG_SMI_PORT0_5_ADDR); + sds_init(); phy_config(8); // PHY configuration: External 8221B? phy_config(3); // PHY configuration: all internal PHYs? @@ -1638,6 +1574,29 @@ void rtl8372_init(void) } +void init_smi(void) +{ + print_string("\ninit_switch called\n"); + + /* Set the SMI(i.e.I2C) type for PHY polling, 0b01 is 2.5/10G PHY. Disable (0b00) for the SFP-ports + * which are at port 8 and additionally at port 3 for a dual SFP device + */ + REG_SET(RTL837X_REG_SMI_MAC_TYPE, machine.n_sfp == 2 ? 0x00005515 : 0x00005555); + + // Configure polling of all PHYs by the MAC to detect link-state changes + if (machine.isRTL8373) { + REG_SET(RTL837X_REG_SMI_PORT_POLLING, 0xff); + } else { + REG_SET(RTL837X_REG_SMI_PORT_POLLING, machine.n_sfp == 2 ? 0xf0 : 0x1f8); + } + // Enable MDC + reg_read_m(RTL837X_REG_SMI_CTRL); + sfr_mask_data(1, 0, 0x70); // Set bits 12-14 to enable MDC for SMI0-SMI2 + reg_write_m(RTL837X_REG_SMI_CTRL); + delay(50); +} + + /* Set up serial port 0 using Timer 2 with an external trigger * as baud generator. * The external clock generator uses a crystal at 25MHz. @@ -1733,17 +1692,19 @@ void bootloader(void) flash_init(0); // Reset NIC - reg_bit_set(0x24, 2); + reg_bit_set(RTL837X_REG_RESET, RESET_NIC_BIT); do { - reg_read(0x24); - } while (SFR_DATA_0 & 0x4); + reg_read(RTL837X_REG_RESET); + } while (SFR_DATA_0 & (1 << RESET_NIC_BIT)); print_string("NIC reset\n"); uip_ipaddr(&uip_hostaddr, ownIP[0], ownIP[1], ownIP[2], ownIP[3]); uip_ipaddr(&uip_draddr, gatewayIP[0], gatewayIP[1], gatewayIP[2], gatewayIP[3]); uip_ipaddr(&uip_netmask, netmask[0], netmask[1], netmask[2], netmask[3]); - REG_SET(0x7f94, 0x0); + REG_SET(RTL837X_PIN_MUX_2, 0x0); // Disable pins for ACL + init_smi(); + rtl8373_revision(); if (machine.isRTL8373) rtl8373_init(); else From e6cf97b895f534928b9028c171b5b56a9dcf45ee Mon Sep 17 00:00:00 2001 From: logicog Date: Fri, 12 Dec 2025 22:06:19 +0100 Subject: [PATCH 13/20] Support keeplink 5+1 device --- machine.c | 58 +++++++++++++++++++++++++++++++++++++++++-------------- machine.h | 4 +++- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/machine.c b/machine.c index 597ec18..0220b0c 100644 --- a/machine.c +++ b/machine.c @@ -1,8 +1,8 @@ #include "machine.h" -#ifdef MACHINE_KL_9000_6XHML_X2 +#ifdef MACHINE_KP_9000_6XHML_X2 __code const struct machine machine = { - .machine_name = "keepLink KL-9000-6XHML-X2", + .machine_name = "keepLink KP-9000-6XHML-X2", .isRTL8373 = 0, .min_port = 3, .max_port = 8, @@ -10,18 +10,47 @@ __code const struct machine machine = { .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, .is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1}, - .sfp_port[0].pin_detect = 45, - .sfp_port[0].pin_los = 21, + .sfp_port[0].pin_detect = 50, + .sfp_port[0].pin_los = 10, .sfp_port[0].sds = 1, .sfp_port[0].i2c = 1, - .sfp_port[1].pin_detect = 1, - .sfp_port[1].pin_los = 58, + .sfp_port[1].pin_detect = 30, + .sfp_port[1].pin_los = 37, .sfp_port[1].sds = 0, .sfp_port[1].i2c = 0, - .reset_pin = 49, + .reset_pin = 46, }; - -#elif MACHINE_SWGT024_V2_0 +#elif defined MACHINE_KP_9000_6XH_X +__code const struct machine machine = { + .machine_name = "keepLink KP-9000-6XH-X", + .isRTL8373 = 0, + .min_port = 3, + .max_port = 8, + .n_sfp = 1, + .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, + .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, + .is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1}, + .sfp_port[0].pin_detect = 30, + .sfp_port[0].pin_los = 37, + .sfp_port[0].sds = 1, + .sfp_port[0].i2c = 0, +}; +#elif defined MACHINE_KP_9000_9XH_X_EU +__code const struct machine machine = { + .machine_name = "keepLink KP-9000-6XH-X-EU", + .isRTL8373 = 1, + .min_port = 0, + .max_port = 8, + .n_sfp = 1, + .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, + .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, + .is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1}, + .sfp_port[0].pin_detect = 30, + .sfp_port[0].pin_los = 37, + .sfp_port[0].sds = 1, + .sfp_port[0].i2c = 0, +}; +#elif defined MACHINE_SWGT024_V2_0 __code const struct machine machine = { .machine_name = "SWGT024 V2.0", .isRTL8373 = 0, @@ -40,19 +69,20 @@ __code const struct machine machine = { .sfp_port[1].sds = 0, .sfp_port[1].i2c = 0, }; -#elif DEFAULT_8C_1SFP +#elif defined DEFAULT_8C_1SFP __code const struct machine machine = { - .machine_name = "9-Port Switch", + .machine_name = "8+1 SFP Port Switch", .isRTL8373 = 1, .min_port = 0, .max_port = 8, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, - .is_sfp= {0, 0, 0, 0, 0, 0, 0, 0, 1}, - .sfp_port[0].pin_detect = 1, - .sfp_port[0].pin_los = 58, + .is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1}, + .sfp_port[0].pin_detect = 30, + .sfp_port[0].pin_los = 37, .sfp_port[0].sds = 1, + .sfp_port[0].i2c = 0, }; #endif diff --git a/machine.h b/machine.h index a5400a4..aa518bd 100644 --- a/machine.h +++ b/machine.h @@ -6,7 +6,9 @@ /* * Select your machine type below */ -#define MACHINE_KL_9000_6XHML_X2 +#define MACHINE_KP_9000_6XHML_X2 +// #define MACHINE_KP_9000_6XH_X +// #define MACHINE_KP_9000_9XH_X_EU // #define MACHINE_SWGT024_V2_0 // #define MACHINE_HORACO_ZX_SG4T2 From 74364ed7e89a9779b5b55d75a2f0a484972430c0 Mon Sep 17 00:00:00 2001 From: logicog Date: Fri, 12 Dec 2025 23:31:44 +0100 Subject: [PATCH 14/20] Add machine name in send_basic_info() --- httpd/page_impl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 725ccd0..0b97815 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -176,8 +176,9 @@ void send_basic_info(void) byte_to_html(uip_ethaddr.addr[5]); slen += strtox(outbuf + slen, "\",\"sw_ver\":\""); slen += strtox(outbuf + slen, VERSION_SW); - slen += strtox(outbuf + slen, "\",\"hw_ver\":\"SWGT024-V2.0\""); - slen += strtox(outbuf + slen, ",\"sfp_slot_0\":\""); + slen += strtox(outbuf + slen, "\",\"hw_ver\":\""); + slen += strtox(outbuf + slen, machine.machine_name); + slen += strtox(outbuf + slen, "\",\"sfp_slot_0\":\""); send_sfp_info(0); char_to_html('"'); if (machine.n_sfp == 2) { From d71a303f6c20649420e948e37c1bb5895b86ac9a Mon Sep 17 00:00:00 2001 From: logicog Date: Sat, 13 Dec 2025 08:58:21 +0100 Subject: [PATCH 15/20] Move RTL8372 SMI address configuration --- rtlplayground.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/rtlplayground.c b/rtlplayground.c index 2d983f3..2fd7dd7 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -1506,18 +1506,6 @@ void rtl8372_init(void) led_config(); - // Change I2C addresses for SMI of the non-existent PHYs - // r6450:000020e6 R6450-000000e6 - reg_read_m(RTL837X_REG_SMI_PORT6_9_ADDR); - sfr_mask_data(1, 0x7c, 0); - reg_write_m(RTL837X_REG_SMI_PORT6_9_ADDR); - - // r644c:0a418820 R644c-0a400820 - reg_read_m(RTL837X_REG_SMI_PORT0_5_ADDR); - sfr_mask_data(2, 0x0f, 0); - sfr_mask_data(1, 0x80, 0); - reg_write_m(RTL837X_REG_SMI_PORT0_5_ADDR); - sds_init(); phy_config(8); // PHY configuration: External 8221B? phy_config(3); // PHY configuration: all internal PHYs? @@ -1574,6 +1562,13 @@ void rtl8372_init(void) } +/* + * The SoC manages Link-State for steering the LEDs and can set PHY-settings + * automatically through Realtek's SMI (Simple Managagement) Interface, a + * proprietary version of MDIO which for example allows for more PHYs on the same + * bus. + * Configure polling via SMI and the interface setup during boot. + */ void init_smi(void) { print_string("\ninit_switch called\n"); @@ -1594,6 +1589,20 @@ void init_smi(void) sfr_mask_data(1, 0, 0x70); // Set bits 12-14 to enable MDC for SMI0-SMI2 reg_write_m(RTL837X_REG_SMI_CTRL); delay(50); + + if (!machine.isRTL8373) { + // Change I2C addresses for SMI of the non-existent PHYs + // r6450:000020e6 R6450-000000e6 + reg_read_m(RTL837X_REG_SMI_PORT6_9_ADDR); + sfr_mask_data(1, 0x7c, 0); + reg_write_m(RTL837X_REG_SMI_PORT6_9_ADDR); + + // r644c:0a418820 R644c-0a400820 + reg_read_m(RTL837X_REG_SMI_PORT0_5_ADDR); + sfr_mask_data(2, 0x0f, 0); + sfr_mask_data(1, 0x80, 0); + reg_write_m(RTL837X_REG_SMI_PORT0_5_ADDR); + } } From 28f832a24d6ccb57ac123bde6fb35ecbc263e3e8 Mon Sep 17 00:00:00 2001 From: logicog Date: Sat, 13 Dec 2025 18:13:03 +0100 Subject: [PATCH 16/20] Fix PHY issues --- rtl837x_phy.c | 10 +++++----- rtlplayground.c | 5 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/rtl837x_phy.c b/rtl837x_phy.c index 780f6d3..cd87850 100644 --- a/rtl837x_phy.c +++ b/rtl837x_phy.c @@ -119,7 +119,7 @@ void phy_config(uint8_t phy) __banked // p031f.a442:043c P000008.1f00a442:0430 // Unknown, but clear bits 2/3 - phy_modify(phy, 0x1f, 0xa442, 0x0006, 0x0000); + phy_modify(phy, 0x1f, 0xa442, 0x000c, 0x0000); delay(20); // P000100.1e0075b5:e084 @@ -202,8 +202,8 @@ void phy_set_mode(uint8_t port, uint8_t speed, uint8_t flow_control, uint8_t dup // AN Advertisement Register (MMD 7.0x0010) phy_write(port, PHY_MMD_AN, 0x10, 0x1001); // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) - phy_write(port, PHY_MMD_AN, 0x20, 0x6081); // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed - phy_write(port, PHY_MMD_AN, 0x00, 0x3200); // Restart AN + phy_write(port, 0x07, 0x20, 0x6081); // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timing enabled + phy_write(port, 0x07, 0x00, 0x3200); // Restart AN } else { // AN Control Register (MMD 7.0x0000) phy_write(port, PHY_MMD_AN, 0x00, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13) @@ -213,12 +213,12 @@ void phy_set_mode(uint8_t port, uint8_t speed, uint8_t flow_control, uint8_t dup // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) phy_write(port, PHY_MMD_AN, 0x20, 0x6001); // bit 14: SLAVE, bit 13: Multi-Port device, 1: LD Loop timin enableed // GBCR (1000Base-T Control Register, MMD 31.0xA412) - phy_modify(port, 0x1f, 0xa412, 0x0000, 0x02000); + phy_modify(port, 0x1f, 0xa412, 0x0000, 0x0200); } else if (speed == PHY_SPEED_2G5) { // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) phy_write(port, PHY_MMD_AN, 0x20, 0x6081); // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed // GBCR (1000Base-T Control Register, MMD 31.0xA412) - phy_modify(port, 0x1f, 0xa412, 0x02000, 0x0000); + phy_modify(port, 0x1f, 0xa412, 0x0200, 0x0000); } phy_write(port, PHY_MMD_AN, 0x00, 0x3200); // Enable AN } diff --git a/rtlplayground.c b/rtlplayground.c index 2fd7dd7..e891ec9 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -1215,12 +1215,13 @@ void phy_modify(uint8_t phy_id, uint8_t dev_id, uint16_t reg, uint16_t mask, uin // Modify the reed data. // TODO: Check if we directly can modify SFR register directly. uint16_t data = SFR_DATA_U16 & ~(mask); - data |= ~(set); + data |= set; uint16_t phy_mask = bit_mask[phy_id]; // Write it back - SFR_SMI_REG_U16 = data; + SFR_SMI_REG_U16 = reg; + SFR_DATA_U16 = data; SFR_SMI_PHYMASK = phy_mask; // SFR_C5 SFR_SMI_DEV = smi_phy | (phy_mask >> 8); SFR_EXEC_GO = SFR_EXEC_WRITE_SMI; From 11d2c843e529dfb9168ae0b44f83d9b31f539b6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Fri, 12 Dec 2025 22:25:16 +0100 Subject: [PATCH 17/20] Fixed to make SWGT024 V2.0 work --- machine.c | 17 +++++++++-------- rtlplayground.c | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/machine.c b/machine.c index 0220b0c..d82e507 100644 --- a/machine.c +++ b/machine.c @@ -60,14 +60,15 @@ __code const struct machine machine = { .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 6, 5, 7, 3, 8, 0, 0, 0}, .is_sfp= {0, 0, 0, 2, 0, 0, 0, 0, 1}, - .sfp_port[0].pin_detect = 1, - .sfp_port[0].pin_los = 58, - .sfp_port[0].sds = 1, - .sfp_port[0].i2c = 1, - .sfp_port[1].pin_detect = 45, - .sfp_port[1].pin_los = 21, - .sfp_port[1].sds = 0, - .sfp_port[1].i2c = 0, + .sfp_port[0].pin_detect = 30, + .sfp_port[0].pin_los = 37, + .sfp_port[0].sds = 0, + .sfp_port[0].i2c = 0, + .sfp_port[1].pin_detect = 50, + .sfp_port[1].pin_los = 51, + .sfp_port[1].sds = 1, + .sfp_port[1].i2c = 1, + .reset_pin = 36, }; #elif defined DEFAULT_8C_1SFP __code const struct machine machine = { diff --git a/rtlplayground.c b/rtlplayground.c index e891ec9..052498e 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -916,7 +916,7 @@ void sfp_print_info(uint8_t sfp) bool gpio_pin_test(uint8_t pin) { reg_read_m(RTL837X_REG_GPIO_00_31_INPUT + (pin > 31 ? 4 : 0)); - return sfr_data[(pin >> 3) & 3] & (1 << (7 - (pin & 7))); + return sfr_data[3-((pin >> 3) & 3)] & (1 << (pin & 7)); } From 2ed9974c0450118342f59dcc393a097a1614a408 Mon Sep 17 00:00:00 2001 From: logicog Date: Sun, 14 Dec 2025 11:41:50 +0100 Subject: [PATCH 18/20] Add more options to Link configuration and status display --- cmd_parser.c | 63 +++++++++++----- phy.h | 1 + rtl837x_phy.c | 197 ++++++++++++++++++++++++++++++++++++++++++++------ rtl837x_phy.h | 14 +++- 4 files changed, 231 insertions(+), 44 deletions(-) diff --git a/cmd_parser.c b/cmd_parser.c index 92529ad..4d1e350 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -409,6 +409,49 @@ void parse_mirror(void) } +void parse_port(void) +{ + print_string("\nPORT "); + uint8_t p = cmd_buffer[cmd_words_b[1]] - '1'; + p = machine.phys_to_log_port[p]; + print_byte(p); + if (cmd_words_b[2] > 0 && cmd_compare(2, "10m")) { + print_string(" 10M\n"); + phy_set_speed(p, PHY_SPEED_10M); + } + if (cmd_words_b[2] > 0 && cmd_compare(2, "100m")) { + print_string(" 100M\n"); + phy_set_speed(p, PHY_SPEED_100M); + } + if (cmd_words_b[2] > 0 && cmd_compare(2, "2g5")) { + print_string(" 2.5G\n"); + phy_set_speed(p, PHY_SPEED_2G5); + } + if (cmd_words_b[2] > 0 && cmd_compare(2, "1g")) { + print_string(" 1G\n"); + phy_set_speed(p, PHY_SPEED_1G); + } + if (cmd_words_b[2] > 0 && cmd_compare(2, "auto")) { + print_string(" AUTO\n"); + phy_set_speed(p, PHY_SPEED_AUTO); + } + if (cmd_words_b[2] > 0 && cmd_compare(2, "off")) { + print_string(" OFF\n"); + phy_set_speed(p, PHY_OFF); + } + if (cmd_words_b[2] > 0 && cmd_compare(2, "duplex")) { + print_string(" DUPLEX\n"); + if (cmd_words_b[3] > 0 && cmd_compare(3, "full")) + phy_set_duplex(p, 1); + else + phy_set_duplex(p, 0); + } + if (cmd_words_b[2] > 0 && cmd_compare(2, "show")) { + phy_show(p); + } +} + + void parse_regget(void) { uint16_t reg = 0; @@ -664,25 +707,7 @@ void cmd_parser(void) __banked flash_region.len = 20; flash_write_bytes(flash_buf); } else if (cmd_compare(0, "port") && cmd_words_b[1] > 0) { - print_string("\nPORT "); - uint8_t p = cmd_buffer[cmd_words_b[1]] - '1'; - print_byte(p); - if (cmd_words_b[2] > 0 && cmd_compare(2, "2g5")) { - print_string(" 2.5G\n"); - phy_set_mode(p, PHY_SPEED_2G5, 0, 0); - } - if (cmd_words_b[2] > 0 && cmd_compare(2, "1g")) { - print_string(" 1G\n"); - phy_set_mode(p, PHY_SPEED_1G, 0, 0); - } - if (cmd_words_b[2] > 0 && cmd_compare(2, "auto")) { - print_string(" AUTO\n"); - phy_set_mode(p, PHY_SPEED_AUTO, 0, 0); - } - if (cmd_words_b[2] > 0 && cmd_compare(2, "off")) { - print_string(" OFF\n"); - phy_set_mode(p, PHY_OFF, 0, 0); - } + parse_port(); } else if (cmd_compare(0, "ip")) { print_string("Got ip command: "); if (!parse_ip(cmd_words_b[1])) diff --git a/phy.h b/phy.h index e73edd4..38eb088 100644 --- a/phy.h +++ b/phy.h @@ -11,6 +11,7 @@ /* * Define PHY pages */ +#define PHY_MMD_PMAPMD 1 #define PHY_MMD_AN 7 #define PHY_SDS_CTRL 30 #define PHY_MMD_CTRL 31 diff --git a/rtl837x_phy.c b/rtl837x_phy.c index cd87850..a387ce1 100644 --- a/rtl837x_phy.c +++ b/rtl837x_phy.c @@ -182,49 +182,204 @@ void phy_config_8224(void) __banked /* - * Set Speed, duplex and flow control mode of a PHY + * Set Speed of a PHY * See e.g. RTL8221B datasheet */ -void phy_set_mode(uint8_t port, uint8_t speed, uint8_t flow_control, uint8_t duplex) __banked +void phy_set_speed(uint8_t port, uint8_t speed) __banked { uint16_t v; - phy_read(port, 0x1f, 0xa610); + phy_read(port, PHY_MMD_CTRL, 0xa610); v = SFR_DATA_U16; if (speed == PHY_OFF) { - phy_write(port, 0x1f, 0xa610, v | 0x0800); + phy_write(port, PHY_MMD_CTRL, 0xa610, v | 0x0800); return; } // Port is on, make sure of it: if (v & 0x0800) - phy_write(port, 0x1f, 0xa610, v & 0xf7ff); + phy_write(port, PHY_MMD_CTRL, 0xa610, v & 0xf7ff); if (speed == PHY_SPEED_AUTO) { // AN Advertisement Register (MMD 7.0x0010) - phy_write(port, PHY_MMD_AN, 0x10, 0x1001); // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used + // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used + phy_write(port, PHY_MMD_AN, 0x10, 0x15e1); // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) - phy_write(port, 0x07, 0x20, 0x6081); // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timing enabled - phy_write(port, 0x07, 0x00, 0x3200); // Restart AN + // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD + phy_write(port, PHY_MMD_AN, 0x20, 0x6081); + // GBCR (1000Base-T Control Register, MMD 31.0xA412) + phy_modify(port, PHY_MMD_CTRL, 0xa412, 0x0000, 0x0200); // Loop timing enabled + phy_write(port, PHY_MMD_AN, 0x00, 0x3200); // Restart AN } else { // AN Control Register (MMD 7.0x0000) phy_write(port, PHY_MMD_AN, 0x00, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13) - // AN Advertisement Register (MMD 7.0x0010) - phy_write(port, PHY_MMD_AN, 0x10, 0x1001); // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used - if (speed == PHY_SPEED_1G) { - // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) - phy_write(port, PHY_MMD_AN, 0x20, 0x6001); // bit 14: SLAVE, bit 13: Multi-Port device, 1: LD Loop timin enableed - // GBCR (1000Base-T Control Register, MMD 31.0xA412) - phy_modify(port, 0x1f, 0xa412, 0x0000, 0x0200); - } else if (speed == PHY_SPEED_2G5) { - // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) - phy_write(port, PHY_MMD_AN, 0x20, 0x6081); // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed - // GBCR (1000Base-T Control Register, MMD 31.0xA412) - phy_modify(port, 0x1f, 0xa412, 0x0200, 0x0000); + if (speed == PHY_SPEED_10M) { + phy_write(port, PHY_MMD_AN, 0x20, 0x6001); + phy_write(port, PHY_MMD_AN, 0x10, 0x1461); + phy_modify(port, PHY_MMD_CTRL, 0xa412, 0x0200, 0x0000); + } else if (speed == PHY_SPEED_100M) { + phy_write(port, PHY_MMD_AN, 0x20, 0x6001); + phy_write(port, PHY_MMD_AN, 0x10, 0x1581); + phy_modify(port, PHY_MMD_CTRL, 0xa412, 0x0200, 0x0000); + } else { + // AN Advertisement Register (MMD 7.0x0010) + // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used + phy_write(port, PHY_MMD_AN, 0x10, 0x1001); + if (speed == PHY_SPEED_1G) { + // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) + // bit 14: SLAVE, bit 13: Multi-Port device, 1: LD Loop timin enableed + phy_write(port, PHY_MMD_AN, 0x20, 0x6001); + // GBCR (1000Base-T Control Register, MMD 31.0xA412) + phy_modify(port, PHY_MMD_CTRL, 0xa412, 0x0000, 0x0200); + } else if (speed == PHY_SPEED_2G5) { + // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) + // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed + phy_write(port, PHY_MMD_AN, 0x20, 0x6081); + // GBCR (1000Base-T Control Register, MMD 31.0xA412) + phy_modify(port, PHY_MMD_CTRL, 0xa412, 0x0200, 0x0000); + } } - phy_write(port, PHY_MMD_AN, 0x00, 0x3200); // Enable AN + phy_write(port, PHY_MMD_AN, 0x00, 0x3000); // Enable AN } } +void phy_set_duplex(uint8_t port, uint8_t fullduplex) __banked +{ + uint16_t v; + phy_read(port, PHY_MMD_AN, 0x00); + v = SFR_DATA_U16; + if (!(v & 0x1000)) { // AN disabled, we are in forced mode + phy_read(port, PHY_MMD_CTRL, 0xa400); + v = SFR_DATA_U16; + if (fullduplex) + v |= 0x0100; + else + v &= 0xfeff; + phy_write(port, PHY_MMD_CTRL, 0xa400, v); + return; + } + // Disable AN + phy_write(port, PHY_MMD_AN, 0x00, 0x2000); + phy_read(port, PHY_MMD_AN, 0x10); + v = SFR_DATA_U16; + if (v & 0x0060) { + if (fullduplex) + phy_modify(port, PHY_MMD_AN, 0x10, 0xffbf, 0x0040); + else + phy_modify(port, PHY_MMD_AN, 0x10, 0xffdf, 0x0020); + } + if (v & 0x0180) { + if (fullduplex) + phy_modify(port, PHY_MMD_AN, 0x10, 0xfeff, 0x0100); + else + phy_modify(port, PHY_MMD_AN, 0x10, 0xff7f, 0x0080); + } + // Restart AN + phy_write(port, PHY_MMD_AN, 0x00, 0x3000); +} + + +void phy_show(uint8_t port) __banked +{ + uint16_t v; + + phy_read(port, PHY_MMD_AN, 0x00); + v = SFR_DATA_U16; + if (!(v & 0x1000)) { // AN disabled, we are in forced mode + phy_read(port, PHY_MMD_PMAPMD, 0); + v = SFR_DATA_U16; + print_string("\nForced speed: "); print_short(v); write_char('\n'); + uint8_t s1 = ((v & 0x40) ? 0x2 : 0x0) | ((v & 0x2000) ? 0x1 : 0x0); + uint8_t s2 = (v >> 2) & 0xf; + print_string("s1, s2: "); print_byte(s1); write_char(' '); print_byte(s2); write_char('\n'); + switch(s1) { + case 0: + print_string("10M\n"); + break; + case 1: + print_string("100M\n"); + break; + case 2: + print_string("1000M\n"); + break; + case 3: + switch (s2) { + case 0: + print_string("10G\n"); + break; + case 6: + print_string("2500M\n"); + break; + case 7: + print_string("5G\n"); + break; + default: + print_string("Unknown\n"); + break; + } + break; + default: + print_string("Unknown\n"); + } + phy_read(port, PHY_MMD_CTRL, 0xa400); + v = SFR_DATA_U16; + print_string("Duplex: "); print_short(v); print_string(" enabled: "); + if (v & 0x100) + print_string("yes"); + else + print_string("no"); + write_char('\n'); + + } else { + print_string("\nAN enabled, advertising:"); + phy_read(port, PHY_MMD_AN, 0x10); + v = SFR_DATA_U16; + if (v & 0x0040) + print_string(" 10Base-Half"); + if (v & 0x0040) + print_string(" 10Base-Full"); + if (v & 0x0080) + print_string(" 100Base-Half"); + if (v & 0x0100) + print_string(" 100Base-Full"); + phy_read(port, PHY_MMD_CTRL, 0xa412); + v = SFR_DATA_U16; + if (v & 0x0200) + print_string(" 1000Base-Full"); + phy_read(port, PHY_MMD_AN, 0x10); + v = SFR_DATA_U16; + if (v & 0x0080) + print_string(" 2500BaseN-Full"); + + } + phy_read(port, PHY_MMD_AN, 0x13); + v = SFR_DATA_U16; + print_string("\nLink Partner advertises:"); + if (v & 0x0020) + print_string(" 10Base-Half"); + if (v & 0x0040) + print_string(" 10Base-Full"); + if (v & 0x0080) + print_string(" 100Base-Half"); + if (v & 0x0100) + print_string(" 100Base-Full"); + phy_read(port, PHY_MMD_CTRL, 0xa414); + v = SFR_DATA_U16; + if (v & 0x0400) + print_string(" 1000Base-Half"); + if (v & 0x0800) + print_string(" 1000Base-Full"); + phy_read(port, PHY_MMD_AN, 33); + v = SFR_DATA_U16; + if (v & 0x0020) + print_string(" 2500Base-Full"); + if (v & 0x0040) + print_string(" 5000Base-Full"); + if (v & 0x0800) + print_string(" 10GBase-Full"); + write_char('\n'); +} + + void phy_reset(uint8_t port) __banked { uint16_t v; diff --git a/rtl837x_phy.h b/rtl837x_phy.h index fac191c..49a13c6 100644 --- a/rtl837x_phy.h +++ b/rtl837x_phy.h @@ -1,15 +1,21 @@ #ifndef _RTL837X_PHY_H_ #define _RTL837X_PHY_H_ -#define PHY_SPEED_AUTO 0x1 -#define PHY_SPEED_1G 0x2 -#define PHY_SPEED_2G5 0x3 +#define PHY_SPEED_10M 0x2 +#define PHY_SPEED_100M 0x3 +#define PHY_SPEED_1G 0x4 +#define PHY_SPEED_2G5 0x5 +#define PHY_SPEED_5G 0x6 +#define PHY_SPEED_10G 0x7 +#define PHY_SPEED_AUTO 0x10 #define PHY_OFF 0xff void rtl8224_phy_enable(void) __banked; void phy_config(uint8_t phy) __banked; void phy_config_8224(void) __banked; -void phy_set_mode(uint8_t port, uint8_t speed, uint8_t flow_control, uint8_t duplex) __banked; +void phy_set_speed(uint8_t port, uint8_t speed) __banked; +void phy_set_duplex(uint8_t port, uint8_t fullduplex) __banked; +void phy_show(uint8_t port) __banked; void phy_reset(uint8_t port) __banked; #endif From 0197c9b6cf9fd780d7d198e421738fc2ede943cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Fri, 12 Dec 2025 22:25:16 +0100 Subject: [PATCH 19/20] Fixed to make SWGT024 V2.0 work --- doc/devices/SWTG024AS.md | 11 +++++++++++ machine.c | 10 ++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/doc/devices/SWTG024AS.md b/doc/devices/SWTG024AS.md index 5c7e40a..6554e7b 100644 --- a/doc/devices/SWTG024AS.md +++ b/doc/devices/SWTG024AS.md @@ -34,6 +34,12 @@ Changes I found with my board vs [Managed version](https://github.com/up-n-atom/ We need to make a `Best`-BOM variant so we can use all the featues. # Connectors + +## J4 + +* Location: Left SFP connector `J4`. +* Connected to: 10GMAC number 8, second SDS. + |`J4` SFP1 PINs | Signal | Component | GPIO | Notes | |---|---|---|---|---| |2| TX_FAULT | B-R262 | --- | | @@ -45,6 +51,11 @@ Changes I found with my board vs [Managed version](https://github.com/up-n-atom/ |8| LOS | B-R258, T-R270 | GPIO37 | | |9| TO? | B-R256 | --- | | +## J2 + +* Location: Right SFP connector `J2`. +* Connected to: 10GMAC number 3, first SDS. + |`J2` SFP2 PINs | Signal | Component | GPIO | Notes | |---|---|---|---|---| |2| TX_FAULT | B-R70 | --- | | diff --git a/machine.c b/machine.c index d82e507..d0275a1 100644 --- a/machine.c +++ b/machine.c @@ -60,14 +60,16 @@ __code const struct machine machine = { .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 6, 5, 7, 3, 8, 0, 0, 0}, .is_sfp= {0, 0, 0, 2, 0, 0, 0, 0, 1}, + // Left SFP port (J4) .sfp_port[0].pin_detect = 30, .sfp_port[0].pin_los = 37, - .sfp_port[0].sds = 0, - .sfp_port[0].i2c = 0, + .sfp_port[0].sds = 1, + .sfp_port[0].i2c = 0, /* GPIO 39 */ + // Right SFP port (J2) .sfp_port[1].pin_detect = 50, .sfp_port[1].pin_los = 51, - .sfp_port[1].sds = 1, - .sfp_port[1].i2c = 1, + .sfp_port[1].sds = 0, + .sfp_port[1].i2c = 1, /* GPIO 40 */ .reset_pin = 36, }; #elif defined DEFAULT_8C_1SFP From b41452026f6346461dae981408d825ec0574eb28 Mon Sep 17 00:00:00 2001 From: logicog Date: Sun, 14 Dec 2025 12:17:53 +0100 Subject: [PATCH 20/20] Make sure port is not called for an SFP module --- cmd_parser.c | 4 ++++ rtl837x_phy.c | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd_parser.c b/cmd_parser.c index 4d1e350..f59c427 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -415,6 +415,10 @@ void parse_port(void) uint8_t p = cmd_buffer[cmd_words_b[1]] - '1'; p = machine.phys_to_log_port[p]; print_byte(p); + if (machine.is_sfp[p]) { + print_string(" is SFP no PHY information available.\n"); + return; + } if (cmd_words_b[2] > 0 && cmd_compare(2, "10m")) { print_string(" 10M\n"); phy_set_speed(p, PHY_SPEED_10M); diff --git a/rtl837x_phy.c b/rtl837x_phy.c index a387ce1..a535a06 100644 --- a/rtl837x_phy.c +++ b/rtl837x_phy.c @@ -290,7 +290,6 @@ void phy_show(uint8_t port) __banked print_string("\nForced speed: "); print_short(v); write_char('\n'); uint8_t s1 = ((v & 0x40) ? 0x2 : 0x0) | ((v & 0x2000) ? 0x1 : 0x0); uint8_t s2 = (v >> 2) & 0xf; - print_string("s1, s2: "); print_byte(s1); write_char(' '); print_byte(s2); write_char('\n'); switch(s1) { case 0: print_string("10M\n");