From 340fdd97e5f9ee7ceaca1d36775a7e53d3b61a3b Mon Sep 17 00:00:00 2001 From: d00f <8052722+DrDoof@users.noreply.github.com> Date: Tue, 22 Sep 2026 20:28:54 +0200 Subject: [PATCH] port: report link role and negotiated pause per port Two per-port MAC status registers that nothing in the firmware reads: 0x6408 says which end is master on a BASE-T link, 0x63FC and 0x6400 say whether pause was negotiated in each direction. port show prints both at the end. The read sits in rtl837x_port.c rather than phy_show(), because these are MAC registers and phy_show() is skipped for SFP ports. Master/slave keys off machine.is_sfp[] so it stays off the fibre ports, where the notion does not apply. Bit N of each register is chip port N, which is not how RTL837X_REG_LINKS_STS indexes its bytes a few lines above in the same header. --- cmd_parser.c | 3 +++ rtl837x_port.c | 32 ++++++++++++++++++++++++++++++++ rtl837x_port.h | 1 + rtl837x_regs.h | 4 ++++ 4 files changed, 40 insertions(+) diff --git a/cmd_parser.c b/cmd_parser.c index 55bba78b..024c49cc 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -893,7 +893,10 @@ void parse_port(void) print_string_x(port_names[phy_settings.port]); if (!machine.is_sfp[phy_settings.port]) { phy_show(phy_settings.port); + } else { + write_char('\n'); } + port_media_show(phy_settings.port); } else if (cmd_compare(2, "name")) { uint8_t i = 0; while ( (i < PORT_NAME_SIZE-1) && (cmd_buffer[cmd_words_b[3] + i] != NUL) ) { diff --git a/rtl837x_port.c b/rtl837x_port.c index 0383aae3..1e303c6c 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -487,6 +487,38 @@ void port_l2_setup(void) __banked } +void port_media_show(uint8_t port) __banked +{ + uint8_t pause; + + if (!machine.is_sfp[port]) { + reg_read_m(RTL837X_REG_LINKS_STS); + if (sfr_data[(port / 8) + 1] >> (port % 8) & 1) { + print_string("Link role: "); + reg_read_m(RTL837X_MAC_MSTR_SLV_STS); + if (sfr_data[3 - (port >> 3)] & (1 << (port & 7))) + print_string("master\n"); + else + print_string("slave\n"); + } + } + + print_string("Pause negotiated:"); + reg_read_m(RTL837X_MAC_TX_PAUSE_STS); + pause = sfr_data[3 - (port >> 3)] & (1 << (port & 7)); + if (pause) + print_string(" TX"); + reg_read_m(RTL837X_MAC_RX_PAUSE_STS); + if (sfr_data[3 - (port >> 3)] & (1 << (port & 7))) { + print_string(" RX"); + pause = 1; + } + if (!pause) + print_string(" none"); + write_char('\n'); +} + + void port_stats_print(void) __banked { print_string("\nPort\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\n"); diff --git a/rtl837x_port.h b/rtl837x_port.h index 0325249c..5001c66b 100644 --- a/rtl837x_port.h +++ b/rtl837x_port.h @@ -49,6 +49,7 @@ extern __xdata struct vlan_settings vlan_settings; uint8_t port_l2_forget(void) __banked; void port_l2_learned(void) __banked; void port_stats_print(void) __banked; +void port_media_show(uint8_t port) __banked; int8_t vlan_get(uint16_t vlan) __banked; __xdata uint16_t vlan_name(uint16_t vlan) __banked; void vlan_name_remove(uint16_t vlan) __banked; diff --git a/rtl837x_regs.h b/rtl837x_regs.h index 6154221b..6b48f316 100644 --- a/rtl837x_regs.h +++ b/rtl837x_regs.h @@ -83,6 +83,10 @@ #define RTL837X_REG_LINKS 0x63f0 #define RTL837X_REG_LINKS_89 0x63f4 #define RTL837X_REG_LINKS_STS 0x63E8 +/* Per-port status bits: bit N is chip port N */ +#define RTL837X_MAC_TX_PAUSE_STS 0x63FC +#define RTL837X_MAC_RX_PAUSE_STS 0x6400 +#define RTL837X_MAC_MSTR_SLV_STS 0x6408 /* Each nibble encodes the link state of a port. Port 0 appears to be the CPU port